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>
结果: