Question

Après avoir lu le billet de blog de Jeff sur Protection de vos cookies :Http uniquement.Je souhaite implémenter les cookies HttpOnly dans mon application Web.

Comment dites-vous à Tomcat d'utiliser uniquement les cookies http pour les sessions ?

Était-ce utile?

La solution

httpOnly est pris en charge à partir de Tomcat 6.0.19 et Tomcat 5.5.28.

Voir le journal des modifications entrée pour le bug 44382.

Le dernier commentaire pour bug 44382 déclare: "Cela a été appliqué à 5.5.x et sera inclus dans 5.5.28." Cependant, il ne semble pas que 5.5.28 ait été libéré.

La fonctionnalité httpOnly peut être activée pour toutes les applications Web de conf/context.xml:

<Context useHttpOnly="true">
...
</Context>

Mon interprétation est que cela fonctionne également pour un contexte individuel en le définissant sur le paramètre souhaité. Contexte entrée dans conf/serveur.xml (de la même manière que ci-dessus).

Autres conseils

Mise à jour:Les trucs JSessionId ici ne sont que pour les conteneurs plus âgés.Veuillez utiliser la réponse actuellement acceptée par JT, sauf si vous utilisez <Tomcat 6.0.19 ou <Tomcat 5.5.28 ou un autre conteneur qui ne prend pas en charge les cookies JSessionID httponly comme option de configuration.

Lorsque vous configurez des cookies dans votre application, utilisez

response.setHeader( "Set-Cookie", "name=value; HttpOnly");

Cependant, dans de nombreuses applications Web, le cookie le plus important est l'identifiant de session, qui est automatiquement défini par le conteneur comme cookie JSESSIONID.

Si vous utilisez uniquement ce cookie, vous pouvez écrire un ServletFilter pour réinitialiser les cookies à la sortie, forçant JSESSIONID à HttpOnly.La page à http://keepitlocked.net/archive/2007/11/05/java-and-httponly.aspx http://alexsmolen.com/blog/?p=16 suggère d'ajouter ce qui suit dans un filtre.

if (response.containsHeader( "SET-COOKIE" )) {
  String sessionid = request.getSession().getId();
  response.setHeader( "SET-COOKIE", "JSESSIONID=" + sessionid 
                      + ";Path=/<whatever>; Secure; HttpOnly" );
} 

mais notez que cela écrasera tous les cookies et définira uniquement ce que vous indiquez ici dans ce filtre.

Si vous utilisez des cookies supplémentaires au cookie JSESSIONID, vous devrez alors étendre ce code pour définir tous les cookies dans le filtre.Ce n'est pas une bonne solution dans le cas de plusieurs cookies, mais c'est peut-être une solution rapide acceptable pour la configuration uniquement JSESSIONID.

Veuillez noter qu'à mesure que votre code évolue au fil du temps, un vilain bug caché vous attend lorsque vous oubliez ce filtre et essayez de définir un autre cookie ailleurs dans votre code.Bien sûr, cela ne sera pas réglé.

C'est vraiment un hack.Si vous utilisez Tomcat et pouvez le compiler, jetez un œil à l'excellente suggestion de Shabaz pour patcher le support HttpOnly dans Tomcat.

Veuillez faire attention à ne pas écraser l'indicateur de cookie « ;secure » ​​dans les sessions https.Cet indicateur empêche le navigateur d'envoyer le cookie via une connexion HTTP non cryptée, ce qui rend inutile l'utilisation de https pour les requêtes légitimes.

private void rewriteCookieToHeader(HttpServletRequest request, HttpServletResponse response) {
    if (response.containsHeader("SET-COOKIE")) {
        String sessionid = request.getSession().getId();
        String contextPath = request.getContextPath();
        String secure = "";
        if (request.isSecure()) {
            secure = "; Secure"; 
        }
        response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid
                         + "; Path=" + contextPath + "; HttpOnly" + secure);
    }
}

Pour les cookies de session, cela ne semble pas encore être pris en charge dans Tomcat.Voir le rapport de bug Besoin d'ajouter la prise en charge du paramètre de cookie de session HTTPOnly.Une solution de contournement quelque peu compliquée pour l'instant peut être trouvée ici, ce qui revient essentiellement à corriger manuellement Tomcat.Je ne trouve pas vraiment de moyen facile de le faire pour le moment, j'ai peur.

