web安全漏洞之三——csrf攻击

1. 什么是CSRF? javascript

      CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。java

 

2. CSRF漏洞的危害?web

        你这能够这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF可以作的事情包括:以你名义发送邮件,发消息,盗取你的帐号,甚至于购买商品,虚拟货币转帐......形成的问题包括:我的隐私泄露以及财产安全。ajax

 

3. CSRF攻击的原理?浏览器

    攻击经过在受权用户访问的页面中包含连接或者脚本的方式工做。CSRF是一种依赖web浏览器的、被混淆过的代理人攻击(deputy attack)。安全


 

 

4. 如何防止CSRF攻击?cookie

     服务端的CSRF方式方法不少样,但总的思想都是一致的,就是在客户端页面增长伪随机数做为token。session

 

具体实现方法:app

 在客户端页面里加上:dom

<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>

 

结果: