2011-11-17 68 views
25

Un producto en el que trabajo recibió una dura auditoría de seguridad por parte de un cliente potencial y les molesta que Tomcat establezca una cookie JSESSIONID antes de que se haya realizado la autenticación. Es decir, Tomcat establece esta cookie cuando se carga nuestra página de inicio de sesión sin estado, pero antes de iniciar sesión.cómo actualizar la cookie JSESSIONID después de iniciar sesión

Sugieren una de las siguientes:

  1. emitir una nueva cookie JSESSIONID después de Entrar
  2. evitar una cookie JSESSIONID de estar ajustado en el primer lugar en la página de entrada (es decir, antes de la autenticación ha sucedido)

He estado estudiando detenidamente todo lo relacionado con JSESSIONID en este sitio y no puedo encontrar una respuesta fácil. Solo espero algunas ideas. Mis mejores soluciones para cada uno son:

  1. justo después de inicio de sesión, clonar la Sesión (menos el id) copiando todos los atributos, lo que invalida la sesión anterior, la creación de uno nuevo, copiando los valores, asociándolo con la solicitud y esperando que eso funcione
  2. crear un servlet Filtro al final de la cadena que elimina la cookie JSESSIONID antes de que la página de inicio de sesión se cargue inicialmente. Y luego, espero que la solicitud de inicio de sesión funcione sin un conjunto de JSESSIONID.

Tengo que dormir un poco, pero lo intentaré por la mañana. Sería increíble recibir comentarios o mejores sugerencias de personas mucho más inteligentes que yo, como tú.

Independientemente, voy a publicar mis resultados aquí porque parece que muchas otras personas han estado queriendo hacer algo similar.

Respuesta

34

No actualizará después, pero justo antes. Al ejecutar la acción login primero hacer:

HttpSession session = request.getSession(false); 
if (session!=null && !session.isNew()) { 
    session.invalidate(); 
} 

Luego haces:

HttpSession session = request.getSession(true); // create the session 
// do the login (store the user in the session, or whatever) 

FYI lo que está resolviendo con este truco es http://www.owasp.org/index.php/Session_Fixation

Por último se puede desactivar la creación de la sesión automática y sólo crear el sesión cuando realmente lo necesite.Si usa JSP, haga eso por:

<%@page contentType="text/html" 
     pageEncoding="UTF-8" 
     session="false"%> 
+0

Cosas interesantes. Estoy usando Wicket 1.3, y parece que no puedo encontrar una manera de establecer 'session = false' (el lado de la vista no está basado en JSP). Voy a probar la idea de getSession (falso) ahora ... ¡gracias! –

+0

Invalidar la sesión antes de iniciar sesión está causando el caos Wicket (solo sigue redirigiendo a la página de inicio de sesión). Todavía estoy jugando con esto ... –

+1

@RichardsonHeights: Eche un vistazo a https://issues.apache.org/jira/browse/WICKET-1767. Parece documentado y resuelto. – cherouvim

1

¿El problema es que el JSESSIONID está visible en el navegador o que se establece en una cookie? Supongo que es lo último en tu caso.

1.issue una nueva cookie JSESSIONID después de Entrar

Este es el comportamiento por defecto de Tomcat si cambia de http a https en el momento de inicio de sesión. El anterior se descarta y se genera uno nuevo.

Si su nombre de usuario en sí es a través de HTTP, que supongo que es otro de los temas de seguridad para los auditores;)

O son todas sus páginas a través de https?

+0

El problema es que la cookie JSESSIONID está configurada en el navegador y visible en el visor de cookies de Firefox (por ejemplo). Como cherouvim señala arriba, es el agujero de seguridad de "fijación de sesión". Interesante sobre el modificador http/https ... Sin embargo, la aplicación solo se ejecuta sobre https. –

1

Dos cosas que he encontrado que podrían ser útiles para los demás.

  1. Si está utilizando Apache Wicket, hay una solución para esto después de la versión 1.4. Mi aplicación todavía está en 1.3, así que no me di cuenta, pero pude realizar una copia de seguridad del puerto muy fácilmente en mi propia clase de WebSession. Wicket 1.4 agrega un método replaceSession() a WebSession, que funciona muy bien. Puede llamarlo justo después de la autenticación y obtendrá un nuevo JSESSIONID. Básicamente resolvió este problema para mí. Más información aquí: https://issues.apache.org/jira/browse/WICKET-1767.

  2. Hay una válvula Apache Tomcat disponible después de la versión 5.5.29 que puede agregar a context.xml. Se encargará de emitir un nuevo JSESSIONID después de la autenticación. Más información está disponible aquí: https://issues.apache.org/bugzilla/show_bug.cgi?id=45255. La entrada de la válvula se vería así: <Valve className="org.apache.catalina.authenticator.FormAuthenticator" changeSessionIdOnAuthentication="true"/>

4

que no puedo comentar sobre la respuesta de @ cherouvim anterior, ya que no tengo suficientes puntos. La nueva ID de sesión se debe establecer "después" de que el usuario inicie sesión con éxito, para evitar la fijación de la sesión. Trataré de explicar mi razonamiento.

La fijación de sesión significa efectivamente que un atacante de alguna manera engañó a un usuario para que use un valor conocido por el atacante. En aras de la simplicidad, supongamos que el atacante se acercó al escritorio del usuario, usó Firebug y editó las cookies del usuario. Ahora cuando el usuario inicia sesión, se iniciará sesión con la cookie controlada por el atacante. Como el atacante también conoce este valor, actualizará su navegador y se les proporcionarán los recursos asignados a esa ID de sesión (los recursos de la víctima). Esa es la fijación de la sesión. ¿Correcto?