Pour résumer la solution, cela implique de télécharger la version 5.5 source, puis modifiez la source aux endroits suivants :

org.apache.catalina.connector.Request.java

//this is what needs to be changed
//response.addCookieInternal(cookie);

//this is whats new
response.addCookieInternal(cookie, true);
}

org.apache.catalina.connectorResponse.addCookieInternal

public void addCookieInternal(final Cookie cookie) {
addCookieInternal(cookie, false);
}

public void addCookieInternal(final Cookie cookie, boolean HTTPOnly) {

if (isCommitted())
return;

final StringBuffer sb = new StringBuffer();
//web application code can receive a IllegalArgumentException
//from the appendCookieValue invokation
if (SecurityUtil.isPackageProtectionEnabled()) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run(){
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(),
cookie.getValue(), cookie.getPath(),
cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
return null;
}
});
} else {
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(), cookie.getValue(),
cookie.getPath(), cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
}
//of course, we really need to modify ServerCookie
//but this is the general idea
if (HTTPOnly) {
sb.append("; HttpOnly");
}

//if we reached here, no exception, cookie is valid
// the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
// RFC2965 is not supported by browsers and the Servlet spec
// asks for 2109.
addHeader("Set-Cookie", sb.toString());

cookies.add(cookie);
}

Si votre serveur Web prend en charge la spécification Serlvet 3.0, comme Tomcat 7.0+, vous pouvez utiliser ci-dessous dans web.xml comme:

<session-config>
  <cookie-config>
     <http-only>true</http-only>        
     <secure>true</secure>        
  </cookie-config>
</session-config>

Comme mentionné dans la documentation :

Http uniquement:Spécifie si des cookies de suivi de session créés par cette application Web seront marqués comme httponly

Sécurisé:Spécifie si des cookies de suivi de session créés par cette application Web seront marqués comme sécurisés même si la demande qui a lancé la session correspondante utilise un http simple au lieu de HTTPS

Prière de se référer à comment définir httponly et le cookie de session pour l'application Web Java

il convient également de noter que l'activation de HttpOnly brisera les applets qui nécessitent un accès avec état à la JVM.

les requêtes http de l'applet n'utiliseront pas le cookie jsessionid et pourront être attribuées à un autre Tomcat.

Pour les cookies que je définis explicitement, j'ai opté pour l'utilisation SimpleCookie fourni par Apache Shiro.Il n'hérite pas de javax.servlet.http.Cookie, il faut donc un peu plus de jonglage pour que tout fonctionne correctement, mais il fournit un jeu de propriétés HttpOnly et fonctionne avec Servlet 2.5.

Pour définir un cookie sur une réponse, plutôt que de le faire response.addCookie(cookie) Tu as besoin de faire cookie.saveTo(request, response).

Dans Tomcat6, vous pouvez activer conditionnellement à partir de votre classe d'écoute HTTP :

public void contextInitialized(ServletContextEvent event) {                 
   if (Boolean.getBoolean("HTTP_ONLY_SESSION")) HttpOnlyConfig.enable(event);
}

Utiliser cette classe

import java.lang.reflect.Field;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import org.apache.catalina.core.StandardContext;
public class HttpOnlyConfig
{
    public static void enable(ServletContextEvent event)
    {
        ServletContext servletContext = event.getServletContext();
        Field f;
        try
        { // WARNING TOMCAT6 SPECIFIC!!
            f = servletContext.getClass().getDeclaredField("context");
            f.setAccessible(true);
            org.apache.catalina.core.ApplicationContext ac = (org.apache.catalina.core.ApplicationContext) f.get(servletContext);
            f = ac.getClass().getDeclaredField("context");
            f.setAccessible(true);
            org.apache.catalina.core.StandardContext sc = (StandardContext) f.get(ac);
            sc.setUseHttpOnly(true);
        }
        catch (Exception e)
        {
            System.err.print("HttpOnlyConfig cant enable");
            e.printStackTrace();
        }
    }
}

J'ai trouvé dans OWASP

<session-config>
  <cookie-config>
    <http-only>true</http-only>
  </cookie-config>
</session-config>

ceci est également un correctif pour le problème de sécurité "httponlycookies in config"

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top