安全攻防
morning
深入浅出 Gohttpserver Zip Slip 漏洞:从黑盒复现到白盒源码审计的闭环剖析
摘要
前言 在日常的 Web 安全研究中,文件上传与解压功能一直是高危漏洞的温床。从 2018 年 Snyk 安全团队首次披露 Zip Slip 漏洞以来,这种利用压缩包内文件名的路径穿越缺陷,广泛存在于各类支持解压的 Web 应用、中间件乃至开发框架中。攻击者通过构造包含 ../ 序列的恶意压缩包,可以绕过应用的上传目录限制,将任意文件写入服务器的敏感位置(如系统配置、计划任务、启动项等),进而实现从...
ZIP
upload
Web
Zip
Slip
Gohttpserver
8000
var
www
uploads
2026-11-12
1 阅读
约10分钟阅读
先知社区
字号:
前言 在日常的 Web 安全研究中,文件上传与解压功能一直是高危漏洞的温床。从 2018 年 Snyk 安全团队首次披露 Zip Slip 漏洞以来,这种利用压缩包内文件名的路径穿越缺陷,广泛存在于各类支持解压的 Web 应用、中间件乃至开发框架中。攻击者通过构造包含 ../ 序列的恶意压缩包,可以绕过应用的上传目录限制,将任意文件写入服务器的敏感位置(如系统配置、计划任务、启动项等),进而实现从“任意文件写入(Arbitrary File Write)”到“远程代码执行(RCE)”的致命跨越。 近期,笔者在对开源 HTTP 文件服务器 Gohttpserver 进行代码审计与安全测试时,完整复现了该漏洞的利用链路。Gohttpserver 是一款基于 Go 语言编写、广受好评的轻量级文件服务器,其内置的 --upload 功能极大地方便了日常的文件传输与共享。然而,正是因为其主打“轻量、便捷”,在安全防护的代码实现上存在致命的逻辑缺陷。 本文将以此漏洞为例,带来一次全景式、深度的漏洞分析。文章涵盖从环境搭建、黑盒漏洞复现、白盒源码溯源、自动化 EXP 工程化开发,到进阶的绝对路径变异测试与防御体系构建。旨在通过这一完整的闭环,为安全研究人员提供实战参考,为开发人员敲响警钟。 一、 漏洞背景与靶场环境搭建 1.1 漏洞概述与影响范围 本次复现的目标为 Gohttpserver v1.3.0 版本(经过笔者的代码比对,甚至在官方最新的 master 分支中,该缺陷依然未被完全修复)。当程序以 --upload 参数启动时,允许用户上传文件。若上传请求中包含 unzip=true 参数,服务端将自动调用内置逻辑解压该 ZIP 文件。 由于解压过程中缺乏对压缩包内部文件名的严格过滤,导致路径穿越(Zip Slip)。这是一个典型的未授权任意文件写入漏洞。在真实的生产环境中,由于很多开发者为了图方便,常常在内部网络或甚至公网直接开启 --upload 功能用于快速传文件,这无疑给攻击者敞开了大门。 1.2 多方式靶场环境搭建 为了高度还原攻击场景,我们在本地 Windows 环境下搭建靶机。这里提供两种方案: 方案 A:源码编译/二进制直接运行(推荐,最轻量) 访问官方 GitHub Releases 页面,下载对应版本的二进制文件 gohttpserver_1.3.0_windows_amd64.zip。 解压后,在当前目录打开 CMD 终端,执行启动命令: .\gohttpserver.exe --upload 方案 B:Docker 部署(适合 Linux 环境复现) 如果是 Linux 靶机,可直接拉取镜像并映射端口,注意必须将 --upload 作为启动参数传给容器内部: docker run -d --name ghs-vuln -p 8000:8000 codeskyblue/gohttpserver --upload 环境启动后,使用浏览器访问 http://127.0.0.1:8000。此时页面顶部呈现出清晰的 Upload 按钮,证明文件上传接口已成功开启,靶场准备就绪。 二、 漏洞黑盒复现:从任意写入到权限夺取 2.1 原理剖析:ZIP 文件结构与路径拼接 要理解 Zip Slip,必须先了解 ZIP 格式的底层结构。一个 ZIP 压缩包由多个文件条目(Entry)组成,每个条目内部不仅保存了文件的二进制数据,还保存了文件的相对路径名。正常情况下的路径可能是 images/avatar.png。 当 Web 应用执行解压时,通常会定义一个“解压目标目录”(如 /var/www/uploads/),然后遍历 ZIP 内部的文件名进行拼接(如 os.path.join('/var/www/uploads/', 'images/avatar.png'))。 但如果在构造 ZIP 时,恶意将内部文件名修改为 ../../../../etc/cron.d/pwn,拼接后的路径就变成了 /var/www/uploads/../../../../etc/cron.d/pwn,这就成功逃逸出了目标目录,实现了文件覆盖。 2.2 基础利用:验证任意文件写入 为了生成恶意 ZIP 包,我们直接编写一段 Python 脚本(利用内置的 zipfile 模块),将目标文件名硬编码为穿越路径: import zipfile with zipfile.ZipFile('evil.zip', 'w') as z: # 利用 ../ 逃逸,目标直指当前 Windows 用户的桌面 z.writestr('../../Desktop/pwned_by_zipslip.txt', 'This file was written outside the web root!\n') 随后,使用 curl 工具模拟上传操作。注意,这里必须加入表单字段 unzip=true 以触发服务端的解压逻辑: curl -F "file=@evil.zip" -F "unzip=true" http://127.0.0.1:8000/ 服务器顺利受理请求,并返回了 {"description":"success","success":true}。 紧接着,我们无需任何额外的权限验证,即可在 Windows 桌面上发现被写入的 pwned_by_zipslip.txt 文件,其内容与脚本中定义的完全一致。这就证明了:攻击者可以跨越 Web 根目录的限制,向任意位置写入任意内容。 2.3 进阶利用:通过系统启动项实现 RCE 任意文件写入通常只是前奏。在 Windows 系统中,如果攻击者能够将 .bat、.vbs 或 .exe 文件写入当前用户的启动目录(Startup Folder),那么只要用户重启或重新登录系统,该程序就会被自动执行。这是一种非常隐蔽的持久化后门手法。 我们修改 Python 脚本,将 Payload 替换为启动计算器的批处理命令: z.writestr('../../AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/calc.bat', 'start calc.exe\n') 重复上述上传动作后,按下 Win + R 键,输入 shell:startup 打开系统的启动文件夹。可以看到,名为 calc.bat 的恶意文件已经越权写入。双击运行,一个计算器赫然弹出,这标志着我们成功实现了从“任意文件写入”到“RCE”的完整攻击链闭环。 三、 白盒审计与底层逻辑剖析:寻找 Source 与 Sink 为了彻底弄清楚漏洞的机理,我们下载 Gohttpserver v1.3.0 的源码,使用 VS Code 打开,展开一次从“污点输入源(Source)”到“危险汇聚点(Sink)”的深度追踪。 3.1 定位漏洞入口(Source) 打开处理 HTTP 路由的核心文件 httpstaticserver.go,定位到第 279 行附近。这是文件上传与解压的入口逻辑: if req.FormValue("unzip") == "true" { er
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