
PoC Python minimale per CVE-2026-40179: inietta un nome di metrica dannoso tramite remote_write Prometheus non autenticato per attivare una XSS persistente nell'interfaccia web. Non richiede stub protobuf.
remote_writeUna proof of concept minima e con poche dipendenze per CVE-2026-40179 (GHSA-vffh-x6r8-xx99): cross-site scripting persistente nell'interfaccia web di Prometheus, veicolato tramite un endpoint remote_write non autenticato.
Prometheus 3.x visualizza i nomi delle metriche e i valori delle etichette nell'interfaccia web tramite innerHTML senza eseguire l'escaping. Poiché Prometheus v3 ha rilassato la validazione delle etichette per consentire UTF-8 arbitrario — inclusi <, > e " — un nome di metrica può trasportare un payload HTML che viene eseguito quando qualcuno naviga nell'interfaccia.
| Interessate | Prometheus 3.0.0 – 3.5.1 |
| Corretta in | 3.5.2 |
| Impatto | XSS persistente, eseguito nel browser di qualsiasi utente che visualizza la metrica interessata |
| Superfici vulnerabili | Tooltip della pagina Graph, Metrics Explorer |
Lo XSS ha comunque bisogno di un modo per iniettare una serie manipolata nel TSDB. Uno qualsiasi di questi va bene:
remote_write aperto (quello che usa questa PoC),Un Prometheus esposto su internet o sulla LAN senza autenticazione davanti offre tutti questi vettori gratuitamente, ed è ciò che rende questa vulnerabilità concretamente sfruttabile e non solo teorica.
Invia una singola richiesta POST /api/v1/write contenente una serie temporale il cui __name__ è:
pentest_poc_cve_2026_40179
Il WriteRequest protobuf è codificato a mano in ~40 righe, quindi non ci sono dipendenze da protobuf, prometheus_pb2 o promtool — solo python-snappy per la compressione di rete e requests per la POST. Questo lo rende facile da installare su un jump host dove non puoi costruire stub protobuf generati.
python3 -m pip install python-snappy requests
python-snappy richiede la libreria C di Snappy:
# Debian/Ubuntu
sudo apt install libsnappy-dev
# macOS
brew install snappy
python3 cve-2026-40179-poc.py <target_ip>
Lo script presuppone HTTPS sulla porta 9090 con verifica del certificato disabilitata (tipico per un'istanza interna con certificato autofirmato). Se il target è in chiaro HTTP o su un'altra porta, modifica la riga url in main().
Un'iniezione riuscita restituisce HTTP 204:
POST https://192.0.2.10:9090/api/v1/write -> 204
Interroga la serie nell'interfaccia web di Prometheus o tramite API — dovrebbe comparire immediatamente:
{__name__=~"pentest_poc.*"}
La vista Table la visualizza correttamente con l'escaping e mostra il payload come testo semplice. Questo è il comportamento previsto e non è la superficie vulnerabile.
Apri il Metrics Explorer (il browser delle metriche accanto alla casella di interrogazione), cerca pentest_poc e passa il mouse sulla voce elencata.
Nei test sul campo contro la 3.2.1, il percorso Metrics Explorer si è attivato in modo affidabile, mentre il tooltip della scheda Graph non si è riprodotto — il campione iniettato (valore 1.0) non veniva visualizzato sul grafico, e passare il mouse sulla legenda non lo attivava. Entrambe le superfici sono indicate nell'avviso di sicurezza; se una non si attiva sulla tua versione target, prova l'altra prima di concludere che non è vulnerabile.
Il payload predefinito usa console.log() così non disturba chi non lo sta cercando. Per una demo visibile — per esempio uno screenshot per un report — cambia METRIC_NAME per usare alert():
METRIC_NAME = ('pentest_poc_cve_2026_40179'
'')
La serie iniettata è persistente. Una volta scritta, rimane nel TSDB fino alla scadenza della retention. Per rimuoverla serve l'API di amministrazione, che è disabilitata per impostazione predefinita:
# Funziona solo se Prometheus è stato avviato con --web.enable-admin-api
curl -X POST -g 'https://<target>:9090/api/v1/admin/tsdb/delete_series?match[]={__name__=~"pentest_poc.*"}'
curl -X POST 'https://<target>:9090/api/v1/admin/tsdb/clean_tombstones'
Se l'API di amministrazione è disattivata, non esiste una via di pulizia remota. L'unica alternativa è promtool tsdb eseguito localmente sull'host, a cui probabilmente non hai accesso.
Conseguenze pratiche:
job="pentest_poc"), così è facile trovarlo ed è ovviamente un artefatto di test.Per riprodurre la vulnerabilità su un'istanza usa-e-getta piuttosto che su un sistema live:
docker run --rm -p 9090:9090 prom/prometheus:v3.2.1 \
--config.file=/etc/prometheus/prometheus.yml \
--web.enable-remote-write-receiver \
--web.enable-admin-api
Poi punta lo script su 127.0.0.1 (cambia lo schema dell'URL in http:// in main()). Avviando con --web.enable-admin-api puoi effettivamente eliminare la serie in seguito.
--web.config.file con basic_auth_users.--web.enable-remote-write-receiver se non necessario, e non esporlo mai senza autenticazione.Nota che (1) da sola corregge lo XSS, ma un Prometheus non autenticato resta comunque una superficie considerevole di divulgazione di informazioni: l'elenco completo dei nomi delle metriche, l'inventario dei target di scraping e i nomi host interni sono tutti leggibili senza credenziali.
Questo è pubblicato per difensori, ricercatori e tester che operano in regime di autorizzazione. La vulnerabilità è pubblicamente divulgata e corretta a monte.
Eseguire questo script contro un sistema scrive dati persistenti su di esso. Non puntarlo contro infrastrutture che non possiedi o per cui non hai un'autorizzazione scritta esplicita al testing.
MIT — vedi LICENSE.