sábado, 29 de marzo de 2014

[Parte 4] Seguridad en PHP

Sesiones y cookies

HTTP es un protocolo sin estado, es decir, que no guarda informacion sobre conexiones anteriores. El desarrollo de aplicaciones web necesita frecuentemente mantener estado. Para eso se usan las cookies, que es informacion que un servidor puede almacenar en el sistema cliente. Esto les permite a las aplicaciones web instruir la nocion de "sesion", y tambien permite rastrear a usuarios ya que las cookies pueden guardarse en el cliente por tiempo indeterminado.

 Figura que muestra el intercambio de cookies

Como estamos hablando de PHP entonces hablaremos sobre sesion_start() la cual inicia una sesion o reanuda una existente...

session_start() crea una sesion o reanuda la actual basada en un identificador de sesion pasado mediante una peticion GET o POST, o pasado mediante una cookie. 
Cuando session_start() es llamada o cuando se autoinicia una sesion, PHP llamara a los gestores de almacenamiento de sesiones open y read. Estos seran un gestor de almacenamiento proporcionado por omision o por extensiones de PHP (Como SQLite o Memcached); o pueden ser un gestor personalizado como esta definido en session_set_save_handler(). La llamada de retorno read recuperara cualquier informacion de sesion existente (almacenada en un formato serializado especial) y sera deserializada y usada para rellenar automaticamente la variable superglobal $_SESSION cuando la llamada de retorno read devuelva la informacion de sesion guardada a la gestion de sesiones PHP. 



Robo de cookies

Al usar cookies uno de los riesgos que conlleva es que pueden ser robadas por un atacante y llevar a un secuestro de sesion.

Los dos metodos mas famosos para el robo de cookies es alguna vulnerabilidad en el navegador o el cross site scripting (XSS).

Para firefox tenemos disponible el complemento noscript que nos ayuda a ver cual script podria ser un riesgo ejecutar y nos pide permiso si deseamos ejecutarlo o no (aveces puede ser un poco molesto pero es una de las maneras de obtener un poco mas de seguridad ante este tipo de ataques).

Otra manera de evitar este tipo de ataques en el navegador es mantenerlo actualizado, ya que cada cierto tiempo realizan la actualizacion incluyen nuevas funciones y parches para las vulnerabilidades de tal.



Para poder evitar este tipo de ataques a nivel web que seria el cross site scripting (XSS) podemos recurrir a la parte 2 de seguridad en PHP.



Datos de sesion expuestos

Los datos de sesion muchas veces contiene informacion confidencial por lo que es una buena practica implementar SSL.

Secure Sockets Layer (SSL; en español <<capa de conexion segura>>) y su sucesor Transport Layer Security (TLS; en español <<Seguridad de la capa de transporte>>) son protocolos criptograficos que proporcionan comunicaciones seguras por una red, comumente internet.

Uno de los usos mas importantes es junto a HTTP para formar HTTPS es usado para asegurar paginas World Wide Web para aplicaciones de comercio electronico, utilizando certificados de clave publica para verificar la identidad de los externos.

O simplemente podemos usar nuestra propia funcion con session_set_save_handler(), pueden ver un ejemplo en wikihow.


Fijacion de sesion

Una de las preocupaciones de las sesiones es el identificador de sesion, ya que un atacante con un identificador de sesion valido podria secuestrar practicamente la sesion del usuario en si.

Un atacante puede obtener un identificador de sesion valido usando:

* Prediccion de sesion (Conjeturas)
* Capturar la sesion (MITM)
* Fijacion de sesion 


Fijacion de sesion es un ataque que engaña a la victima para el uso de un identificador de sesion elegida por el atacante. Es el metodo mas simple por el cual el atacante puede obtener un identificador de sesion valido.


Un ejemplo muy basico seria el siguiente:



Otro enfoque es realizar una redireccion:



El objetivo del ataque es conseguir que el usuario visite una URL que incluye un identificador de sesion de la eleccion del atacante. 





Antes de seguir quiero comentarles que este tipo de vulnerabilidad esta corregida desde la version 5.5.2: http://unaaldia.hispasec.com/2013/08/solucionada-la-fijacion-de-sesiones-en.html

En caso de que funcionara en su servidor la sesion deberia reanudarse (reemplazar tuhost.com por tu URL):

fixation.php


fixation_echo.php


Primero antes que nada nos aseguramos de que no tengamos cookies para el host actual, ahora visitamos tuhost.com/fixation.php?PHPSESSID=1234

Esto crea una variable de sesion con un valor de arthusu...



El segundo script fixation_echo.php, muestra si el valor $_SESSION['username'] existe. Visitamos la misma la siguiente URL utilizando un navegador o equipo diferente...

tuhost.com/fixation_echo.php?PHPSESSID=1234

Esto hace que se reanude la sesion cuando se visito fixation.php, y el equipo o navegador diferente imitan la posicion del atacante, y con esto la sesion ha sido secuestrada.

Para prevenir este tipo de ataque usamos session_regenerate_id() que lo que hace es actualizar el id de sesion actual con uno mas reciente.



Un ejemplo seria el siguiente:



Esto asegura que siempre que se inicie una nueva sesion el identificador se renueve.
Pero como esto no elimina del todo la vulnerabilidad ya que un atacante puede "capturar" el PHPSESSID que manda PHP y enviarselo a la victima...





Lo mas conveniente seria regenerar el identificador cada vez que haya un cambio en el nivel de privilegio, de esta manera:



En este caso check_login() seria nuestra funcion personalizada...



Secuestro de sesion

Como comentamos anteriormente el secuestro de sesion se puede llevar a cabo por prediccion, capturar y fijar la sesion, y tambien esta por medio de ataques XSS, bueno pero lo importante aqui, es que si te estan "olfateando la red" como te proteges? Hay un ataque conocido como MITM (Man in the middle, es español <<Hombre en el medio>>), lo que realiza este tipo de ataque es infectar las tablas ARP quedando como si fuera un proxy asi todas las peticiones que haga la victima pasaran por el...


Algunas de las prevenciones que podemos agregar seria, registrar el navegador que estamos usando en la sesion actual, de esta manera si alguien llega y nos atrapa la sesion al querer mandarla por las cabeceras HTTP por medio de Google Chrome mientras la persona real esta usando Mozilla Firefox, entonces que muestre un campo donde introduzca su contraseña. 



Pero esto tiene un inconveniente, ya que puede manejar las cabeceras HTTP podemos predecir que se trata del navegador y realizar el ataque es por eso que es mas recomendable usar un token, de esta manera, no sabria realmente como predecirlo...


Si no quisieramos depender del navegador simplemente podemos usar un token aleatorio...



Los tokens se usan para verificar la autenticidad del usuario, de esta manera sabriamos decir si es realmente el o no, esto verificando el token actual...

Y como comentamos anteriormente el uso de SSL podria ayudarnos en el momento de que nos esten "olfateando la red", aunque no es tan seguro como se dice ser pero sirve de mucho, y como vemos siempre es bueno tener un "safeguard" por si no funciona uno como en este caso SSL, tenemos los tokens con los cuales no pueden pasar, el objetivo es "hacerle la vida dificil" al atacante...

Referencias:

* Essential PHP Security
* OWASP
* Wikipedia
* PHP.net
* hispaSEC




1 comentario: