CSRF漏洞

原理

CSRF(Cross-Site Request Forgery)跨站请求伪造,是一种利用用户在某网站的身份认证信息,通过伪造请求来执行恶意操作的攻击方式。

  1. 受害者登录:受害者先登录一个网站(如网上银行、社交平台等),并且此时浏览器保存了该网站的登录认证信息(比如 cookie)。

  2. 攻击者构造恶意请求:攻击者构造一个恶意网页或链接,链接中包含一个目标网站的请求(如更改账户密码、转账等)。该请求看似合法,但实际上是恶意构造的。

  3. 受害者点击链接:受害者在不知情的情况下点击了攻击者诱导的链接,或访问了包含恶意请求的网页。

  4. 伪造请求被发送:由于受害者已经登录目标网站,浏览器会自动附带上该网站的 Cookie 等身份认证信息,目标网站接收到这个伪造的请求时,认为这个请求来自合法用户,从而执行了恶意操作。

利用条件

  1. 需要伪造请求数据包。

  2. 无过滤防护,或有过滤防护但可以绕过。

  3. 受害者触发 (钓鱼)。

无防护

演示靶场:发货 100 模板 T11 - 电子商城模板(PC)-> 后台用户管理

BurpSuite抓一个添加管理员的包:

然后右键选择 ->Engagement tools->Generate CSRF Poc->Options->Include auto-submit script

复制生成的html代码:

将其放到攻击者网站目录:

引诱目标人员在同一浏览器访问这个页面,即可攻击成功。

此时在后台发现管理员已添加成功。

若目标管理员未登录后台,或者后台 cookie 已经过期,需要重新登录,那么将无法完成攻击。

有防护- Referer 同源

演示靶场:Zblog 后台用户管理

按照上面步骤操作后,显示非法访问:

查看网站源码,在 cmd.php 中找到了检测 referer 的函数 CheckIsRefererValid, 按住 Ctrl 点击,跳转到定义如下:

 function CheckHTTPRefererValid()
 {
     global $bloghost;
     $referer = GetVars('HTTP_REFERER', 'SERVER'); // 获取请求中的referer
     if (trim($referer) === '') {
         return true;
    }
     $s = $bloghost;
     $s = str_replace(':80/', '/', $s);
     $s = str_replace(':443/', '/', $s);
     if (stripos($referer, $s) === false) {
         return false;
    }
 ​
     return true;
 }

绕过referer匹配的策略:

目标网站:http://22.22.22.22/
攻击者:http://11.11.11.11/

  1. 部分匹配

如上面这个 zblog 靶场的 referer 检测就是 php 的 stripos 函数,该函数 stripos () 是查找字符串在另一字符串中第一次出现的位置,并且不区分大小写的。

此时将 referer 修改为这样即可绕过检测:

http://11.11.11.11/http://22.22.22.22/add.html

怎么构造这个 referer 呢?在你的网站下创建这样一个目录即可。这里讲思路,实际上实现不了这个,因为不能创建 http: //这样的目录。

也可以针对不严谨的代码逻辑绕过。上面zblog 网站源码中,若 referer 为空也返回 true。有时候重新打开浏览器访问的时候就是没有 referer,所以不是代码有问题,只是逻辑不严谨。所以可以在add.html中设置referer为空。

<meta name="referrer" content="no-referrer">
  1. 完全匹配

只能配合文件上传漏洞(上传到目标网站目录,这时候 referer 肯定就是目标网站本身)和XSS漏洞(利用JS代码发送add.html)绕过。

有防护-Token校验

绕过策略(代码逻辑不严谨):

  1. 将 Token 参数值复用
    即一个 Token 可以一直使用或者使用多次。

  2. 将 Token 参数删除
    不验证 Token 的时候。

  3. 将 Token 参数值置空
    Token 为空的时候也可以通过验证的情况。