Está en la página 1de 10

Manejo de sesiones en php

Nota: Lamentablemente algunos ejemplos de este artculo se vern momentneamente rotos, pues el plugin de hilite de sintxis de wordpress no funciona muy bien, y omite el cdigo que est escrito dentro de bloques de cdigo de php. En cuanto arregle el plugin o salga un fix se vern los ejemplos al 100% nuevamente. Si alguien conoce una solucin por supuesto se agradecer el dato.

Introduccin
En este artculo vamos a explicar el manejo de sesiones en PHP, su utilidad, las funciones y las directivas de configuracin implicadas en el manejo de sesiones.

Qu son las sesiones?


Primero que nada, qu son las sesiones de PHP? Las sesiones son una facilidad que permite vincular informacin a un visitante a lo largo de sus diversos accesos a nuestro sitio web. Un visitante puede acceder a varias pginas de nuestro sitio, las sesiones nos ayudan a identificarlo y a vincularle informacin. Algunos usos tpicos de las sesiones son: Mejorar la experiencia del usuario almacenando informacin de preferencias como colores o elementos de navegacin preferidos. Almacenar informacin de estado (ej: si el usuario est logeado o no). En el caso de una aplicacin de comercio electrnico llevar registro de los productos que ha agregado a su carro de compras, o de productos que ha comprado anteriormente para establecer sus preferencias. Estos son solo unos ejemplos pero las posibilidades son infinitas. En general, cuando querramos almacenar informacin en relacin a un visitante de forma persistente a lo largo de su visita las sesiones nos facilitarn la vida.

Cmo funcionan las sesiones en PHP?


Podramos imaginarnos a la sesin como un nmero estampado en la frente del visitante que nos ayuda a identificarlo en cada pgina que visite de nuestro sitio. Adems para cada cada nmero asignado a un visitante habr un locker donde guardar sus cosas. As es que quien est a la entrada (nuestro cdigo de manejo de sesiones) al llegar un visitante escoge un nmero para l y se lo estampa en la frente para que lo utiliice durante su visita. Para poner a funcionar una sesin se necesitan cumplir dos requisitos fundamentales: 1. Asignar al visitante un identificador nico (escoger un nmero).

2. Propagar este identificador nico a travs de los diferentes accesos del visitante para que podamos reconocerlo (estamprselo en la frente). Nuestro identificador nico es una cadena nica aleatoria con la que marcamos al visitante. Llamaremos a este identificador nico session_id. No tendremos que preocuparnos por generar el session_id pues el sistema de sesin se encarga automticamente de generarlo. Ahora, dado que el session_id es generado del lado del servidor, hay que encontrar alguna forma de que esa informacin persista a travs de los diferentes accesos del mismo visitante. No es posible vincular el session_id con la direccin IP del usuario ya que hay varios casos en que la misma IP puede ser utilizada por varios usuarios, por ejemplo cuando varios usuarios estn tras un proxy o tras un router que est haciendo IP masquerade. Por lo tanto para que el session_id est disponible junto a cada solicitud de pgina del usuario es necesario propagar el session_id para que est presente junto al visitante en cada acceso y as podamos identificarlo. Esto se llama propagacin de la sesin y ms adelante veremos cmo se hace.

Creando una sesin


Cada sesin comienza con la funcin session_start(), de la forma: bool session_start(void) session_start() siempre devuelve true. En caso de que el visitante no tenga una sesin la crea y en el caso de que ya la tenga la contina. Si ya tena una sesin tiene que haber una forma de que podamos vincularla al usuario. Para ello el session_id tiene que haber sido pasado a la pgina actual, y esto se hace por cookie, por GET o por POST. Ten en cuenta que si la propagacin es por cookie session_start() se encargar de crear un cookie, entonces es necesario llamarla antes de enviar cualquier cabecera HTTP, esto es antes de comenzar a imprimir nuestra pgina pues sino habr un error al tratar de crear el cookie. Una vez iniciada la sesin podremos almacenar informacin de la sesin en el array $_SESSION ( o $HTTP_SESSION_VARS en versiones anteriores a PHP 4.0.6). Este es una array asociativo, adems es superglobal lo que quiere decir que su alcance se extiende a todo el mbito de la aplicacin y no tendrs que declararlo como global al utilizarlo dentro de funciones. Hagamos un ejemplo. Supongamos que tenemos en lnea una pgina con la foto de George la cacata con el siguiente cdigo: Ejemplo 1 (george_la_cacatua.php) PLAIN TEXT PHP: 1. <h1>sts en la pgina de George la cacata</h1> 2. <img title="George la cacata" src="http://localhost/blog/wordpress/cacatua.jpg" />

