Tomcat 7 sessionid cookie 禁用 http-only 和安全

Posted

技术标签:

【中文标题】Tomcat 7 sessionid cookie 禁用 http-only 和安全【英文标题】:Tomcat 7 sessionid cookie disable http-only and secure 【发布时间】:2013-08-02 04:49:27 【问题描述】:

我有一个在 Tomcat 7 服务器上运行的 Web 应用程序。默认情况下,带有会话 id 的 cookie 具有标志 HttpOnlySecure。我想为JSESSIONID cookie 禁用这个标志。但它不会工作。我已经在我的web.xml 文件中更改了它,但它不起作用。

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

我知道这是一个安全风险,因为如果攻击者发现了 xss 漏洞,他就能够窃取 cookie 并劫持会话。

JSESSIONID cookie 应使用 HTTP 和 HTTPS 以及 AJAX 请求发送。

编辑:

我已通过将以下选项添加到 conf/context.xml 文件中成功禁用了 HttpOnly 标志:

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

【问题讨论】:

请关闭这个问题,你得到了答案。谢谢。 你知道如何禁用安全吗? Chrome 最近的更新让这一点变得非常重要! chromium.googlesource.com/chromium/src/+/… 【参考方案1】:

我没有在 Tomcat 中找到解决方案,但如果您使用 apache 作为反向代理,您可以这样做:

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

使用mod_headers,它将在返回的途中删除标头以删除安全标志。不漂亮,但如果这很关键,则可以使用。

【讨论】:

【参考方案2】:

如果您阅读code from tomcat,您会发现:

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

因此,如果请求是安全的(即来自https url 或 SSL 端口)。

一种解决方案是在会话创建后立即使用请求过滤器修改服务器响应上的 JSESSIONID cookie。 这是我的实现(非常基本):

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));
                
            
        
    


在 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>

请记住,启用不安全的 cookie 会绕过重要的 https 安全性!(我必须这样做才能从 http 顺利过渡到 https)

【讨论】:

不是过滤前缀并保护行中的任何位置,使用例如更健壮java.net.HttpCookie.parse(str) 然后使用 getter 方法提取适当的部分。【参考方案3】:

除了上面George Powell针对Apache的解决方案,如果你在IIS上,可以如下解决:

    安装 IIS URL 重写模块 将以下内容添加到您的 web.config 中

<rewrite>
  <outboundRules>
    <rule name="RemoveSecureJessionID">
      <match serverVariable="RESPONSE_Set-Cookie" pattern="^(.*JSESSIONID.*)Secure;(.*)$" />
      <action type="Rewrite" value="R:1R:2" />
    </rule>
  </outboundRules>
</rewrite>

此解决方案来自Pete Freitag's blog

如上所述,自最近的 Chrome 更新(2017 年 1 月)以来,这已成为一个问题。

【讨论】:

以上是关于Tomcat 7 sessionid cookie 禁用 http-only 和安全的主要内容,如果未能解决你的问题,请参考以下文章

单点登录

tomcatsessionId学习(未完待续)

相同域名下的cookie污染

nginx 在浏览器端保持cookie 一致

Cookie 与 SessionID 的本质

webbrowser如何获取cookie中的sessionid