El comportamiento por defecto de las sesiones puede modificarse utilizando los métodos estáticos de
Zend_Session. Toda la gestión y manipulación global de sesiones
ocurre usando Zend_Session, incluyendo la configuración de las
opciones habituales proporcionadas por
ext/session, usando Zend_Session::setOptions(). Por
ejemplo, no asegurar el uso de un save_path seguro o un nombre de cookie único
por parte de ext/session usando Zend_Session::setOptions() puede resultar en
problemas de seguridad.
Cuando se solicita el primer espacio de nombres de sesión, Zend_Session
iniciará automáticamente la sesión PHP, a menos que ya se haya iniciado con
Zend_Session::start().
La sesión PHP subyacente utilizará los valores por defecto de
Zend_Session, a menos que sean modificados primero mediante
Zend_Session::setOptions().
Para establecer una opción de configuración de sesión, incluya el nombre base (la parte del nombre después de
"session.") como clave de un array pasado a
Zend_Session::setOptions(). El valor correspondiente en el
array se utiliza para establecer el valor de la opción de sesión. Si el desarrollador no establece ninguna opción,
Zend_Session utilizará primero las opciones recomendadas por defecto, y luego
los valores por defecto de php.ini. Los comentarios de la comunidad sobre las mejores prácticas para estas opciones
deben enviarse a fw-auth@lists.zend.com.
Ejemplo 65.16. Uso de Zend_Config para configurar Zend_Session
Para configurar este componente usando Zend_Config_Ini,
primero añada las opciones de configuración al archivo INI:
; Accept defaults for production [production] ; bug_compat_42 ; bug_compat_warn ; cache_expire ; cache_limiter ; cookie_domain ; cookie_lifetime ; cookie_path ; cookie_secure ; entropy_file ; entropy_length ; gc_divisor ; gc_maxlifetime ; gc_probability ; hash_bits_per_character ; hash_function ; name should be unique for each PHP application sharing the same ; domain name name = UNIQUE_NAME ; referer_check ; save_handler ; save_path ; serialize_handler ; use_cookies ; use_only_cookies ; use_trans_sid ; remember_me_seconds = <integer seconds> ; strict = on|off ; Development inherits configuration from production, but overrides ; several values [development : production] ; Don't forget to create this directory and make it rwx (readable and ; modifiable) by PHP. save_path = /home/myaccount/zend_sessions/myapp use_only_cookies = on ; When persisting session id cookies, request a TTL of 10 days remember_me_seconds = 864000
A continuación, cargue el archivo de configuración y pase su representación en array a
Zend_Session::setOptions():
$config = new Zend_Config_Ini('myapp.ini', 'development');
Zend_Session::setOptions($config->toArray());
La mayoría de las opciones mostradas arriba no necesitan más explicación que la que se encuentra en la documentación estándar de PHP, pero aquellas de especial interés se detallan a continuación.
booleano
strict- deshabilita el inicio automático deZend_Sessional usarnew Zend_Session_Namespace().entero
remember_me_seconds- cuánto tiempo debe persistir la cookie del id de sesión, después de que el user agent haya finalizado (por ejemplo, se cierre la aplicación del navegador).-
cadena
save_path- El valor correcto depende del sistema, y debe ser proporcionado por el desarrollador usando una ruta absoluta a un directorio legible y con permisos de escritura por el proceso PHP. Si no se proporciona una ruta con permisos de escritura, entoncesZend_Sessionlanzará una excepción al iniciarse (es decir, cuando se llama astart()).![[Note]](images/note.png)
Riesgo de seguridad Si la ruta es legible por otras aplicaciones, entonces el secuestro de sesión podría ser posible. Si la ruta tiene permisos de escritura por otras aplicaciones, entonces el envenenamiento de sesión podría ser posible. Si esta ruta se comparte con otros usuarios u otras aplicaciones PHP, pueden ocurrir diversos problemas de seguridad, incluyendo el robo del contenido de la sesión, el secuestro de sesiones y la colisión de la recolección de basura (por ejemplo, la aplicación de otro usuario podría hacer que PHP elimine los archivos de sesión de su aplicación).
Por ejemplo, un atacante puede visitar el sitio web de la víctima para obtener una cookie de sesión. Luego, edita la ruta de la cookie hacia su propio dominio en el mismo servidor, antes de visitar su propio sitio web para ejecutar
var_dump($_SESSION). Armado con conocimiento detallado del uso que la víctima hace de los datos en sus sesiones, el atacante puede entonces modificar el estado de la sesión (envenenando la sesión), alterar la ruta de la cookie de vuelta hacia el sitio web de la víctima, y luego realizar solicitudes desde el sitio web de la víctima usando la sesión envenenada. Incluso si dos aplicaciones en el mismo servidor no tienen acceso de lectura/escritura alsave_pathde la otra aplicación, si elsave_pathes adivinable, y el atacante tiene control sobre uno de esos dos sitios web, el atacante podría alterar elsave_pathde su sitio web para usar el de la otra, y así lograr el envenenamiento de sesión, bajo algunas configuraciones comunes de PHP. Por lo tanto, el valor desave_pathno debe hacerse público y debe alterarse hacia una ubicación segura y única para cada aplicación. -
cadena
name- El valor correcto depende del sistema y debe ser proporcionado por el desarrollador usando un valor único para la aplicación.![[Note]](images/note.png)
Riesgo de seguridad Si el valor de
php.iniparasession.namees el mismo (por ejemplo, el valor por defecto "PHPSESSID"), y hay dos o más aplicaciones PHP accesibles a través del mismo nombre de dominio entonces compartirán los mismos datos de sesión para los visitantes de ambos sitios web. Además, podría producirse una posible corrupción de los datos de sesión. -
booleano
use_only_cookies- Para evitar introducir riesgos de seguridad adicionales, no altere el valor por defecto de esta opción.![[Note]](images/note.png)
Riesgo de seguridad Si esta configuración no está habilitada, un atacante puede fijar fácilmente el id de sesión de la víctima, usando enlaces en el sitio web del atacante, como
http://www.example.com/index.php?PHPSESSID=fixed_session_id. La fijación funciona si la víctima aún no tiene una cookie de id de sesión para example.com. Una vez que la víctima usa un id de sesión conocido, el atacante puede entonces intentar secuestrar la sesión haciéndose pasar por la víctima, y emulando el user agent de la víctima.
Si ve el mensaje de error, "Cannot modify header information - headers already sent", o, "You must call ... before any output has been sent to the browser; output started in ...", entonces examine cuidadosamente la causa inmediata (función o método) asociada con el mensaje. Cualquier acción que requiera el envío de cabeceras HTTP, como el envío de una cookie, debe realizarse antes de enviar la salida normal (salida sin buffer), excepto cuando se utiliza el buffering de salida de PHP.
Usar el buffering de salida suele ser suficiente para prevenir este problema, y puede ayudar a mejorar el rendimiento. Por ejemplo, en
php.ini, "output_buffering = 65535" habilita el buffering de salida con un buffer de 64K. Aunque el buffering de salida puede ser una buena táctica en servidores de producción para aumentar el rendimiento, confiar únicamente en el buffering para resolver el problema de "headers already sent" no es suficiente. La aplicación no debe exceder el tamaño del buffer, o el problema ocurrirá siempre que la salida enviada (antes de las cabeceras HTTP) exceda el tamaño del buffer.Si un método de
Zend_Sessionestá involucrado en causar el mensaje de error, examine el método cuidadosamente, y asegúrese de que su uso realmente sea necesario en la aplicación. Por ejemplo, el uso por defecto dedestroy()también envía una cabecera HTTP para expirar la cookie de sesión del lado del cliente. Si esto no es necesario, entonces usedestroy(false), ya que las instrucciones para establecer cookies se envían con cabeceras HTTP.Alternativamente, intente reorganizar la lógica de la aplicación de modo que todas las acciones que manipulan cabeceras se realicen antes de enviar cualquier salida.
Elimine cualquier etiqueta de cierre "
?>", si aparecen al final de un archivo fuente PHP. No son necesarias, y los saltos de línea y otros espacios en blanco casi invisibles después de la etiqueta de cierre pueden desencadenar el envío de salida al cliente.
Introducción: la mejor práctica en relación con el uso de sesiones con Zend Framework recomienda
usar una cookie de navegador (es decir, una cookie normal almacenada en su navegador web), en lugar de
incrustar un identificador de sesión único en las URLs como medio para rastrear
usuarios individuales. Por defecto, este componente usa únicamente cookies para mantener los identificadores
de sesión. El valor de la cookie es el identificador único de la sesión de su navegador.
El ext/session de PHP usa este identificador para mantener una relación
única uno a uno entre los visitantes del sitio web y el almacenamiento de datos de sesión
persistente único para cada visitante. Zend_Session* envuelve este mecanismo
de almacenamiento ($_SESSION) con una interfaz orientada a objetos.
Desafortunadamente, si un atacante obtiene acceso al valor de la cookie (el id de sesión),
un atacante podría ser capaz de secuestrar la sesión de un visitante. Este problema no es exclusivo de
PHP, ni de Zend Framework. El método
regenerateId() permite a una aplicación cambiar el id de sesión
(almacenado en la cookie del visitante) a un valor nuevo, aleatorio e impredecible. Nota: aunque no es lo mismo,
para facilitar la lectura de esta sección, usamos los términos "user agent" y "navegador web" indistintamente.
¿Por qué?: Si un atacante obtiene un identificador de sesión válido, un atacante podría ser capaz de
hacerse pasar por un usuario válido (la víctima), y luego obtener acceso a información
confidencial o manipular de otro modo los datos de la víctima gestionados por su aplicación.
Cambiar los ids de sesión ayuda a proteger contra el secuestro de sesión. Si el id de sesión
se cambia, y un atacante no conoce el nuevo valor, el atacante no puede usar el nuevo
id de sesión en sus intentos de secuestrar la sesión del visitante. Incluso si un atacante obtiene
acceso a un id de sesión antiguo, regenerateId() también mueve los
datos de sesión del "handle" del id de sesión antiguo al nuevo, de modo que no quedan datos
accesibles a través del id de sesión antiguo.
Cuándo usar regenerateId(): añadir Zend_Session::regenerateId()
a su bootstrap de Zend Framework produce una de las formas más seguras
de regenerar los ids de sesión en las cookies del user agent. Si no hay lógica condicional para
determinar cuándo regenerar el id de sesión, entonces no hay fallos en esa lógica.
Aunque regenerar en cada solicitud previene varias posibles vías de ataque, no
todo el mundo quiere el pequeño costo asociado en rendimiento y ancho de banda. Por lo tanto, las aplicaciones
comúnmente intentan determinar dinámicamente situaciones de mayor riesgo, y solo regeneran
los ids de sesión en esas situaciones. Cada vez que se "escalan" los privilegios de la sesión de un
visitante del sitio web (por ejemplo, un visitante vuelve a autenticar su identidad antes de editar su
"perfil" personal), o cada vez que ocurre un cambio "sensible" de seguridad en un parámetro de sesión,
considere usar regenerateId() para crear un nuevo id de sesión. Si
llama a la función rememberMe(), entonces no use
regenerateId(), ya que la primera llama a la segunda. Si un usuario
ha iniciado sesión exitosamente en su sitio web, use rememberMe()
en lugar de regenerateId().
Evitar las vulnerabilidades de
cross-site scripting (XSS) ayuda a prevenir el secuestro de sesión.
Según las estadísticas de Secunia los problemas
de XSS ocurren con frecuencia, independientemente de los lenguajes usados para crear aplicaciones
web. En lugar de esperar no tener nunca un problema de XSS con una aplicación,
planifique para ello siguiendo las mejores prácticas para ayudar a minimizar el daño, si ocurre. Con
XSS, un atacante no necesita acceso directo al tráfico de red de la víctima. Si la
víctima ya tiene una cookie de sesión, un XSS con Javascript podría permitir a un atacante leer
la cookie y robar la sesión. Para víctimas sin cookies de sesión, usando XSS para
inyectar Javascript, un atacante podría crear una cookie de id de sesión en el navegador de la víctima
con un valor conocido, y luego establecer una cookie idéntica en el sistema del atacante,
con el fin de secuestrar la sesión de la víctima. Si la víctima visitó un
sitio web del atacante, entonces el atacante también puede emular la mayoría de otras características identificables
del user agent de la víctima. Si su sitio web tiene una vulnerabilidad de XSS, el atacante
podría insertar un Javascript de AJAX que "visite" en secreto
el sitio web del atacante, de modo que el atacante conozca las características del navegador de la víctima
y se dé cuenta de una sesión comprometida en el sitio web de la víctima.
Sin embargo, el atacante no puede alterar arbitrariamente el estado del lado del servidor de
las sesiones PHP, siempre que el desarrollador haya establecido correctamente el valor
de la opción save_path.
Por sí solo, llamar a Zend_Session::regenerateId() cuando
se usa la sesión del usuario por primera vez, no previene los ataques de fijación de sesión, a menos que
pueda distinguir entre una sesión originada por un atacante que emula a la víctima. A
primera vista, esto podría parecer contradictorio con la afirmación anterior, hasta que
consideramos a un atacante que primero inicia una sesión real en su sitio web. La sesión
se "usa por primera vez" por el atacante, quien luego conoce el resultado de la inicialización
(regenerateId()). El atacante entonces usa el nuevo id de sesión
en combinación con una vulnerabilidad de XSS, o inyecta el id de sesión mediante un enlace en
el sitio web del atacante (funciona si use_only_cookies = off).
Si puede distinguir entre un atacante y una víctima que usan el mismo id de sesión, entonces el secuestro de sesión puede tratarse directamente. Sin embargo, tales distinciones generalmente implican algún tipo de compromiso de usabilidad, porque los métodos de distinción suelen ser imprecisos. Por ejemplo, si se recibe una solicitud desde una IP en un país diferente al de la IP de la solicitud cuando se creó la sesión, entonces la nueva solicitud probablemente pertenece a un atacante. Bajo las siguientes condiciones, podría no haber ninguna forma de que una aplicación web distinga entre una víctima y un atacante:
el atacante primero inicia una sesión en su sitio web para obtener un id de sesión válido
el atacante usa una vulnerabilidad de XSS en su sitio web para crear una cookie en el navegador de la víctima con el mismo id de sesión válido (es decir, fijación de sesión)
tanto la víctima como el atacante se originan desde la misma granja de proxies (por ejemplo, ambos están detrás del mismo firewall en una gran empresa, como AOL)
El código de ejemplo a continuación hace mucho más difícil que un atacante conozca el id de sesión actual de la víctima, a menos que el atacante ya haya realizado los dos primeros pasos anteriores.
Ejemplo 65.17. Fijación de sesión
$defaultNamespace = new Zend_Session_Namespace();
if (!isset($defaultNamespace->initialized)) {
Zend_Session::regenerateId();
$defaultNamespace->initialized = true;
}
Normalmente, las sesiones terminan cuando el user agent finaliza, como cuando un usuario final cierra
un programa de navegador web. Sin embargo, su aplicación puede proporcionar la capacidad de extender las sesiones
de usuario más allá del tiempo de vida del programa cliente mediante el uso de cookies
persistentes. Use Zend_Session::rememberMe() antes de que se inicie una sesión
para controlar el tiempo antes de que expire una cookie de sesión persistida. Si no
especifica un número de segundos, entonces el tiempo de vida de la cookie de sesión por defecto es
remember_me_seconds, que puede establecerse usando
Zend_Session::setOptions(). Para ayudar a frustrar la fijación/secuestro
de sesión, use esta función cuando un usuario se autentique exitosamente con su
aplicación (por ejemplo, desde un formulario de "login").
Esta función complementa a rememberMe() escribiendo una cookie
de sesión que tiene un tiempo de vida que termina cuando el user agent finaliza.
Use este método para determinar si ya existe una sesión para el user agent/solicitud
actual. Puede usarse antes de iniciar una sesión, e independientemente de todos los demás
métodos de Zend_Session y Zend_Session_Namespace.
Zend_Session::destroy() destruye todos los datos persistentes
asociados con la sesión actual. Sin embargo, ninguna variable en PHP se ve
afectada, por lo que sus sesiones con espacio de nombres (instancias de
Zend_Session_Namespace) siguen siendo legibles. Para completar un "logout",
establezca el parámetro opcional como TRUE (el valor por defecto) para también eliminar
la cookie de id de sesión del user agent. El parámetro opcional $readonly
elimina la capacidad de crear nuevas instancias de Zend_Session_Namespace
y de que los métodos de Zend_Session escriban en el almacén de datos de sesión.
Si ve el mensaje de error, "Cannot modify header information - headers already sent",
entonces evite usar TRUE como valor del primer argumento
(solicitando la eliminación de la cookie de sesión), o vea esta sección.
Por lo tanto, Zend_Session::destroy(true) debe ser llamado antes de que
PHP haya enviado cabeceras HTTP, o el buffering de salida
debe estar habilitado. Además, la salida total enviada no debe exceder el tamaño de buffer establecido, con el
fin de evitar que se dispare el envío de la salida antes de la llamada a
destroy().
![]() |
Lanza |
|---|---|
Por defecto, |
Este método no hace absolutamente nada más que alternar un indicador en
Zend_Session para evitar más escrituras en el almacén de datos de
sesión. Estamos solicitando específicamente comentarios sobre esta característica. Los usos/abusos potenciales
podrían incluir deshabilitar temporalmente el uso de instancias de
Zend_Session_Namespace o métodos de
Zend_Session para escribir en el almacén de datos de sesión, mientras
la ejecución se transfiere a código relacionado con la vista. Los intentos de realizar acciones de
escritura mediante estas instancias o métodos lanzarán una excepción.
Apaga la sesión, cierra la escritura y desvincula $_SESSION del
mecanismo de almacenamiento subyacente. Esto completará la transformación interna de datos en esta
solicitud. El parámetro booleano opcional $readonly puede eliminar el acceso
de escritura lanzando una excepción ante cualquier intento de escribir en la sesión mediante
Zend_Session o Zend_Session_Namespace.
![]() |
Lanza |
|---|---|
Por defecto, |
Este método envía una cookie de id de sesión expirada, causando que el cliente elimine la cookie de sesión. A veces esta técnica se usa para realizar un logout del lado del cliente.
La mayoría de los desarrolladores encontrarán suficiente el manejador de almacenamiento por defecto. Este método proporciona un
envoltorio orientado a objetos para session_set_save_handler().
Use este método para determinar si existe un espacio de nombres de sesión, o si un índice en particular existe en un espacio de nombres en particular.
![]() |
Lanza |
|---|---|
Se lanzará una excepción si |
Use Zend_Session::namespaceUnset($namespace) para eliminar
eficientemente un espacio de nombres completo y su contenido. Como con todos los arrays en
PHP, si se destruye (unset) una variable que contiene un array, y el array
contiene otros objetos, esos objetos permanecerán disponibles, si también se almacenaron por
referencia en otros arrays/objetos que permanecen accesibles mediante otras variables. Por lo tanto
namespaceUnset() no realiza una eliminación "profunda"
del contenido de las entradas en el espacio de nombres. Para una explicación más detallada, por favor
consulte References Explained en el
manual de PHP.
![]() |
Lanza |
|---|---|
Se lanzará una excepción si el espacio de nombres no tiene permisos de escritura (por ejemplo, después de
|
OBSOLETO: use getIterator() en
Zend_Session_Namespace. Este método devuelve un array con el
contenido de $namespace. Si tiene razones lógicas para mantener este
método accesible públicamente, por favor proporcione sus comentarios a la lista de correo fw-auth@lists.zend.com.
De hecho, se agradece la participación en cualquier tema relevante :)
![]() |
Lanza |
|---|---|
Se lanzará una excepción si |