upload-labs靶场通关
文件上传漏洞学习
文件上传的种类有很多,我们借助github的一个开源项目来做文件上传漏洞的学习
靶场:upload-labs
靶场地址:
https://github.com/c0ny1/upload-labs.git
这个项目有一个绿色版的压缩包,解决了在部署这个靶场的时候会遇到的环境问题,算是比较方便的了
下载后解压得到:

第一部我们需要看的是使用说明

交代了我们如何启动这个项目
先运行modify_path.bat再启动phpstudy
直接启动:

由于是文件上传的漏洞,其实数据库开不开都可以,这里开不起来我猜测是压根没有数据库这个程序在目录里面
直接在浏览器访问

我们只是学习文件上传的原理,所以这里就不介绍思路,也就是不介绍黑盒测试中的文件上传如何测试的
这个项目的右上角有一个显示源码的按钮,可以直接做白盒审计

还有就是基础的木马连接我们也不介绍,一句话木马不在这个学习的范畴中,大家自行了解,这里方便看效果我们采用的是phpinfo探针来验证我们文件上传漏洞是否存在
代码:
// phpinfo.php
<?php phpinfo();
第一关
查看源码
发现提供的代码明显的注意到是一个js的代码:

这个代码是一个白名单,检测文件后缀名的一个逻辑,只要用户选择上传的文件的后缀不是允许的列表那就会被阻止上传

我们注意到这里其实只给了一个检查上传文件的后缀,没有告诉我们上传文件这个功能的逻辑,对于这种用前端js实现的文件类型检测,我们可以关闭浏览器的js代码功能来绕过这个文件类型的检测,只要把浏览器的js功能关掉,所有网页的js都会失效
这里用火狐浏览器举例子
按F12或者Ctrl+Shift+i就可以打开控制台

然后在右上角有三个点,点击之后点击设置

在高级设置这里就有一个禁用js的选项:

选择之后刷新页面,再上传我们的php文件上去

点击上传之后出现一张损坏的图片

文件就上传成功了,也没有提示上传文件有问题,大概是成功了,如何验证呢?其实可以右键这个图片看看能不能新标签打开


那么这个文件确实被上传成功且被服务器正确解析了,文件上传漏洞存在
虽然这个方法可以,但是也存在一个小问题,如果对方的上传逻辑也是用js写的,那么你如果把js禁用,那么这个文件也无法上传,这里就要介绍我们的第二种办法
利用抓包工具修改后缀
这里的逻辑是前端验证文件后缀类型,那我们可以在本地把php文件的后缀改成这里白名单的内容也就是jpg,这样文件就可以正常上传,然后利用我们的抓包工具,把上传的文件的后缀改成php就可以实现前端js验证的绕过了
这里我习惯用的抓包工具是yakit,也可以是用burpsuite,都差不多
准备好文件:

拦截包开启来:

选择jpg后缀的代码文件:

点击上传,回到yakit

成功抓到了一个请求数据包,然后把这个后缀改成php

然后放行,回到浏览器查看

文件成功上传,我们右键新标签打开看看

成功绕过前端的js文件后缀验证
完成这关之后我们需要清空上传的文件,以免造成干扰

第二关
第二关的源码就不是简单的js代码了,而是后端的php代码,这个时候再想用禁用js已经没用了,因为这里验证文件的逻辑是在后端而不是前端
而后端验证文件类型的代码:

其实是验证文件的mime类型,而巧的是,文件上传的mime类型对应的就是我们发送的请求包头部的content-type字段的内容,只要我们利用抓包工具,讲请求包中的content-type字段的值修改成允许的内容就可以了



上传成功:

一样右键打开

文件上传成功,简单的通过修改content-type的值绕过后端对传输的mime类型做验证
同样的我们需要清空上传的文件
第三关
这关同样还是php代码
不过这次也是验证的是文件的后缀
但是不同的地方在于
这次采用的是黑名单的逻辑
注意到其中其实只过滤了php这个后缀,其中如果中间件的错误配置可能导致有长格式的后缀同样可以解析为php代码,例如apache中就可以添加把什么后缀的文件作为php解析,例如phtml、php3、php5等
所以我们可以试试这个系统是否存在这个漏洞
先准备好这个文件:

直接上传就成功了,不用抓包


清空上传文件

第四关

这里禁止了很多可以解析的脚本后缀,我们可以另辟蹊径
采用.htaccess绕过
这是一个配置文件,会强制中间件在这个目录下安装这个文件配置文件里面的规则来解析
这里的黑名单里面也没有这个文件
所以我们可以上传这个文件
文件内容
<FilesMatch "phpinfo.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
这个代码的意思是把phpinfo.jpg看成php文件,这样服务器会把这个jpg文件当成php去解析
准备好文件:

上传:



上传成功,然后我们上传phpinfo.jpg这个文件,注意这个文件只是把后缀改成jpg而已


上传成功

清空文件
第五关
没有了转换小写的步骤
所以我们其实也可以试试大小写绕过
上传文件并抓包:

