Wie konfiguriere ich HttpOnly-Cookies in Tomcat / Java-Webanwendungen?

Antworten:

66

httpOnly wird ab Tomcat 6.0.19 und Tomcat 5.5.28 unterstützt.

Siehe den Änderungsprotokolleintrag für Fehler 44382.

Der letzte Kommentar zu Fehler 44382 lautet: "Dies wurde auf 5.5.x angewendet und wird ab 5.5.28 enthalten sein." Es scheint jedoch nicht, dass 5.5.28 veröffentlicht wurde.

Die httpOnly-Funktionalität kann für alle Webanwendungen in conf / context.xml aktiviert werden :

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

Meine Interpretation ist, dass es auch für einen einzelnen Kontext funktioniert, indem es auf den gewünschten Kontexteintrag in conf / server.xml gesetzt wird (auf die gleiche Weise wie oben).

jt.
quelle
Ich verwende Tomcat 5.5.36. Dieses useHttpOnly-Attribut scheint nur für JSESSIONID-Cookies zu funktionieren. Ich habe dieses Flag in allen meinen Kontexten hinzugefügt, um sicherzustellen, dass alle Cookies am Ende mit "; HttpOnly" versehen werden. Es war jedoch nur JSESSIONID wie folgt betroffen: Set-Cookie=JSESSIONID = 25E8F ...; Pfad = / custompath; HttpOnly mycustomcookie1 = xxxxxxx; Pfad = / mycustomcookie2 = 1351101062602; Pfad = / mycustomcookie3 = 0; Pfad = / mycustomcookie4 = 1; Pfad = /; Secure mycustomcookie5 = 4000; Läuft ab = Sa, 22.10.2022 17:51:02 GMT; Pfad = / Mache ich sonst noch etwas falsch?
L. Holanda
Diese Dokumentation scheint darauf hinzudeuten, dass das Flag useHttpOnly nur das Sitzungs-ID-Cookie betrifft: tomcat.apache.org/tomcat-5.5-doc/config/… Ich denke, dies war eine Stop-Gap-Maßnahme zum Schutz des Sitzungscookies. Die Möglichkeit, Cookies als HttpOnly zu kennzeichnen, war
jt.
19

Update: Das JSESSIONID-Zeug hier ist nur für ältere Container. Bitte verwenden Sie die aktuell akzeptierte Antwort von jt, es sei denn, Sie verwenden <Tomcat 6.0.19 oder <Tomcat 5.5.28 oder einen anderen Container, der keine HttpOnly JSESSIONID-Cookies als Konfigurationsoption unterstützt.

Verwenden Sie zum Setzen von Cookies in Ihrer App

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

In vielen Webanwendungen ist das wichtigste Cookie jedoch die Sitzungskennung, die vom Container automatisch als JSESSIONID-Cookie festgelegt wird.

Wenn Sie nur dieses Cookie verwenden, können Sie einen ServletFilter schreiben, um die Cookies auf dem Weg nach draußen zurückzusetzen und JSESSIONID auf HttpOnly zu zwingen. Die Seite unter http://keepitlocked.net/archive/2007/11/05/java-and-httponly.aspx http://alexsmolen.com/blog/?p=16 schlägt vor, Folgendes in einen Filter aufzunehmen.

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

Beachten Sie jedoch, dass dadurch alle Cookies überschrieben werden und nur festgelegt wird, was Sie hier in diesem Filter angeben.

Wenn Sie zusätzliche Cookies zum JSESSIONID-Cookie verwenden, müssen Sie diesen Code erweitern, um alle Cookies im Filter zu setzen. Dies ist keine großartige Lösung für mehrere Cookies, aber möglicherweise eine akzeptable schnelle Lösung für das Nur-JSESSIONID-Setup.

Bitte beachten Sie, dass im Laufe der Zeit ein böser versteckter Fehler auf Sie wartet, wenn Sie diesen Filter vergessen und versuchen, ein anderes Cookie an einer anderen Stelle in Ihrem Code zu setzen. Natürlich wird es nicht eingestellt.

Dies ist jedoch wirklich ein Hack. Wenn Sie Tomcat verwenden und es kompilieren können, werfen Sie einen Blick auf Shabaz 'hervorragenden Vorschlag, die HttpOnly-Unterstützung in Tomcat zu patchen.

