我有一个在Tomcat 7服务器上运行的Web应用程序。具有会话ID的cookie默认具有标志HttpOnly
和Secure
。我想为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>
我知道这是一个安全风险,因为攻击者能够窃取cookie并劫持会话,如果他找到了xss vuln。
JSESSIONID
cookie应该使用HTTP和HTTPS以及AJAX请求发送。
修改
我已成功通过在HttpOnly
文件中添加以下选项来禁用conf/context.xml
标记:
<Context useHttpOnly="false">
....
</Context>
答案 0 :(得分:1)
我没有在Tomcat中找到解决方案,但是如果你使用apache作为反向代理,你可以这样做:
Header edit* Set-Cookie "(JSESSIONID=.*)(; Secure)" "$1"
使用mod_headers
,它会在返回途中删除标题以删除安全标记。不漂亮,但如果这很重要,那就有效。
答案 1 :(得分:1)
如果您阅读code from tomcat,您会发现:
// Always set secure if the request is secure
if (scc.isSecure() || secure) {
cookie.setSecure(true);
}
因此,尝试在侦听器中使用sessionCookieConfig.setSecure(false);
或在web.xml中<cookie-config><secure>false</secure></cookie-config>
停用JSESSIONID cookie上的安全标志将无效,因为如果请求是安全的,Tomcat会将安全标志强制为true(即来自https网址或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)
答案 2 :(得分:-1)
除了上面针对Apache的George Powell的解决方案,如果您使用的是IIS,可以按如下方式解决:
<rewrite>
<outboundRules>
<rule name="RemoveSecureJessionID">
<match serverVariable="RESPONSE_Set-Cookie" pattern="^(.*JSESSIONID.*)Secure;(.*)$" />
<action type="Rewrite" value="{R:1}{R:2}" />
</rule>
</outboundRules>
</rewrite>
&#13;
此解决方案来自Pete Freitag's blog
如上所述,自最近的Chrome更新(2017年1月)以来,这已经成为一个问题。