web-dev-qa-db-fra.com

Tomcat 7 sessionid cookie désactive le protocole http uniquement et sécurisé

J'ai une application Web qui s'exécute sur un serveur Tomcat 7. Le cookie avec l'identifiant de session a par défaut les indicateurs HttpOnly et Secure. Je souhaite désactiver ces indicateurs pour le cookie JSESSIONID. Mais ça ne marchera pas. J'ai changé cela dans mon fichier web.xml mais cela ne fonctionne pas.

<session-config>
    <session-timeout>20160</session-timeout>
    <cookie-config>
        <http-only>false</http-only>
        <secure>false</secure>
    </cookie-config>
</session-config>

Je sais que c'est un risque pour la sécurité, car un attaquant est capable de voler le cookie et de pirater la session s'il a trouvé un XSS VUL.

Le cookie JSESSIONID doit être envoyé avec HTTP et HTTPS et avec les requêtes AJAX.

Modifier:

J'ai correctement désactivé l'indicateur HttpOnly en ajoutant l'option suivante au fichier conf/context.xml:

<Context useHttpOnly="false">
....
</Context>
24
JEE-Dev

Tomcat n’a pas trouvé de solution à ce problème, mais si vous utilisez Apache comme proxy inverse, vous pouvez procéder comme suit:

Header edit* Set-Cookie "(JSESSIONID=.*)(; Secure)" "$1"

avec mod_headers qui supprimera l’en-tête sur le chemin de retour pour supprimer le drapeau sécurisé. Pas joli mais fonctionne si c'est critique.

1
George Powell

Si vous lisez le code de Tomcat vous trouverez:

// Always set secure if the request is secure
if (scc.isSecure() || secure) {
    cookie.setSecure(true);
}

Donc, essayer de désactiver l'indicateur sécurisé sur le cookie JSESSIONID avec sessionCookieConfig.setSecure(false); dans un écouteur ou <cookie-config><secure>false</secure></cookie-config> dans le web.xml NE FONCTIONNE PAS car Tomcat force l'indicateur sécurisé à true si la demande est sécurisée (c'est-à-dire à partir d'une URL https ou du port SSL) .

Une solution consiste à utiliser un filtre de requête pour modifier le cookie JSESSIONID sur la réponse du serveur immédiatement après la création de la session. Voici mon implémentation (très basique):

public class DisableSecureCookieFilter implements javax.servlet.Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if(request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
            request = new ForceUnsecureSessionCookieRequestWrapper((HttpServletRequest) request, (HttpServletResponse) response);
        }

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() { }

    public static class ForceUnsecureSessionCookieRequestWrapper extends HttpServletRequestWrapper {
        HttpServletResponse response;

        public ForceUnsecureSessionCookieRequestWrapper(HttpServletRequest request, HttpServletResponse response) {
            super(request);
            this.response = response;
        }

        @Override
        public HttpSession getSession(boolean create) {
            if(create) {
                HttpSession session = super.getSession(create);
                updateCookie(response.getHeaders("Set-Cookie"));
                return session;
            }
            return super.getSession(create);
        }

        @Override
        public HttpSession getSession() {
            HttpSession session = super.getSession();
            if(session != null) {
                updateCookie(response.getHeaders("Set-Cookie"));
            }

            return session;
        }

        protected void updateCookie(Collection<String> cookiesAfterCreateSession) {
            if(cookiesAfterCreateSession != null && !response.isCommitted()) {
                // search if a cookie JSESSIONID Secure exists
                Optional<String> cookieJSessionId = cookiesAfterCreateSession.stream()
                                                        .filter(cookie -> cookie.startsWith("JSESSIONID") && cookie.contains("Secure"))
                                                        .findAny();
                if(cookieJSessionId.isPresent()) {
                    // remove all Set-Cookie and add the unsecure version of the JSessionId Cookie
                    response.setHeader("Set-Cookie", cookieJSessionId.get().replace("Secure", ""));

                    // re-add all other Cookies
                    cookiesAfterCreateSession.stream()
                            .filter(cookie -> !cookie.startsWith("JSESSIONID"))
                            .forEach(cookie -> response.addHeader("Set-Cookie", cookie));
                }
            }
        }
    }

}

et dans le web.xml:

<filter>
    <filter-name>disableSecureCookieFilter</filter-name>
    <filter-class>com.xxxx.security.DisableSecureCookieFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>disableSecureCookieFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

N'oubliez pas que l'activation des cookies non sécurisés contourne une sécurité https importante! (je devais le faire pour une transition en douceur de http à https)

0
PCO