然后放包

大小写绕过成功:

清空文件

第六关
这次不演了已经,明显缺少了首尾去空的代码,这里大家要知道,空格本身也算一个字符,所以下面的比较是不一样的
".php" 不等于 ".php "
所以我们可以在上传文件抓包,然后在后缀加上空格


文件上传成功,而且也要注意
在windows中文件名不能以空格结尾,所以文件落地之后windows会自动把空格去掉
而在linux是允许文件名空格结尾的,所以能不能解析我们的脚本文件还有待商榷
我们靶机是在windows上运行的就没有这个顾虑
直接右键打开

绕过成功
清空文件

第七关

这里代码没有去掉点
只要我们上传文件为:
phpinfo.php.
那么经过代码处理之后,得到的后缀应该是
.
没错是个点
那这个点在黑名单里面吗,不在
但是在保存文件的时候会多一个点
也就是
phpinfo.php.
不过这个情况在windows可以绕过,linux不一定
在windows文件末尾不允许有点,所以在文件落地的时候系统会自动把这个点删掉
所以可以绕过
我们上传文件抓包试试

上传成功

打开试试

成功绕过
清空文件继续
第八关
这里的代码没有删掉::$DATA

这个标识符在啊windows的NTFS文件系统中指的是:
备用数据流(Alternate Data Stream,ADS)
这个解释起来比较复杂
只要知道在NTFS系统中,文件在保存的时候会忽略::$DATA
也就是说如果我们上传的是
phpinfo.php::$DATA
经过代码处理获取到的文件扩展名是:
.php::$DATA
很明显这个也不在黑名单内
所以可以绕过黑名单后缀的检测,且在windows系统依然会把啊这个文件保存为
phpinfo.php
尝试:

上传成功

访问一下:

清空文件继续
第九关
看上去这里排除了很多的后缀,不给攻击者机会
不过这里的代码还是有逻辑上的缺陷
这里删除点的操作只有一次,导致我们可以写两次点来绕过检测的逻辑
例如我们这里上传的是
phpinfo.php. .
那么经过这里的逻辑处理后

得到的结果是
.
没错就是一个点
那么这个点在黑名单里面吗?不在
所以就绕过了黑名单的检测
但是文件虽然可以上传,但是保存的名字却是
phpinfo.php.
会在文件名的末尾的多一个点,绝大部分情况在linux系统上无法把这个文件作为一个php代码去执行,但是在windows不一样,windows不允许文件以点结尾,系统会主动的把点删掉,也就是在windows保存的文件实际上是
phpinfo.php
那这样的话我们就可以解析了
操作很简单,我们先上传一个普通的phpinfo.php文件,然后抓包修改后缀

成功上传:


清空上传文件
第十关

一个很经典的情况,只要文件名中匹配到黑名单中的内容,就会删除这个字段,例如我们上传的是
phpinfo.php
经过处理会变成
info.
那么文件就会以上面这个结果保存,那么我们的php后缀没了,服务器也不会当成脚本去解析
但是和第九关一样的毛病,就是没有迭代的去检测和删除
这里只删除了一次,我们可以用经典的双写绕过这个逻辑
例如我修改我上传的文件为:
phpinfo.pphphp
那么经过处理就变成了
info.php
这样又可以作为脚本解析了
试一下


上传成功
打开看看:

ok,绕过成功
清空上传文件继续
第十一关

这里的话和前面不一样,从黑名单变成了白名单
也就是我们只能上传符合白名单后缀的文件了
但是注意到下面的保存文件的逻辑
发现是可以传递一个保存文件目录的参数

于是我们可以抓包看看这个参数

可以看到是长这样的参数
我们可以把这里的参数改成
../upload/phpinfo.php%00
这里的%00是空对象NULL的意思
程序在遇到这个的时候会自动截断后面的内容
也就是在保存文件的时候
会保存为
../upload/phpinfo.php
会把我们传递的实际文件名给截断
而这个验证的文件的逻辑就是在我们上传的实际的文件名上
只要我们实际传递的文件名字是jpg结尾的话就可以绕过验证
我们抓包上传试试

上传成功

右键打开看看

ok上传解析成功
清空文件继续
第十二关

这里的话和上面的类型方法一样
不过保存路径的参数从get传递变成post传递
只要继续抓包修改就可以了:

不过这里yakit不支持修改hex,导致我不能添加空对象
所以用burpsuite做
那这里就是bp原来的数据包内容


那么数据包长这样:

上面是用数据包的hex数据在phpinfo.php后面添00就好了
但是在bp有另一种方式就是利用解码工具
直接输入%00,然后选中%00右键,有一个转换所选内容的选项,选择url-decode就可以了

然后放包
上传成功:

右键打开看看

ok完成
清空文件继续

第十三关

这里开始变成了上传图片马并配合文件包含漏洞去解析我们的脚本
我们可以先分析一下这个文件包含漏洞

