
स्थानीय Docker प्रयोगशाला जो CtrlPanel वेब इंस्टॉलर में CVE-2026-34234 अप्रमाणित RCE का प्रदर्शन करती है। इसमें कमजोर और पैच किए गए कंटेनर, PoC स्क्रिप्ट और सुरक्षा अनुसंधान एवं रक्षात्मक सत्यापन के लिए मूल कारण विश्लेषण शामिल हैं।
CtrlPanel में CVE-2026-34234 प्रदर्शित करने के लिए स्थानीय Docker लैब।
यह रिपॉजिटरी तुलना करता है:
vuln: डाइजेस्ट द्वारा पिन किया गया CtrlPanel 1.1.1patched: डाइजेस्ट द्वारा पिन किया गया CtrlPanel 1.2.0लैब केवल स्थानीय है और सेवाओं को 127.0.0.1 से बांधता है।
CVE-2026-34234, CtrlPanel के वेब इंस्टॉलर में एक अनप्रमाणित RCE है।
यह समस्या दो बगों के श्रृंखलाबद्ध होने के कारण होती है:
install.lock गेट से पहले इंस्टॉलर फॉर्म हैंडलर सुलभ थे।इस लैब में, कमजोर कंटेनर एक हानिरहित प्रूफ कमांड निष्पादित करता है और अपना आउटपुट कंटेनर के अंदर लिखता है। पैच किए गए कंटेनर को समान अनुरोध प्राप्त होता है लेकिन प्रूफ फ़ाइल नहीं बनाता है।
अपेक्षित परिणाम:
vulnerable => proof file created
patched => no proof file
1.1.1 में कमजोर शेल निष्पादनमूल कमजोर फ़ाइल:
public/installer/src/functions/shell.php
1.1.1 में प्रासंगिक अपस्ट्रीम कोड:
function run_console(string $command, ...) {
$path = dirname(__DIR__, 4);
$handle = proc_open("cd '$path' && bash -c 'exec -a ServerCPP $command'", ...);
}
समस्या:
run_console() एक शेल कमांड स्ट्रिंग स्वीकार करता है।bash -c में पास की जाती है।मूल कमजोर फ़ाइल:
public/installer/src/forms/pterodactyl.php
1.1.1 में प्रासंगिक अपस्ट्रीम व्यवहार:
run_console("php artisan settings:set 'PterodactylSettings' 'panel_url' '$url'", ...);
run_console("php artisan settings:set 'PterodactylSettings' 'admin_token' '$key'", ...);
run_console("php artisan settings:set 'PterodactylSettings' 'user_token' '$clientkey'", ...);
समस्या:
url, key, और clientkey इंस्टॉलर POST डेटा से उत्पन्न होते हैं।सलाह में कहा गया है कि public/installer/index.php ने इंस्टॉलर फॉर्म लॉजिक को लोड/निष्पादित करने के बाद ही install.lock की जाँच की। इसने इंस्टॉलर हैंडलर को पहले से स्थापित इंस्टेंस पर भी सुलभ बना दिया।
फिक्स install.lock जांच को फॉर्म हैंडलर लोड होने से पहले स्थानांतरित करता है।
पैच किया गया व्यवहार:
if (file_exists('../../install.lock')) {
exit("The installation has been completed already. Please delete the File 'install.lock' to re-run");
}
मूल पैच फ़ाइल:
public/installer/src/functions/shell.php
1.2.0 में प्रासंगिक अपस्ट्रीम कोड:
function run_console(array $command, ...): string {
$cwd = $cwd ?? $path;
$handle = proc_open($command, $descriptors, $pipes, $cwd, null, $options);
}
यह समस्या को क्यों ठीक करता है:
run_console() अब argv-शैली सरणी स्वीकार करता है।$() जैसा पेलोड सिंटैक्स शेल सिंटैक्स के बजाय शाब्दिक इनपुट बना रहता है।1.2.0 में पैच किया गया फॉर्म व्यवहार array-शैली कमांड निष्पादन का उपयोग करता है:
run_console(['php', 'artisan', 'settings:set', 'PterodactylSettings', 'panel_url', $url], ...);
run_console(['php', 'artisan', 'settings:set', 'PterodactylSettings', 'admin_token', $key], ...);
run_console(['php', 'artisan', 'settings:set', 'PterodactylSettings', 'user_token', $clientkey], ...);
127.0.0.1:8081 -> vulnerable CtrlPanel 1.1.1
127.0.0.1:8082 -> patched CtrlPanel 1.2.0
127.0.0.1:9100 -> fake Pterodactyl API
सेवाएं:
vuln: वास्तविक CtrlPanel 1.1.1patched: वास्तविक CtrlPanel 1.2.0fake-api: केवल इंस्टॉलर जांच को संतुष्ट करने के लिए उपयोग किया जाने वाला स्थानीय नकली Pterodactyl APImysql_vuln / mysql_patched: अलग-अलग MariaDB इंस्टेंसredis_vuln / redis_patched: अलग-अलग Redis इंस्टेंसलैब CtrlPanel एप्लिकेशन स्रोत कोड को संशोधित नहीं करता है।
Dockerfiles केवल मूल कंटेनर एंट्रीपॉइंट को लपेटते हैं ताकि निम्नलिखित के लिए Docker Desktop रनटाइम अनुमतियों को सामान्य किया जा सके:
/var/www/html/storage
/var/www/html/bootstrap/cache
अनुमतियाँ ठीक करने के बाद, रैपर मूल उत्पाद एंट्रीपॉइंट निष्पादित करता है।
प्राथमिक PoC:
poc/poc_http_only.py
गुण:
docker exec का उपयोग नहीं करता हैid, whoami, hostnameसहायक स्क्रिप्ट:
poc/poc_lab.py
उद्देश्य:
docker compose exec का उपयोग करके कंटेनरों के अंदर प्रूफ सत्यापित करता हैएप कंटेनर के अंदर प्रूफ फ़ाइल:
/var/www/html/storage/logs/cve_2026_34234_proof.txt
स्वच्छ लैब स्थिति से शुरू करें:
docker compose down -v --remove-orphans
docker compose up -d --build
एप कंटेनरों के ऊपर आने तक प्रतीक्षा करें, फिर चलाएं:
python3 poc/poc_lab.py
अपेक्षित आउटपुट:
== Testing vulnerable ==
proof_exists: True
result: PASS expected_proof=True
== Testing patched ==
proof_exists: False
result: PASS expected_proof=False
[+] Expected result reached:
vulnerable => proof file created
patched => no proof file
कमजोर लक्ष्य पर HTTP-केवल PoC भेजें:
python3 poc/poc_http_only.py --target http://127.0.0.1:8081
प्रूफ मैन्युअल रूप से सत्यापित करें:
docker compose exec vuln sh -lc 'cat /var/www/html/storage/logs/cve_2026_34234_proof.txt'
अपेक्षित प्रूफ:
uid=1000(laravel) gid=1000(laravel) groups=1000(laravel)
laravel
<container-hostname>
पैच किए गए के विरुद्ध समान अनुरोध चलाएं:
python3 poc/poc_http_only.py --target http://127.0.0.1:8082
पैच किए गए व्यवहार को सत्यापित करें:
docker compose exec patched sh -lc 'test -f /var/www/html/storage/logs/cve_2026_34234_proof.txt && cat /var/www/html/storage/logs/cve_2026_34234_proof.txt || echo "no proof file"'
अपेक्षित:
no proof file
कंटेनर, नेटवर्क और लैब वॉल्यूम हटाएं:
docker compose down -v
यह रिपॉजिटरी केवल शैक्षिक सुरक्षा अनुसंधान और रक्षात्मक सत्यापन के लिए प्रदान की गई है।
सभी प्रदर्शन प्रदान किए गए स्थानीय Docker लैब वातावरण में चलाने के लिए अभिप्रेत हैं। प्रूफ-ऑफ-कॉन्सेप्ट विनाशकारी कार्यों, स्थिरता, क्रेडेंशियल चोरी, डेटा बाहर निकालने और वास्तविक दुनिया के लक्ष्यीकरण से बचता है।
इस प्रोजेक्ट का उपयोग स्पष्ट प्राधिकरण के बिना किसी भी सिस्टम के विरुद्ध न करें। लेखक इस सामग्री से उत्पन्न दुरुपयोग या क्षति के लिए जिम्मेदार नहीं है।