Ahora digamos que ejecutamos session.invalidate antes de que el usuario de la víctima inicie sesión. Digamos que la cookie inicialmente tenía un valor abc. Al ejecutar session.invalidate, se borra el valor abc de la sesión del servidor.

Ahora viene la parte en la que no estoy de acuerdo. Lo que sugiere es generar una nueva sesión antes de que el usuario realmente inicie sesión (ingrese nombre de usuario y contraseña y haga clic en enviar). Esto sin duda causará que se genere una nueva cookie, pero estará en el navegador del usuario antes de iniciar sesión. Entonces, si un atacante puede editar nuevamente la cookie "prelogin", el ataque aún persiste, ya que la misma cookie se usará incluso después de que el usuario inicie sesión.

Creo que este es el flujo correcto.

  • usuario hace un /login.html GET
  • página Volver Entrar con cualquier cookie es actualmente existe en el navegador
  • entra usuario credenciales y hace clic en Enviar
  • aplicación verifica las credenciales
  • Al verificar si las credenciales eran correctas session.invalidate() se ejecuta ... destruyendo la cookie anterior.
  • ahora generan la nueva cookie usando request.getSession (verdadero)

Lo que esto significa, es que incluso si un atacante logra engañarlo para que el uso de un valor controlado antes de iniciar la sesión, que está todavía está protegido ... a medida que la aplicación cambia forzosamente el valor después de iniciar sesión.

Aquí es un buen blog sobre este tema - https://blog.whitehatsec.com/tag/session-fixation/

3

He seguido siguiente manera para regenerar la nueva sesión de la sesión anterior. Espero que se beneficie de ello.

private void regenerateSession(HttpServletRequest request) { 

    HttpSession oldSession = request.getSession(); 

    Enumeration attrNames = oldSession.getAttributeNames(); 
    Properties props = new Properties(); 

    if (attrNames != null) { 
     while (attrNames.hasMoreElements()) { 
      String key = (String) attrNames.nextElement(); 
      props.put(key, oldSession.getAttribute(key)); 
     } 

     //Invalidating previous session 
     oldSession.invalidate(); 
     //Generate new session 
     HttpSession newSession = request.getSession(true); 
     attrNames = props.keys(); 

     while (attrNames.hasMoreElements()) { 
      String key = (String) attrNames.nextElement(); 
      newSession.setAttribute(key, props.get(key)); 
     } 
    } 
-1
session=request.getSession(true); 
Enumeration keys = session.getAttributeNames();  
HashMap<String,Object> hm=new HashMap<String,Object>(); 
while (keys.hasMoreElements()) 
{ 
    String key = (String)keys.nextElement(); 
    hm.put(key,session.getValue(key)); 
    session.removeAttribute(key);  
} 
session.invalidate(); 
session=request.getSession(true); 
for(Map.Entry m:hm.entrySet()) 
{ 
    session.setAttribute((String)m.getKey(),m.getValue()); 
    hm.remove(m); 
} 
0

Cuando se utiliza la primavera, se debe utilizar SessionFixationProtectionStrategy.

<property name="sessionAuthenticationStrategy" ref="sas"/> 
... 
<bean id="sas" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/> 

Al inspeccionar el source code, se verá que esto es similar al enfoque de harsha89: Será

  1. crear una nueva sesión
  2. tranfer
  3. atributos de la sesión anterior.
0

Si está utilizando Tomcat y desea aplicar esta forma global a todos los servlets que utilizan el mecanismo de autenticación de Tomcat, puede escribir una válvula para obligar a este comportamiento, como se muestra en este sample code.

0

Si está utilizando la versión anterior de jboss como jboss 4 simplemente llama a request.getSession (true) después de que session.invalidate() no cambia la identificación de la sesión.

Si no desea utilizar la válvula y desea cambiar la identificación de la sesión en la clase de acción, puede archivarse usando la reflexión porque CatalinaRequest no estará disponible directamente en su clase de acción.

Código de ejemplo

private HttpSession changeSessionId(HttpServletRequest request) 
{ 
    HttpSession oldSession = request.getSession(false); 
    HttpSession newSession = null; 

    try 
    { 
     //get all cookies from request 
     Cookie[] cookies = request.getCookies(); 

     //Get all attribute from old session 
     Enumeration<Object> attrNames = oldSession.getAttributeNames(); 

     Properties attributFromOldSession = new Properties(); 

     while (attrNames.hasMoreElements()) 
     { 
      String key = (String)attrNames.nextElement(); 
      attributFromOldSession.put(key, oldSession.getAttribute(key)); 
     } 

     //Actual logic to change session id 

     Field catalinaRequestField; 

     //Getting actual catalina request using reflection 
     catalinaRequestField = request.getClass().getDeclaredField("request"); 
     catalinaRequestField.setAccessible(true); // grant access to (protected) field 
     Request realRequest = (Request)catalinaRequestField.get(request); 

     //Invalidating actual request 
     realRequest.getSession(true).invalidate(); 
     realRequest.setRequestedSessionId(null); 
     realRequest.clearCookies(); 

     //setting new session Id 
     realRequest.setRequestedSessionId(realRequest.getSessionInternal(true).getId()); 

     //Put back the cookies 
     for (Cookie cookie : cookies) 
     { 

      if (!"JSESSIONID".equals(cookie.getName())) 
      { 
       realRequest.addCookie(cookie); 
      } 
     } 

     // put attribute from old session 
     attrNames = attributFromOldSession.keys(); 

     while (attrNames.hasMoreElements()) 
     { 
      String key = (String)attrNames.nextElement(); 
      newSession.setAttribute(key, attributFromOldSession.get(key)); 
     } 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
    return newSession; 

} 
0

HttpServletRequest.changeSessionId() se puede utilizar para cambiar el ID de sesión en cualquier punto del tiempo.

Cuestiones relacionadas