这里的逻辑就是如果存在file参数,这个参数一般指的是文件路径,只要传递了这个参数,就会include进来作为php代码解析
所以我们可以上传一个在白名单内的文件上去,然后利用这个漏洞去解析
分析完这个文件漏洞的内容,我们分析上传的源码

这里首先会对这个上传的文件的内容的头部字段进行判断,如果没有符合的字段那么就无法上传
其实就是简单的文件头判断,基础知识
我们只要在脚本的头部添加GIF89a这个头部就可以了

上传成功

然后我们右键打开,就会得到这个文件的地址

这里简单实验不用探究太多,这里的文件包含是允许远程文件包含的,我们可以直接使用这个url去包含这个脚本代码
传递参数file的值为刚才上传的的文件地址

以后遇到不能远程包含的可以猜一下相对路径
这里就成功利用文件包含漏洞上传图片木马
清空文件下一关
第十四关
这里依然使用头部字段来判断图片的类型

这不过判断的函数换了而已
所以原理还是一样的,判断头部的类型字段,我们一样加上GIF89a就可以了
然后抓包上传,利用文件包含解析我们的脚本代码即可




第十五关

只是又换了一种判断类型的函数罢了,但是都是读取文件头部字段的内容判断的,一样加上GIF89a就可以啦

清空继续下一关
第十六关
这里的主要逻辑是利用文件上传时候的mime类型和文件扩展名进行比较,然后还有一个关键的地方,他会把用户上传的图片做一次渲染
就是用户上传的图片还会被服务器重新渲染一次
在这个渲染的过程中我们图片中的脚本代码可能会消失
验证的方式可以上传我们的图片马上去,然后下载回来,就会发现我们的代码消失了,文件的大小也变得很小
这里就只简单的介绍图片马如何制作
用windows的cmd执行命令
准备好一张正常的图片和带有脚本代码的文件
copy chuxue.png/b+phpinfo.php/a phpinfo.png
输出的phpinfo.png就是我们的图片马
但是这里会二次渲染
这里依靠的是在二次渲染的时候会有些地方不变,我们可以在这个不变的地方添加我们的脚本代码,这个实现起来比较麻烦,网上有很多现成的二次渲染的图片可以利用,直接下载下来即可
图片就放在这里了:
https://cdn.jsdelivr.net/gh/wudiloveyh/my-image-bucket@main/images/20251210103613860.gif
下载下来之后直接上传即可
密码是zoe可以直接蚁剑连接
这里懒得开蚁剑了,直接hackbar看效果就可以了


二次渲染成功绕过
第十七关
这里的代码很少
但是注意到有一个temp_file的变量
然后

这里会把这个临时文件先保存到这个目录下,然后再去判断文件是否合法
不合法才执行删除操作
这里我们可以举个例子
在日常生活中存在我们在使用电脑删除文件的时候会提示删除失败,文件正在被什么程序使用中,导致我们不能删除这个文件
同样的,在这里服务器想要删除这个文件,如果我在删除之前打开了这个文件,他就无法删除,也就是我们在上传文件的同时访问这个文件,服务器就无法删除了
我们手速没那么快所以做不到上传的时候去访问
但是我们可以不断地重复的上传这个文件,然后我们只需要去访问这个文件这样就轻松很多了
实现这个方式有很多,python脚本跑一下
或者最简单的用bp不断上传这个文件即可
我们先抓这个上传文件的包

然后随便找个地方加上我们的payload变量
然后再在payload修改我们的参数

线程的话我的测试10个是够用的,觉得不够可以调整到20
现在开始发包


发包的同时访问这个文件,不断刷新就会有这个页面了
这里会有一个新的问题,如果我们再次刷新是不是就没了
为什么?因为bp一直在发包,所以服务器一直在删,导致访问了一次之后这个文件又被删除了
所以在合法的渗透的时候可以修改你的脚本,这个你们自己想吧,我可不能乱教
这里演示成功了
清空文件下一关
第十八关
代码很多
其实也是条件竞争
只不过这里的话只能上传图片了,得继续用到之前的文件包含漏洞
这里的条件竞争在于我们得在图片重命名之前去访问,否则会被删除
但是看上去是这样但是我直接上传图片马然后用文件包含漏洞一样可以通过,直接下一关吧
第十九关
这里其实就是允许我们指定保存的名字
但是一样不允许直接保存为php格式
不过没有对用户上传的文件内容做判断
只判断用户保存的文件名是否合法
这里利用的是
pathinfo($file_name,PATHINFO_EXTENSION);
来获取文件扩展名的,获取的是点后面的内容
而
这个函数在移动文件的时候会忽略末尾的/.
也就是我们可以把保存的名字写成
upload19.php/.
这样既能绕过黑名单,也能作为php文件保存


过关
第二十关
关键点在于

他会把这个字符串用点分隔并返回一个数组
然后就是保存文件名的逻辑

我们可以直接传递数组来打乱服务器的逻辑



右键查看

成功