1. 什么是CSRF?
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
2. CSRF漏洞的危害?
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。
3. CSRF攻击的原理?
攻击通过在授权用户访问的页面中包含链接或者脚本的方式工作。CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)。
4. 如何防止CSRF攻击?
服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数作为token。
具体实现方法:
在客户端页面里加上:
<script type="text/javascript"> (function(){ function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e16]+1e16).replace(/[01]/g,b)}; var csrftoken = b(); Cookies.set('CSRF-TOKEN', csrftoken, { expires: 7 }); jQuery.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRF-Token", csrftoken); } } }); })(); </script>
服务端过滤器:
package com.comp.sip.web.csrf;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import com.comp.sip.SipHelper;
import java.io.IOException;
import java.util.regex.Pattern;
public class CsrfFilter implements Filter {
private static final String CSRF_TOKEN = "CSRF-TOKEN";
private static final String X_CSRF_TOKEN = "X-CSRF-TOKEN";
private RequestMatcher requireCsrfProtectionMatcher = null;
private static String ALLOWEDMETHOD = "GET|HEAD|TRACE|OPTIONS";
public void init(FilterConfig filterConfig) throws ServletException {
String ams = filterConfig.getInitParameter("allowed");
if (ams != null || ams.trim().length() > 0)
ALLOWEDMETHOD = ams;
requireCsrfProtectionMatcher = new CustomRequiresCsrfMatcher(ALLOWEDMETHOD);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
} else {
throw new IOException();
}
HttpServletRequest hsr = (HttpServletRequest) request;
if (requireCsrfProtectionMatcher.matches(hsr)) {
String csrfTokenValue = hsr.getHeader(X_CSRF_TOKEN);
if (csrfTokenValue == null || csrfTokenValue.trim().length() == 0)
csrfTokenValue = hsr.getParameter(X_CSRF_TOKEN);
final Cookie[] cookies = hsr.getCookies();
String csrfCookieValue = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(CSRF_TOKEN)) {
csrfCookieValue = cookie.getValue();
}
}
}
if (csrfTokenValue == null || !csrfTokenValue.equals(csrfCookieValue)) {
return;
}
}
}
chain.doFilter(request, response);
}
public void destroy() {
}
public static final class DefaultRequiresCsrfMatcher implements RequestMatcher {
private final Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
public boolean matches(HttpServletRequest request) {
return !allowedMethods.matcher(request.getMethod()).matches();
}
}
public static final class CustomRequiresCsrfMatcher implements RequestMatcher {
private final Pattern allowedMethods;
public CustomRequiresCsrfMatcher(String allowed) {
allowedMethods = Pattern.compile("^(" + allowed + ")$");
}
public boolean matches(HttpServletRequest request) {
return !allowedMethods.matcher(request.getMethod()).matches();
}
}
public interface RequestMatcher {
public boolean matches(HttpServletRequest request);
}
}
然后在web.xml里配置过滤器:
<filter> <filter-name>XsrfFilter</filter-name> <filter-class>com.comp.sip.web.csrf.CsrfFilter</filter-class> <init-param> <description>不需要进行csrf防御的http method</description> <param-name>allowed</param-name> <param-value>GET|HEAD|TRACE|OPTIONS</param-value> </init-param> </filter> <filter-mapping> <filter-name>XsrfFilter</filter-name> <url-pattern>/message/replyMsg.do</url-pattern> </filter-mapping>
结果: