Grafana è una piattaforma open-source molto utilizzata per l’analisi e il monitoraggio. La vulnerabilità CVE-2021-43798 consente ad attori malintenzionati non autenticati di leggere file arbitrari dal file system del server, sfruttando una debolezza nel modo in cui vengono gestiti i percorsi dei plugin. Tale vulnerabilità è stata attivamente sfruttata ed è ora elencata nel catalogo CISA delle vulnerabilità conosciute sfruttate. È fondamentale applicare immediatamente le patch disponibili.
| Prodotto | Grafana, Grafana |
| Data | 2025-10-10 13:14:42 |
Riassunto tecnico
La vulnerabilità era presente nella funzione getPluginAssets all’interno del file pkg/api/plugins.go. Il codice originale non effettuava alcuna validazione sul percorso del file richiesto, ma prendeva semplicemente il parametro URL e lo utilizzava per costruire un percorso del file:
func (hs *HTTPServer) getPluginAssets(c *models.ReqContext) {
pluginID := web.Params(c.Req)[":pluginId"]
...........................
requestedFile := filepath.Clean(web.Params(c.Req)["*"])
pluginFilePath := filepath.Join(plugin.PluginDir, requestedFile)
...........................
f, err := os.Open(pluginFilePath)
...........................
}
Il codice prendeva il percorso wild-card fornito dall’utente (web.Params(c.Req)["*"]) ed eseguiva un filepath.Clean direttamente su di esso, poi filepath.Join(plugin.PluginDir, requestedFile). Questo permetteva a segmenti di tipo ..%2f..%2f..%2f..%2fetc/passwd di “uscire” dalla directory del plugin dopo l’unione dei percorsi.
La correzione è ora la seguente:
func (hs *HTTPServer) getPluginAssets(c *models.ReqContext) {
pluginID := web.Params(c.Req)[":pluginId"]
plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), pluginID)
if (!exists) {
c.JsonApiErr(404, "Plugin not found", nil)
return
}
// prepend slash for cleaning relative paths
requestedFile := filepath.Clean(filepath.Join("/", web.Params(c.Req)["*"]))
rel, err := filepath.Rel("/", requestedFile)
if (err != nil) {
// slash is prepended above therefore this is not expected to fail
c.JsonApiErr(500, "Failed to get the relative path", err)
return
}
if !plugin.IncludedInSignature(rel) {
hs.log.Warn("Access to requested plugin file will be forbidden in upcoming Grafana versions as the file "+
"is not included in the plugin signature", "file", requestedFile)
}
absPluginDir, err := filepath.Abs(plugin.PluginDir)
if (err != nil) {
c.JsonApiErr(500, "Failed to get plugin absolute path", nil)
return
}
pluginFilePath := filepath.Join(absPluginDir, rel)
f, err := os.Open(pluginFilePath)
...........................
}
Raccomandazioni
-
Applicare immediatamente la patch: Eseguire l’aggiornamento di tutte le istanze di Grafana comprese tra le versioni v8.0.0-beta1 e v8.3.0 alla versione più recente.
-
Reverse proxy: Se non è possibile aggiornare, utilizzare un reverse proxy davanti a Grafana che normalizzi il PATH della richiesta per mitigare la vulnerabilità.
-
Monitoraggio e analisi: Eseguire un audit degli accessi e rivedere le richieste all’endpoint
/public/plugins/alla ricerca di anomalie. -
Difesa in profondità: Utilizzare Web Application Firewall (WAF) configurati per bloccare i tentativi di traversal di percorso come ulteriore strato di protezione.