<a href="http://localhost/blog/wordpress/pagina2.php">Vis ita la siguiente pgina</a> session_start() comienza la sesin si no la hay, o contina con la sesin del visitante si esta ya exista; la siguiente sentencia se encarga de guardar en la posicin "actividad" del array asociativo de la sesin la cadena: "He visto a George la cacata!". Esta informacin estar disponible an cuando el visitante acceda otras pginas de nuestro sitio, y esta es la magia de las sesiones. Podemos hacer sobre el array $_SESSION cualquier operacin que podemos hacer sobre una un array. Esto nos d una interfaz muy intuitiva y familiar para operar con la informacin de la sesin del usuario. Operacin Ejemplo Crear un elemento $_SESSION['elemento'] = valor Eliminar un elemento unset($_SESSION['elemento']) elemento ha sido creado isset($_SESSION['elemento']) Vaciar la sesin $_SESSION = array(); Existe como alternativa al uso directo del array $_SESSION el uso de las funciones session_register(), session_unregister(), session_is_registered() y session_unset() para operar sobre la informacin de la sesin. Sin embargo, existen varios problemas en su uso que pueden hacernos introducir fallos. session_register() registra variables globales por lo que nos tendremos que cuidar en el alcance de las variables que registremos. Estas funciones solo trabajan cuando la directiva register_globals de nuestro php.ini est activada, cosa que no es nada recomendable por motivos de seguridad, y por lo mismo desde PHP 4.2.0 en adelante el valor por defecto de register_globals es off. As que no es nada recomendable utilizar estas funciones, pero si vas por ellas de todas formas o tienes un cdigo que ya las utiliza abundantemente ten en cuenta que no se deben utilizar el mtodo de acceso directo al array $_SESSION y las funciones al mismo tiempo, se debe utilizar uno o el otro. Sigamos pensando en nuestro ejemplo. Ahora, al visitar la pgina de George la cacata nuestro visitante hace click en el enlace a pagina2.php, el cdigo de esta pgina es as: Ejemplo 2 (pagina2.php) PLAIN TEXT PHP: 1. De nuevo session_start() crea o contina la sesin, como nuestro visitante ya tiene una sesin la contina, cargando sus datos en el array $_SESSION. Entonces por arte de magia la sentencia con el echo imprimir: He visto a George la cacata!

Cmo ha llegado el valor de $_SESSION['actividad'] hasta esta pgina? Ha llegado por la sesin del visitante. Los valores almacenados en la sesin son serializados en un archivo al cerrar cada script y al continuar la sesin en otra pgina son cargados en el array $_SESSION. El archivo de la sesin suele estar en el directorio /tmp en los sistemas UNIX o en c:\tmp en windows y tiene por nombre el session_id del visitante. Podemos configurar dnde queremos serializar las sesiones con la directiva session.save_path de nuestro php.ini o en tiempo de ejecucin mediante la funcin session_save_path() de esta forma: string session_save_path(string); Si llamamos a session_save_path() sin parmetros nos devuelve el save_path actual, si le pasamos una cadena la toma como el nuevo save_path. Si vas a modificar el save_path con esta funcin tienes que llamarla antes de llamar a session_start(). Ahora Cmo llega el llamado a session_start() en pagina2.php a conocer que el visitante ya tiene una sesin y continuarla? La nica forma que tiene de hacerlo es que le proporcionemos de alguna forma el session_id del visitante, esto es lo que se logra por la propagacin del session_id y vamos a explicar en datalle a continuacin.

Propagacin del session_id


Hay dos formas de propagar el session_id: 1. Propagacin por URL 2. Propagacin por cookie

Propagacin por URL


La propagacin del session_id por URL implica escribir el session_id en el query string de cada enlace interno de nuestro sitio. Un enlace con un session_id podri verse de la siguiente forma: PLAIN TEXT PHP: 1. <a href="http://localhost/blog/wordpress/pagina2.php?PHPS ESSID=F513fad624vDx3">Visita la siguiente pgina</a> Donde la variable PHPSESSID del query string se est encargando de pasar el session_id para la sesin del visitante a la pgina pagina2.php. El nombre de la variable que porta el session_id es igual al nombre de la sesin, y puede definirse con la directiva session.name de nuestro php.ini o en tiempo de corrida por la funcin session_name().

Para hacer ms fcil la escritura del session_id en cada URL est disponible la constante SID que contiene la cadena "nombre_de_sesion=session_id", que en nuestro caso sera "PHPSESSID= F513fad624vDx3". Cmo quedara nuestro ejemplo de George la cacata si propagramos el session_id por URL? Aqu est nuestra segunda versin de la pgina: Ejemplo 3 (george_la_cacatua_reloaded.php) PLAIN TEXT PHP: 1.

