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>
攻撃者がxss vulnを発見した場合、攻撃者がcookieを盗んでセッションを乗っ取ることができるため、これがセキュリティリスクであることはわかっています。
JSESSIONID
Cookieは、HTTPとHTTPS、およびAJAXリクエストで送信する必要があります。
編集:
conf/context.xml
ファイルに次のオプションを追加して、HttpOnly
フラグを正常に無効にしました。
<Context useHttpOnly="false">
....
</Context>
Tomcatでこれに対する解決策は見つかりませんでしたが、Apacheをリバースプロキシとして使用している場合は、次のことができます。
Header edit* Set-Cookie "(JSESSIONID=.*)(; Secure)" "$1"
mod_headers
は、セキュアフラグを削除するために戻る途中でヘッダーを変更します。きれいではありませんが、これが重要な場合は機能します。
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のセキュアフラグを非アクティブ化しようとすると、リクエストがセキュアな場合(つまり、 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にスムーズに移行するために、これを実行する必要がありました)