cookies - site - java cookie httponly
La cookie de sessionc de Tomcat 7 deshabilita http-only y es segura (3)
Tengo una aplicación web que se ejecuta en un servidor Tomcat 7. La cookie con identificación de sesión tiene por defecto las banderas HttpOnly
y Secure
. Quiero desactivar estos indicadores para la cookie JSESSIONID
. Pero no funcionará. Cambié esto en mi archivo web.xml
pero no funciona.
<session-config>
<session-timeout>20160</session-timeout>
<cookie-config>
<http-only>false</http-only>
<secure>false</secure>
</cookie-config>
</session-config>
Sé que esto es un riesgo de seguridad porque un atacante puede robar la cookie y secuestrar la sesión si ha encontrado un xss vuln.
La cookie JSESSIONID
debe enviar con HTTP y HTTPS y con solicitudes AJAX.
Editar:
He desactivado satisfactoriamente el indicador HttpOnly
agregando la siguiente opción al archivo conf/context.xml
:
<Context useHttpOnly="false">
....
</Context>
Además de la solución anterior de George Powell para Apache, si está en IIS, puede resolverlo de la siguiente manera:
- Instalar el módulo Reescribir URL de IIS
- Agregue lo siguiente a su web.config
<rewrite>
<outboundRules>
<rule name="RemoveSecureJessionID">
<match serverVariable="RESPONSE_Set-Cookie" pattern="^(.*JSESSIONID.*)Secure;(.*)$" />
<action type="Rewrite" value="{R:1}{R:2}" />
</rule>
</outboundRules>
</rewrite>
Esta solución era del blog de Pete Freitag
Como se indicó anteriormente, desde la reciente actualización de Chrome (enero de 2017), esto se ha convertido en un problema.
No encontré una solución en Tomcat para esto, pero si está usando apache como un proxy inverso, puede hacer lo siguiente:
Header edit* Set-Cookie "(JSESSIONID=.*)(; Secure)" "$1"
con mod_headers
que enviarán el encabezado en el camino de regreso para eliminar el indicador de seguridad. No es bonito, pero funciona si esto es crítico.
Si lees el código de tomcat , encontrarás:
// Always set secure if the request is secure
if (scc.isSecure() || secure) {
cookie.setSecure(true);
}
sessionCookieConfig.setSecure(false);
desactivar el indicador seguro en la cookie JSESSIONID con sessionCookieConfig.setSecure(false);
en un oyente o <cookie-config><secure>false</secure></cookie-config>
en el web.xml NO FUNCIONARÁ ya que Tomcat fuerza el indicador de seguridad a verdadero si la solicitud es segura (es decir, proviene de un https url o el puerto SSL).
Una solución es usar un filtro de solicitud para modificar la cookie JSESSIONID en la respuesta del servidor inmediatamente después de la creación de la sesión. Esta es mi implementación (muy básica):
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));
}
}
}
}
}
y en el 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>
Recuerde que al habilitar cookies no seguras, se evita una importante seguridad https. (Tuve que hacer eso para una transición sin problemas de http a https)