Ests en la pgina de George la cacata


Visita la siguiente pgina [/php]Nota que en el enlace a pagina2.php hemos embebido un echo de la constante SID, por lo que nuestro enlace se vera as: PLAIN TEXT PHP: 1. <a href="http://localhost/blog/wordpress/pagina2.php?PHPS ESSID=F513fad624vDx3">Visita la siguiente pgina</a>

Propagacin automtica del session_id en cada URL


Por suerte y para hacerlo ms fcil PHP puede encargarse de transformar por nosotros todos los enlaces internos de nuestro sitio para que incluyan el session_id. Esto depende de dos cosas, de que php est compilado para hacerlo (con soporte para trans_sid) y de que la directiva session.use_trans_sid en nuestro php.ini est activada (valor igual a "1"). PHP 4.2.0 viene compilado por defecto con esta funcionalidad, si utilizamos de PHP 4.1.2 para atrs tendremos que recompilar PHP pasando el parmetro --enabletrans-sid al script configure antes de la compilacin (en UNIX). Por motivos de seguridad la directiva session.use_trans_sid viene con el valor "0" por defecto, de modo que para habilitarla deberemos editar nuestro php.ini o utilizar la funcin ini_set(). ini_set("session.use_trans_sid", "1");Si la directiva est habilitada y PHP ha sido compilado con soporte para trans_id entonces un enlace escrito de la siguiente forma en nuestra pgina: PLAIN TEXT PHP:

1. <a href="http://localhost/blog/wordpress/pagina2.php">Vis ita la siguiente pgina</a> ser transformado automticamente por PHP en el siguiente enlace: PLAIN TEXT PHP: 1. <a href="http://localhost/blog/wordpress/pagina2.php?PHPS ESSID=%20F513fad624vDx3">Visita la siguiente pgina</a> propagando por nosotros el session_id en cada URL.

Propagacin por cookie


Cmo funciona la propagacin por cookie? De estar habilitada la propagacin por cookie session_start() buscar en un cookie el session_id del visitante, si no lo encuentra crear una nueva sesin, crear un cookie para la sesin y almacenar en el el session_id del visitante. En un prximo llamado de session_start(), la funcin leer el cookie que contiene el session_id y podr continuar la sesin correspondiente. Como vemos session_start() se encarga de crear y leer el cookie, as que el proceso es automtico y no tendramos que preocuparnos por l. En nuestro Ejemplo 1 y Ejemplo 2, de George la cacata y la pagina2.php, asumimos que el session_id se propaga desde la primer pgina a la segunda por cookie. De no haber estado habilitada la propagacin por cookies en pagina2.php no se hubiera continuado la sesin del visitante pues tampoco estbamos haciendo propagacin del session_id por URL. La sesin hubiera quedado desvinculada del visitante y el echo $_SESSION['actividad']; no hubiera mostrado nada. Como en el caso de la propagacin por URL, el nombre del cookie que contiene el session_id es el mismo que el nombre de la sesin. Por defecto es PHPSESSID pero podemos modificarlo con la directiva session.name de nuestro php.ini o con la funcin session_name(). La propagacin por cookie estar habilitada segn el valor de la directiva session.use_cookie en nuestro php.ini. El valor por defecto es "1" o sea que est activa. Si queremos desactivar la propagacin del session_id por cookie debemos cambiar session.use_cookie a "0" en nuestro php.ini, o si no tenemos acceso al php.ini o queremos cambiarla en tiempo de corrida a nivel de aplicacin, podemos hacerlo mediante la funcin ini_set() de la siguiente forma: ini_set("session.use_cookie", "0");

Cerrando una sesin

Hasta ahora hemos visto como abrir o continuar una sesin con session_start(), cmo registrar valores en la sesin haciendo asignaciones sobre el array $_SESSION, y cmo propagar el session_id por cookies o por URL; ahora veremos como cerrar una sesin. Para cerrar una sesin y terminarla completamente tenemos la funcin session_destroy(). Esta funcin se encarga de hacer desaparecer la sesin de nuestro servidor, (elimina el archivo de /tmp o de nuestro session.save_path). Si se solicita una pgina y se le enva el session_id de una sesin destruda session_start() reportar un error pues la sesin no existe. session_destroy() no elimina las posibles variables globales creadas con la sesin (correspondientes a cada posicin de $_SESSION si tenamos activado register_globals) ni vaca el array $_SESSION. Por supuesto que esto ocurrir al cerrar el script, pero si queremos asegurarnos de que la sesin muera al instante que hacemos el session_destroy() tendremos que encargarnos de vaciar la sesin nosotros mismos. As es que una destruccin tpica de sesin se vera as: Ejemplo 4 (destruyendo una sesin) PLAIN TEXT PHP: 1.

