CSRF跨站请求伪造 漏洞修复
CSRF:
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。
修复思想:
可以在前端修复也可以在后端修复,一般前端和后端结合修复,这样修复的效果比较好。
提供两种修复方法:
1.在需要修复的页面生成随机数,并把这个随机数传到后端校验,校验通过即可继续下一步,校验不通过跳转指定页面或者返回
2.后端使用过滤器生成加密的随机数,并把随机数传到需要保护的页面接收,页面提交的时候把这个参数传递到后台做校验。
第二种修复方式示例 项目背景是:JSP+TOMCAT+SPRINGMVC
- 创建一个过滤器,请求全部通过这个过滤器放过静态资源,并生成加密的随机数 放入到缓存中
public class Sjs implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
//获取页面请求路径
String a=httpReq.getRequestURI();
if(a.contains(".css") || a.contains(".js") || a.contains(".png")|| a.contains(".jpg")){
chain.doFilter(request, response);
}else{
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>)
httpReq.getSession().getAttribute("csrfPreventionSaltCache");
if (csrfPreventionSaltCache == null){
csrfPreventionSaltCache = CacheBuilder.newBuilder()
.maximumSize(5000)
.expireAfterWrite(20, TimeUnit.MINUTES)
.build();
httpReq.getSession().setAttribute("csrfPreventionSaltCache", csrfPreventionSaltCache);
}
String salt = RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());
csrfPreventionSaltCache.put(salt, Boolean.TRUE);
System.out.println("初始化生成的随机数"+salt);
httpReq.setAttribute("csrfPreventionSalt", salt);
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
- web.xml配置
<!--生成随机数过滤器-->
<filter>
<filter-name>loadSalt</filter-name>
<filter-class>com.common.filter.LoadSalt</filter-class>
</filter>
<filter-mapping>
<filter-name>loadSalt</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
- 前台页面 login.jsp 接收 此处需要写道from表单里面,要不接收不到
<input type="hidden" name="csrfPreventionSalt" value="${csrfPreventionSalt}"/>
- 后端校验随机数
@RequestMapping(value = "/toLogin",method = RequestMethod.POST)
@ResponseBody
public JSONObject toMainPage(HttpServletRequest request,AdminEntity admin) throws ServletException, IOException {
/**
* 校验页面传过来的随机数
*/
HttpServletRequest httpReq = (HttpServletRequest) request;
String salt = (String) httpReq.getParameter("csrfPreventionSalt");
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>)
httpReq.getSession().getAttribute("csrfPreventionSaltCache");
if (csrfPreventionSaltCache != null &&
salt != null &&
csrfPreventionSaltCache.getIfPresent(salt) != null){
//不做处理 往下走
} else {
//重定向错误页面
httpReq.getRequestDispatcher("/common/error_page").forward(request, response);
}
备注
使用这种方式即可修复CSRF漏洞,如有不对 欢迎指出。