web安全基础——CSRF

来源:互联网 发布:淘宝内衣模特 编辑:程序博客网 时间:2024/04/28 15:14

  主要是CSRF(Cross Site Request Forgery)的基础知识,作为对自己学习的总结。无实践,无干货。

一、CSRF的概念

1. 概念

  CSRF是指跨站请求伪造。跨站:指的是存在一个受害者网站Alice:www.example.com,一个攻击者网站Mallory:www.mallory.com。在Alice网上有一个敏感操作,其全部参数可以被mallory知晓,不过这个操作需要用户登录,也就是说这个参数中包含识别用户身份的cookie。这样,Mallory是无法完成消息伪造的。但是, 如果在Mallory网站和Alice网站在同一浏览器进程中打开,Mallory 在发送向Alice的请求时,浏览器将携带用户身份的session cookie信息,这样Mallory向Alice发送的请求就是合法的。换句话说,只要用户等了Alice网站,并且在同一个浏览器中打开连接:www.example.com/index.php?a=dedecd&b=huhjioijo就可以完成敏感操作,cookie信息已经被浏览器自动发送(临时cookie,浏览器关闭时失效)。

  ps:所以,最终,请求时受害者自己发送的。

2. CSRF出现的原因

  CSRF漏洞形成原因很多,我个人觉得来自浏览器特性和开发者两个方面。从浏览器和http角度,主要原因有(个人看书总结,望大家指出错误):
  (1)HTTP是无状态协议,也就是说对于众多用户发送的请求不能识别谁发的。所以,从浏览器也就是前端角度引入了cookie,通过这cookie写入一些随机的不可预测的值来识别用户。从服务器后台角度引入了session,同样是随机的不可预测的。这两个值对应该对第三方保密,即除了用户和服务器不能谁也不能拿到到这两个数据。
  (2) session有两种,一种以参数形式写在了url中,另一种存于cookie中,以存在cookie中的为例说明问题。session一般有两种,一种是存在本地的”永久session”(存在过期时间),另一种是临时session,只要浏览器关闭session就会失效。对于临时session,对于一个设置了session的网站,在第二次以及之后的请求中,浏览器会自动在请求中添加包含session信息的cookie。例如,在www.example.com网站(Alice)存在敏感的操作,各项存在可被攻击者得到。这样,只要用户Bob登录了Alice网站,Mallory发送了一个连接,Bob打开时,浏览器得知链接是Alice网站,会自动添加cookie信息,于是,Bob的账户被攻击。

二、CSRF的防范策略

1. 通过Http Referer字段

  在关键请求中添加Referer字段。这样,在服务端检查request中携带的Referer,如果携带的Referer的域是Alice的,即以.example.com开头,则说明请求来自自己的网站。反之,如果Referer字段的域不是来自Alice,说明请求是伪造的,应拦截。

  这种策略的基础:不能对浏览器的发送请求的字段的Referer字段做修改。(难道在局域网内也不能修改)

  弊端:其实这中防御方式感觉是扯淡:第一,在局域网中可以修改;第二,部分老的浏览器可以修改Referer字段;第三,Referer可能会泄露用户隐私,用户可能会禁用掉。

  一个疑问:对于不是在第三方网站构造的请求,即不是通过一个Mallory网站上的链接指向request请求。而是直接向受害者发送请求的链接,例如通过QQ,那么测试的Referer是什么?

  正确的攻击姿势:在一个网站上添加一个<img>标签,例如<img src=”http://www.mybank.com/sendFunds.do?acctId=123456”>。这样,在浏览器加载html代码时,就会把上面的url当做图片地址来加载。如果此时用户正好登陆了上面url对应的网站,则url加载的时候对应的请求被发出(携带了cookie),即跨站请求伪造完成。

  摘抄一段利用Referer过滤的代码,源自https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/>CSRF攻击的应对之道.

 // 从 HTTP 头中取得 Referer 值 String referer=request.getHeader("Referer");  // 判断 Referer 是否以 bank.example 开头 if((referer!=null) &&(referer.trim().startsWith(“bank.example”))){     chain.doFilter(request, response);  }else{     request.getRequestDispatcher(“error.jsp”).forward(request,response);  }
 HttpServletRequest req = (HttpServletRequest)request;  HttpSession s = req.getSession();  // 从 session 中得到 csrftoken 属性 String sToken = (String)s.getAttribute(“csrftoken”);  if(sToken == null){     // 产生新的 token 放入 session 中    sToken = generateToken();     s.setAttribute(“csrftoken”,sToken);     chain.doFilter(request, response);  } else{     // 从 HTTP 头中取得 csrftoken     String xhrToken = req.getHeader(“csrftoken”);     // 从请求参数中取得 csrftoken     String pToken = req.getParameter(“csrftoken”);     if(sToken != null && xhrToken != null && sToken.equals(xhrToken)){         chain.doFilter(request, response);     }else if(sToken != null && pToken != null && sToken.equals(pToken)){         chain.doFilter(request, response);     }else{         request.getRequestDispatcher(“error.jsp”).forward(request,response);     }  }

2. 通过token信息

  另一种信息是通过在请求的Url中加入token信息。CSRF的关键是从第三方网站发送请求时,浏览器会自动添加上cookie信息,所以这种请求就是针对此提出的,即通过不是在cookie中的信心来确认请求来源。集体做法是:
  在请求的Url链接中添加一个随机的不可推测值作为token。这样,在用户登录后,将token信息写入服务端的session,每次用提请求时,比较和请求参数中的token是否和url中的token一致。

  这种策略的基础:token信息的不可推测性,只要不是来自自己的网站,攻击者不可能伪造得到此token值。

  弊端:一是对于所有请求都要把token值写到url中,异常麻烦,容易遗漏;二是对于用户可以添加内容网页,攻击者可以添加一个自己的网址,这样点击之后,token会发送到攻击者网站,所以token泄露;三是对于使用了Referer的网站,在发送请求时浏览器会自动添加上当前请求所在的网站的url,所以token信息会随着Referer值传给攻击者。

3. 通过Http自定义属性

  其实这种方法和前面的差不多,都是添加一个参数到请求中,这里是把参数添加到Http自定义属性中去。实现技术:XMLHttpRequest请求,这种方法使用不多。

  写在最后,对于这类漏洞何如高效挖掘,证明存在和证明不存在。总不能人工审计吧,如何自动化搞定(证是或证否),且待后续学习…

0 0