Sesiones Vs. cookies?


No es una comparativa que sea necesaria llevar a cabo. Son herramientas diferentes y muchas veces complementarias. Pero si conoces el uso de los cookies posiblemente te hayas planteado que las sesiones te permiten hacer exactamente lo mismo que los cookies. Pues bien, te mencionamos al menos dos cosas que no puedes lograr con cookies para que veas la diferencia: No depender del uso de cookies. Bastante obvio, si utilizas cookies dependes de ellos. Por qu querra alguien no depender de cookies? Porque por principio de diseo no es bueno depender de ellos en el caso de funcionalidades medulares de nuestra aplicacin web. Por qu? Por el simple hecho de que muchos usuarios pueden no aceptar los cookies, o no aceptar todos los cookies que les enviamos. Si utilizas sesiones puedes no depender del uso de cookies propagando las sesiones por URL. Mantener la informacin fuera del alcance del cliente. Muchas veces la informacin que quieres almacenar sobre el visitante no debera ser accedida por l, por ejemplo informacin administrativa o informacin de estado de un usuario (est logueado?). No hay forma de lograr esto con cookies pues los cookies estn al alcance del visitante, se almacenan en el cliente y pueden ser modificados por l. En el caso de las sesiones no es as pues la informacin de cada sesin se almacena en el servidor fuera del alcance del visitante.

Consideraciones de seguridad en el manejo de sesiones


En la propagacin del session_id

En la propagaccin del session_id es donde encontramos el punto en el que ms cuidado tendremos que tener al manejar sesiones. Vamos a discutir dnde se encuentran las posibles brechas al sistema y algunas medidas defensivas que podemos tomar. En todos los casos mencionaremos las brechas conocidas, aunque la posibilidad de que alguien las explote sea tan pequea que parezca ridculo mencionarlas. La relevencia de cada una de ellas la juzgaremos segn el sistema que estemos desarrollando.

Brechas de seguridad en la propagacin del session_id por URL


Como hemos dicho anteriormente en este mtodo el session_id se pasa de una pgina a otra de nuestra aplicacin web incluyndolo como una variable en el query string de cada URL. Una URL con session_id podra verse as: PLAIN TEXT PHP: 1. http://www.example.com/index.php?PHPSESSID=A86fad765xv c De modo que con tan solo conocer uno de los URLs de nuestro sitio que el usuario legtimo est visitando un atacante podra tomar su papel ante nuestro sistema. El mtodo de realizar el ataque es muy sencillo, pues solo se tiene que acceder a nuestro sitio con un URL que incluya la variable PHPSESSID con el valor substrado. Por ejemplo: PLAIN TEXT PHP: 1. http://www.example.com/account.php?PHPSESSID=A86fad765 xvc As que la brecha de este sistema de propagacin del session_id se presenta en cualquier situacin en la que el URL pueda llegar a ser descubierto. Planteemos algunos escenarios en los que esto puede suceder: 1) Enlaces a pginas externas.Si tenemos enlaces a pginas externas hemos de cuidarnos de no imprimir el sesion_id en ellos. Si estamos utilizando la transformacin de URLs de PHP para que inserte el session_id por nosotros no nos enfrentaremos a este riesgo, pues PHP solo reescribe con el session_id las URLs relativas, dejando intactas las URLs absolutas que son usualmente las que llevan a otros sitios.El riesgo que se corre al pasar el session_id a un sitio externo es que un webmaster malintencionado capte ese session_id y lo utilice. As que all nuestro primer punto a cuidar, no imprimir el session_id en enlaces a sitios externos. Dentro del mismo caso hay otra brecha. La mayora de los navegadores web incluyen la URL del referer en cada solicitud a un servidor web. El referer es literalmente el referido, o el sitio que est enviando la visita. La informacin del referer suele almacenarse en los logs de los servidores web para hacer anlisis de trfico. Lo cierto es que si desde nuestro sitio el usuario legtimo hace click en un enlace externo, aunque nos hallamos cuidado de no imprimir en l es session_id es muy probable que el sitio