Cheekysoft
quelle
8
Dieser Code entfernt das Flag; Secure, wodurch die Verwendung von https sinnlos wird.
Hendrik Brummermann
In Servlet 3.0-Beschwerdeanwendungsservern kann ich die HttpOnly- und Secure-Flags für das Sitzungscookie (JSESSIONID) setzen, indem ich der web.xml Folgendes hinzufüge: <session-config> <cookie-config> <secure> true </secure> < http-only> true </ http-only> </ cookie-config> </ session-config>
Roger Jin
@ RogerJin bitte poste dies als neue Antwort, diese 6 Jahre alte Antwort wird zunehmend veraltet.
Cheekysoft
Seien Sie vorsichtig mit setHeader, da alle vorherigen Header mit demselben Namen gelöscht werden. Beispielsweise kann das JSESSIONID-Cookie gelöscht werden, wenn Sie ein benutzerdefiniertes Cookie festlegen. Verwenden Sie stattdessen response.addHeader () für benutzerdefinierte Cookies
dpinya
14

Bitte achten Sie darauf, das "; sichere" Cookie-Flag in https-Sessions nicht zu überschreiben. Dieses Flag verhindert, dass der Browser das Cookie über eine unverschlüsselte http-Verbindung sendet, wodurch die Verwendung von https für legitime Anforderungen grundsätzlich sinnlos wird.

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);
    }
}
Hendrik Brummermann
quelle
2
Beachten Sie, dass die Verwendung request.isSecure()nicht immer korrekt ist. Stellen Sie sich einen Knoten mit Lastenausgleich hinter dem LB vor, der die SSL-Beschleunigung ausführt. Die Anforderung vom Browser an den Load Balancer erfolgt über HTTPS, während die Anforderung zwischen Load Balancer und dem tatsächlichen Server über einfaches HTTP erfolgt. Dies führt request.isSecure()dazu false, dass der Browser SSL verwendet.
Anton
13

Wenn Ihr Webserver die Serlvet 3.0-Spezifikation wie Tomcat 7.0+ unterstützt, können Sie Folgendes verwenden web.xml:

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

Wie in den Dokumenten erwähnt:

HttpOnly : Gibt an, ob von dieser Webanwendung erstellte Sitzungsverfolgungscookies als HttpOnly markiert werden

Sicher : Gibt an, ob von dieser Webanwendung erstellte Sitzungsverfolgungscookies als sicher markiert werden, selbst wenn die Anforderung, die die entsprechende Sitzung initiiert hat, einfaches HTTP anstelle von HTTPS verwendet

Bitte beachten Sie , wie Httponly und Session - Cookie für Java - Web - Anwendung setzen

Alireza Fattahi
quelle
10

Für Sitzungscookies scheint es in Tomcat noch nicht unterstützt zu werden. Siehe Fehlerbericht. Unterstützung für HTTPOnly-Sitzungscookie-Parameter muss hinzugefügt werden . Eine etwas komplizierte Problemumgehung finden Sie hier komplizierte Problemumgehung , die sich im Wesentlichen auf das manuelle Patchen von Tomcat beschränkt. Ich fürchte, ich kann derzeit keinen einfachen Weg finden, dies zu tun.

Um die Problemumgehung zusammenzufassen, müssen Sie die 5.5- Quelle herunterladen und die Quelle an den folgenden Stellen ändern:

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);
}
Shabaz
quelle
2

Es sollte auch beachtet werden, dass durch das Aktivieren von HttpOnly Applets beschädigt werden, die einen zustandsbehafteten Zugriff auf das JVM erfordern.

Die Applet-http-Anforderungen verwenden nicht das jsessionid-Cookie und werden möglicherweise einem anderen Kater zugewiesen.

Pete Brumm
quelle
2

Für Cookies, die ich explizit setze , habe ich auf SimpleCookie von Apache Shiro umgestellt . Es erbt nicht von javax.servlet.http.Cookie, daher ist etwas mehr Jonglieren erforderlich, damit alles ordnungsgemäß funktioniert. Es stellt jedoch einen Eigenschaftssatz HttpOnly bereit und funktioniert mit Servlet 2.5.

Um ein Cookie für eine Antwort zu setzen, response.addCookie(cookie)müssen Sie dies tun cookie.saveTo(request, response).

Jesse Vogt
quelle
2

Ich habe in OWASP gefunden

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

Dies wurde auch für das Sicherheitsproblem "httponlycookies in config" behoben

Ravipati Praveen
quelle
1

In Tomcat6 können Sie von Ihrer HTTP-Listener-Klasse aus bedingt aktivieren:

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

Verwenden dieser Klasse

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();
        }
    }
}
Systemplanet
quelle