OWASP企业安全API提供了一种非常好的选项,可以提供可靠的CSRF保护。实际上,CSRF很容易解决。OWASP ESAPI提供了以下实施CSRF保护的规范。
1. 生成新的CSRF令牌,并在登录时将其添加到用户中,然后将用户存储在http会话中。
这是默认ESAPI实现中完成的,它被存储为User
对象的成员变量,该对象被存储在session
中。
/this code is in the DefaultUser implementation of ESAPI
private String csrfToken = resetCSRFToken();
...
public String resetCSRFToken() {
csrfToken = ESAPI.randomizer().getRandomString(8, DefaultEncoder.CHAR_ALPHANUMERICS);
return csrfToken;
}
2. 在任何需要受保护的表单或URL中,将令牌添加为参数/隐藏字段。
对于任何需要CSRF保护的URL,应调用下面的addCSRFToken
方法。或者,如果您正在创建一个表单,或者有另一种呈现URL的技术(例如c:url
),那么请确保添加一个名为“ctoken
”且值为DefaultHTTPUtilities.getCSRFToken()
的参数或隐藏字段。
final static String CSRF_TOKEN_NAME = "ctoken";
public String addCSRFToken(String href) {
User user = ESAPI.authenticator().getCurrentUser();
if (user.isAnonymous()) {
return href;
}
String token = CSRF_TOKEN_NAME + "=" + user.getCSRFToken();
return href.indexOf( '?') != -1 ? href + "&" + token : href + "?" + token;
}
...
public String getCSRFToken() {
User user = ESAPI.authenticator().getCurrentUser();
if (user == null) return null;
return user.getCSRFToken();
}
3. 在服务器端对于那些受保护的操作,检查提交的令牌是否与会话中用户对象的令牌匹配。
确保从您的servlet
或spring
动作或jsf
控制器调用此方法,或者您使用的任何服务器端机制来处理请求。这应该在需要验证CSRF保护的任何请求上调用。请注意,当令牌不匹配时,它被认为是可能伪造的请求。
public void verifyCSRFToken(HttpServletRequest request) throws IntrusionException {
User user = ESAPI.authenticator().getCurrentUser();
if( request.getAttribute(user.getCSRFToken()) != null ) {
return;
}
String token = request.getParameter(CSRF_TOKEN_NAME);
if ( !user.getCSRFToken().equals( token ) ) {
throw new IntrusionException("Authentication failed", "Possibly forged HTTP request without proper CSRF token detected");
}
}
4. 在注销和会话超时时,用户对象将从会话中移除并销毁会话。
在这一步骤中,调用了注销。当这种情况发生时,请注意会话被无效化,并且当前用户对象被重置为匿名用户,从而删除了对当前用户的引用以及相应的 csrf 令牌。
public void logout() {
ESAPI.httpUtilities().killCookie( ESAPI.currentRequest(), ESAPI.currentResponse(), HTTPUtilities.REMEMBER_TOKEN_COOKIE_NAME );
HttpSession session = ESAPI.currentRequest().getSession(false);
if (session != null) {
removeSession(session);
session.invalidate();
}
ESAPI.httpUtilities().killCookie(ESAPI.currentRequest(), ESAPI.currentResponse(), "JSESSIONID");
loggedIn = false;
logger.info(Logger.SECURITY_SUCCESS, "Logout successful" );
ESAPI.authenticator().setCurrentUser(User.ANONYMOUS);
}
来源: http://www.jtmelton.com/2010/05/16/the-owasp-top-ten-and-esapi-part-6-cross-site-request-forgery-csrf/
希望这能帮到你。
Shishir
3.2.5.RELEASE
。 - Manish Kumar