remoto reciba la informacin del referer, que en este caso es la URL completa de nuestro sitio incluyendo el query string donde est el session_id. Si el servidor remoto est almacenando en sus logs los referers tendr all el session_id de nuestro usuario el cul podr ser utilizado para impersonarlo. Podemos evitar que se enve el referer al sitio remoto? No, de ninguna manera, pues esto es algo que hace el navegador. El nico caso en el que los navegadores no envan el referer es en el caso que se proceda desde una conexin segura. Es decir que si nuestro sitio est implementado con HTTP sobre SSL ( o https), el navegador no enviar la informacin de referer al sitio externo. As es que si tenemos enlaces externos y no queremos que nuestro session_id llegue a ser revelado por el navegador tendremos que implementar nuestro sitio sobre https. Esto nos proteger adems en el caso de que un atacante muy dedicado est a la escucha de nuestro trfico de red con un sniffer, leyendo los requests de HTTP a nuestro servidor web. 2) Brechas introducidas por el usuario.Puede que hayamos hecho todo para que el session_id no pase a sitios externos, pero an as hay situaciones en las que el URL puede ser tontamente revelada por nuestro propio usuario legtimo. Desconociendo la relevancia de la informacin en el URL nuestro usuario podra pasar un enlace de nuestro sitio a otra persona, vcitima de ingeniera social, dndole sin saber la informacin necesaria para que tome su rol. Adems, el URL puede ser agregado en los Favoritos por nuestro usuario o quedar guardado en el cache del navegador o historial, donde otro usuario de la misma mquina pueda leerlos y utilizarlos o donde un usuario remoto puede substraerlos en alguna oportunidad. De modo que por parte del usaurio hay tambin gran riesgo de revelar el session_id a un atacante.

Brechas de seguridad en la propagacin del session_id por cookies


En este mtodo el session_id se escribe en un cookie en el sistema del usuario as que la seguridad se comprometer en cualquier caso en el que el contenido del cookie sea revelado. En la propagacin por cookie existen muy pocos casos en los que el session_id pueda ser revelado. No hay posibilidad de que el visitante revele el cookie al visitar otro sitio o al pasar un enlace de nuestro sitio a otra persona. El atacante tendra que ser muy dedicado y estar escuchando el trfico de nuestra red para "ver pasar" el cookie o tendra que atacar directamente a la mquina de nuestro usuario para substraerle el cookie. De nuevo, podemos protegernos de la posibilidad de un siffer escuchando el trfico de red utilizando https y enviando el cookie de la sesin solo sobre https. Si optamos por propagar la sesin por cookie adems de habilitar session.use_cookies en nuestro php.ini o por ini_set(), ser bueno deshabilitar la propagacin del session_id en las URLs, podremos hacerlo asegurndonos de que est deshabilitada la directiva session.use_trans_id de nuestro php.ini y en el caso de php 4.3.0 en adelante habilitando session.use_only_cookies para asegurarnos que el session_id solo se propague por cookies.

Permisos de sistema de archivos en nuestro session.save_path


Como ya hemos mencionado la informacin de cada sesin se almacena en un directorio establecido por la directiva session.save_path, si dicho directorio fuera legible

por otros usuarios del sistema estos podran leer los session_id y la informacin de cada sesin de usuario. Hemos por lo tanto de establecer restricciones a nivel del sistema de archivos para impedir que usuarios no autorizados de nuestro propio sistema tengan acceso a las sesiones de usuario.

Algunas medidas de defensa


En todos los casos dos buenas medidas de defensa que podemos llevar a cabo son, hacer expirar las sesiones a un tiempo razonable, y conservar informacin de la sesin que nos ayude a detectar cualquier anomala. Un mtodo muy comn es llevar un registro de sesiones, (en una tabla o archivo) donde incluyamos de cada sesin de nuestro sistema la hora de ltima actividad de la sesin y la direccin IP del usuario que comenz la sesin. En cada acceso del usuario haremos dos controles, que no haya pasado cierto tiempo preestablacido desde la ltima actividad y que la IP del usuario sea la misma que la IP del usuario que comenz la sesin. Si la sesin ha expirado podremos destruirla y solicitarle que comienze una nueva sesin. Si la IP de usuario que hace el acceso es distinta a la IP del usuario que comenz la sesin habrn dos posibilidades, que el usuario haya rotado la IP como sucede bajo ciertas conecciones, como las establecidas sobre PPPoE, o que se trate de alguien impersonando a nuestro usuario legtimo. En todos los casos, no debera suceder que el usuario rote su IP, o es al menos un caso muy poco probable, por lo que sera bueno hacer este control y caducar la sesin para impedir un posible ataque. http://www.elmaster.com/2006/03/16/manejo-de-sesiones-en-php/

También podría gustarte