
CVE-2026-40179 के लिए न्यूनतम Python PoC: बिना प्रमाणीकरण के Prometheus remote_write के माध्यम से एक दुर्भावनापूर्ण मीट्रिक नाम इंजेक्ट करके वेब UI में संग्रहीत XSS ट्रिगर करता है। किसी protobuf स्टब की आवश्यकता नहीं है।
remote_write के माध्यम से संग्रहीत XSSCVE-2026-40179 (GHSA-vffh-x6r8-xx99) के लिए एक न्यूनतम, न्यूनतम-निर्भरता वाला प्रूफ ऑफ कॉन्सेप्ट: Prometheus वेब UI में संग्रहीत क्रॉस-साइट स्क्रिप्टिंग, जो एक अप्रमाणित remote_write एंडपॉइंट के माध्यम से पहुंचाई जाती है।
Prometheus 3.x मीट्रिक नामों और लेबल मानों को innerHTML के माध्यम से बिना एस्केप किए वेब UI में रेंडर करता है। चूँकि Prometheus v3 ने लेबल सत्यापन को शिथिल कर दिया है ताकि मनमाना UTF-8 — जिसमें <, >, और " शामिल हैं — की अनुमति हो, एक मीट्रिक नाम HTML पेलोड ले जा सकता है जो किसी के UI ब्राउज़ करते समय निष्पादित हो जाता है।
| प्रभावित | Prometheus 3.0.0 – 3.5.1 |
| फिक्स संस्करण | 3.5.2 |
| प्रभाव | संग्रहीत XSS, प्रभावित मीट्रिक देखने वाले किसी भी उपयोगकर्ता के ब्राउज़र में निष्पादित होता है |
| कमज़ोर सतहें | ग्राफ़ पेज टूलटिप्स, मेट्रिक्स एक्सप्लोरर |
XSS को स्वयं TSDB में एक तैयार की गई सीरीज़ डालने का रास्ता चाहिए। इनमें से कोई भी काम करेगा:
remote_write एंडपॉइंट (जो इस PoC में उपयोग होता है),इंटरनेट या LAN पर खुला Prometheus, जिसके सामने कोई प्रमाणीकरण नहीं है, उपरोक्त सभी को मुफ्त में देता है, और यही इसे सैद्धांतिक नहीं बल्कि व्यावहारिक रूप से शोषण योग्य बनाता है।
एकल POST /api/v1/write भेजता है जिसमें एक टाइम सीरीज़ होती है जिसका __name__ है:
pentest_poc_cve_2026_40179
प्रोटोबफ WriteRequest को ~40 पंक्तियों में हाथ से एन्कोड किया गया है, इसलिए कोई protobuf, prometheus_pb2, या promtool निर्भरता नहीं है — केवल वायर कम्प्रेशन के लिए python-snappy और POST के लिए requests। इससे इसे ऐसे जंप होस्ट पर डालना आसान हो जाता है जहाँ आप जनरेट किए गए प्रोटोबफ स्टब्स नहीं बना सकते।
python3 -m pip install python-snappy requests
python-snappy को Snappy C लाइब्रेरी की आवश्यकता होती है:
# Debian/Ubuntu
sudo apt install libsnappy-dev
# macOS
brew install snappy
python3 cve-2026-40179-poc.py <target_ip>
स्क्रिप्ट पोर्ट 9090 पर HTTPS मानती है तथा सर्टिफिकेट सत्यापन अक्षम होता है (यह self-signed सर्टिफिकेट वाले आंतरिक इंस्टेंस के लिए सामान्य है)। यदि आपका टारगेट सादा HTTP है या किसी अन्य पोर्ट पर है, तो main() में url लाइन संपादित करें।
एक सफल इंजेक्शन HTTP 204 लौटाता है:
POST https://192.0.2.10:9090/api/v1/write -> 204
Prometheus UI या API में सीरीज़ क्वेरी करें — इसे तुरंत परिणाम देना चाहिए:
{__name__=~"pentest_poc.*"}
टेबल व्यू इसे सही ढंग से एस्केप करता है और पेलोड को सादे टेक्स्ट के रूप में दिखाता है। यह अपेक्षित है और यह कमज़ोर सतह नहीं है।
मेट्रिक्स एक्सप्लोरर खोलें (क्वेरी बॉक्स के बगल में मौजूद मेट्रिक ब्राउज़र), pentest_poc खोजें, और सूचीबद्ध एंट्री पर होवर करें।
3.2.1 के विरुद्ध फ़ील्ड परीक्षण में, मेट्रिक्स एक्सप्लोरर पथ विश्वसनीय रूप से ट्रिगर हुआ, जबकि ग्राफ़ टैब टूलटिप रिप्रोड्यूस नहीं हुई — इंजेक्ट किया गया सैंपल (मान 1.0) प्लॉट किए गए चार्ट पर दृश्य रूप से रेंडर नहीं हुआ था, और लीजेंड पर होवर करने से भी यह ट्रिगर नहीं हुआ। दोनों सतहों का नाम एडवाइज़री में दिया गया है; यदि आपके टारगेट वर्शन पर एक ट्रिगर नहीं होता है, तो यह निष्कर्ष निकालने से पहले कि यह कमज़ोर नहीं है, दूसरे को आज़माएँ।
डिफ़ॉल्ट पेलोड console.log() का उपयोग करता है ताकि यह उसे बाधित न करे जो इसकी तलाश में नहीं है। एक दृश्यमान डेमो के लिए — उदाहरण के लिए, रिपोर्ट के लिए स्क्रीनशॉट — alert() उपयोग करने के लिए METRIC_NAME बदलें:
METRIC_NAME = ('pentest_poc_cve_2026_40179'
'')
इंजेक्ट की गई सीरीज़ स्थायी होती है। एक बार लिखे जाने के बाद, यह तब तक TSDB में बनी रहती है जब तक रिटेंशन इसे समाप्त नहीं कर देता। इसे हटाने के लिए एडमिन API की आवश्यकता होती है, जो डिफ़ॉल्ट रूप से अक्षम है:
# Only works if Prometheus was started with --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'
यदि एडमिन API बंद है, तो कोई रिमोट क्लीनअप मार्ग नहीं है। एकमात्र विकल्प promtool tsdb को होस्ट पर स्थानीय रूप से चलाना है, जिस तक आपकी शायद पहुँच नहीं है।
व्यावहारिक परिणाम:
job="pentest_poc") वाला होता है, ताकि इसे ढूँढना आसान हो और यह स्पष्ट रूप से एक परीक्षण आर्टिफैक्ट हो।किसी भी लाइव सिस्टम के बजाय एक अस्थायी (disposable) इंस्टेंस पर रिप्रोड्यूस करने के लिए:
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
फिर स्क्रिप्ट को 127.0.0.1 पर इंगित करें (main() में URL स्कीम को http:// में बदलें)। --web.enable-admin-api के साथ शुरू करने का मतलब है कि आप बाद में सीरीज़ को वास्तव में हटा सकते हैं।
basic_auth_users के साथ --web.config.file।--web.enable-remote-write-receiver को तब तक सक्षम न करें जब तक आपको इसकी आवश्यकता न हो, और इसे कभी भी बिना प्रमाणीकरण के एक्सपोज़ न करें।ध्यान दें कि अकेले (1) XSS को ठीक करता है, लेकिन एक अप्रमाणित Prometheus अपने आप में एक महत्वपूर्ण सूचना-प्रकटीकरण सतह बना रहता है: पूरी मीट्रिक नाम सूची, स्क्रेप टारगेट इन्वेंट्री और आंतरिक होस्टनाम सभी बिना क्रेडेंशियल के पढ़े जा सकते हैं।
यह अधिकार के तहत काम करने वाले डिफेंडरों, शोधकर्ताओं और परीक्षकों के लिए प्रकाशित किया गया है। यह भेद्यता सार्वजनिक रूप से प्रकट की जा चुकी है और अपस्ट्रीम में पैच की जा चुकी है।
इसे किसी सिस्टम के विरुद्ध चलाने से उस पर स्थायी डेटा लिखा जाता है। इसे उस इंफ्रास्ट्रक्चर पर न चलाएं जिसके मालिक आप नहीं हैं या जिसके परीक्षण की स्पष्ट लिखित अनुमति आपके पास नहीं है।
MIT — LICENSE देखें।