搜索结果

×

搜索结果将在这里显示。

upload-labs靶场通关

文件上传漏洞学习

文件上传的种类有很多,我们借助github的一个开源项目来做文件上传漏洞的学习

靶场:upload-labs

靶场地址:

https://github.com/c0ny1/upload-labs.git

这个项目有一个绿色版的压缩包,解决了在部署这个靶场的时候会遇到的环境问题,算是比较方便的了

下载后解压得到:

image-20251209185414218

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

image-20251209185436570

交代了我们如何启动这个项目

先运行modify_path.bat再启动phpstudy

直接启动:

image-20251209185650002

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

直接在浏览器访问

http://localhost

image-20251209185826077

我们只是学习文件上传的原理,所以这里就不介绍思路,也就是不介绍黑盒测试中的文件上传如何测试的

这个项目的右上角有一个显示源码的按钮,可以直接做白盒审计

image-20251209190012354

还有就是基础的木马连接我们也不介绍,一句话木马不在这个学习的范畴中,大家自行了解,这里方便看效果我们采用的是phpinfo探针来验证我们文件上传漏洞是否存在

代码:

// phpinfo.php
<?php phpinfo();

第一关

查看源码

发现提供的代码明显的注意到是一个js的代码:

image-20251209190057038

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

image-20251209190215140

我们注意到这里其实只给了一个检查上传文件的后缀,没有告诉我们上传文件这个功能的逻辑,对于这种用前端js实现的文件类型检测,我们可以关闭浏览器的js代码功能来绕过这个文件类型的检测,只要把浏览器的js功能关掉,所有网页的js都会失效

这里用火狐浏览器举例子

按F12或者Ctrl+Shift+i就可以打开控制台

image-20251209190450227

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

image-20251209190541905

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

image-20251209190623196

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

image-20251209191135254

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

image-20251209191158959

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

image-20251209191257329

image-20251209191307770

那么这个文件确实被上传成功且被服务器正确解析了,文件上传漏洞存在

虽然这个方法可以,但是也存在一个小问题,如果对方的上传逻辑也是用js写的,那么你如果把js禁用,那么这个文件也无法上传,这里就要介绍我们的第二种办法

利用抓包工具修改后缀

这里的逻辑是前端验证文件后缀类型,那我们可以在本地把php文件的后缀改成这里白名单的内容也就是jpg,这样文件就可以正常上传,然后利用我们的抓包工具,把上传的文件的后缀改成php就可以实现前端js验证的绕过了

这里我习惯用的抓包工具是yakit,也可以是用burpsuite,都差不多

准备好文件:

image-20251209192020906

拦截包开启来:

image-20251209192036012

选择jpg后缀的代码文件:

image-20251209192058798

点击上传,回到yakit

image-20251209192127657

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

image-20251209192218678

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

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

image-20251209192315282

成功绕过前端的js文件后缀验证

完成这关之后我们需要清空上传的文件,以免造成干扰

image-20251209192430741

第二关

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

而后端验证文件类型的代码:

image-20251209192621496

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

image-20251209192753723

image-20251209192817138

image-20251209192840304

上传成功:

image-20251209192859614

一样右键打开

image-20251209192927035

文件上传成功,简单的通过修改content-type的值绕过后端对传输的mime类型做验证

同样的我们需要清空上传的文件

第三关

这关同样还是php代码

不过这次也是验证的是文件的后缀

但是不同的地方在于

这次采用的是黑名单的逻辑

注意到其中其实只过滤了php这个后缀,其中如果中间件的错误配置可能导致有长格式的后缀同样可以解析为php代码,例如apache中就可以添加把什么后缀的文件作为php解析,例如phtml、php3、php5等

所以我们可以试试这个系统是否存在这个漏洞

先准备好这个文件:

image-20251209193619855

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

image-20251209193650378

image-20251209193709970

清空上传文件

image-20251209193728361

第四关

image-20251209193755464

这里禁止了很多可以解析的脚本后缀,我们可以另辟蹊径

采用.htaccess绕过

这是一个配置文件,会强制中间件在这个目录下安装这个文件配置文件里面的规则来解析

这里的黑名单里面也没有这个文件

所以我们可以上传这个文件

文件内容

<FilesMatch "phpinfo.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

这个代码的意思是把phpinfo.jpg看成php文件,这样服务器会把这个jpg文件当成php去解析

准备好文件:

image-20251209201350710

上传:

image-20251209201415562

image-20251209201420838

image-20251209201428019

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

image-20251209201510871

image-20251209201538229

上传成功

image-20251209202625361

清空文件

第五关

没有了转换小写的步骤

所以我们其实也可以试试大小写绕过

上传文件并抓包:

image-20251209195544421

然后放包

image-20251209195641070

大小写绕过成功:

image-20251209195701874

清空文件

image-20251209195731374

第六关

这次不演了已经,明显缺少了首尾去空的代码,这里大家要知道,空格本身也算一个字符,所以下面的比较是不一样的

".php" 不等于 ".php "

所以我们可以在上传文件抓包,然后在后缀加上空格

image-20251209200001658

image-20251209200011702

文件上传成功,而且也要注意

在windows中文件名不能以空格结尾,所以文件落地之后windows会自动把空格去掉

而在linux是允许文件名空格结尾的,所以能不能解析我们的脚本文件还有待商榷

我们靶机是在windows上运行的就没有这个顾虑

直接右键打开

image-20251209200358450

绕过成功

清空文件

image-20251209200416081

第七关

image-20251209214030433

这里代码没有去掉点

只要我们上传文件为:

phpinfo.php.

那么经过代码处理之后,得到的后缀应该是

.

没错是个点

那这个点在黑名单里面吗,不在

但是在保存文件的时候会多一个点

也就是

phpinfo.php.

不过这个情况在windows可以绕过,linux不一定

在windows文件末尾不允许有点,所以在文件落地的时候系统会自动把这个点删掉

所以可以绕过

我们上传文件抓包试试

image-20251209214214086

上传成功

image-20251209214231174

打开试试

image-20251209214240532

成功绕过

清空文件继续

第八关

这里的代码没有删掉::$DATA

image-20251209212424706

这个标识符在啊windows的NTFS文件系统中指的是:

备用数据流(Alternate Data Stream,ADS)

这个解释起来比较复杂

只要知道在NTFS系统中,文件在保存的时候会忽略::$DATA

也就是说如果我们上传的是

phpinfo.php::$DATA

经过代码处理获取到的文件扩展名是:

.php::$DATA

很明显这个也不在黑名单内

所以可以绕过黑名单后缀的检测,且在windows系统依然会把啊这个文件保存为

phpinfo.php

尝试:

image-20251209213134543

上传成功

image-20251209213153278

访问一下:

image-20251209213211331

清空文件继续

第九关

看上去这里排除了很多的后缀,不给攻击者机会

不过这里的代码还是有逻辑上的缺陷

这里删除点的操作只有一次,导致我们可以写两次点来绕过检测的逻辑

例如我们这里上传的是

phpinfo.php. .

那么经过这里的逻辑处理后

image-20251209194646807

得到的结果是

.

没错就是一个点

那么这个点在黑名单里面吗?不在

所以就绕过了黑名单的检测

但是文件虽然可以上传,但是保存的名字却是

phpinfo.php.

会在文件名的末尾的多一个点,绝大部分情况在linux系统上无法把这个文件作为一个php代码去执行,但是在windows不一样,windows不允许文件以点结尾,系统会主动的把点删掉,也就是在windows保存的文件实际上是

phpinfo.php

那这样的话我们就可以解析了

操作很简单,我们先上传一个普通的phpinfo.php文件,然后抓包修改后缀

image-20251209195137114

成功上传:

image-20251209195206669

image-20251209195019224

清空上传文件

第十关

image-20251209214613540

一个很经典的情况,只要文件名中匹配到黑名单中的内容,就会删除这个字段,例如我们上传的是

phpinfo.php

经过处理会变成

info.

那么文件就会以上面这个结果保存,那么我们的php后缀没了,服务器也不会当成脚本去解析

但是和第九关一样的毛病,就是没有迭代的去检测和删除

这里只删除了一次,我们可以用经典的双写绕过这个逻辑

例如我修改我上传的文件为:

phpinfo.pphphp

那么经过处理就变成了

info.php

这样又可以作为脚本解析了

试一下

image-20251209215046500

image-20251209215056337

上传成功

打开看看:

image-20251209215113819

ok,绕过成功

清空上传文件继续

第十一关

image-20251210082221258

这里的话和前面不一样,从黑名单变成了白名单

也就是我们只能上传符合白名单后缀的文件了

但是注意到下面的保存文件的逻辑

发现是可以传递一个保存文件目录的参数

image-20251210082443019

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

image-20251210082850814

可以看到是长这样的参数

我们可以把这里的参数改成

../upload/phpinfo.php%00

这里的%00是空对象NULL的意思

程序在遇到这个的时候会自动截断后面的内容

也就是在保存文件的时候

会保存为

../upload/phpinfo.php

会把我们传递的实际文件名给截断

而这个验证的文件的逻辑就是在我们上传的实际的文件名上

只要我们实际传递的文件名字是jpg结尾的话就可以绕过验证

我们抓包上传试试

image-20251210083339084

上传成功

image-20251210083432896

右键打开看看

image-20251210083519175

ok上传解析成功

清空文件继续

第十二关

image-20251210083619535

这里的话和上面的类型方法一样

不过保存路径的参数从get传递变成post传递

只要继续抓包修改就可以了:

image-20251210083750149

不过这里yakit不支持修改hex,导致我不能添加空对象

所以用burpsuite做

那这里就是bp原来的数据包内容

image-20251210091447238

image-20251210091601840

那么数据包长这样:

image-20251210091631297

上面是用数据包的hex数据在phpinfo.php后面添00就好了

但是在bp有另一种方式就是利用解码工具

直接输入%00,然后选中%00右键,有一个转换所选内容的选项,选择url-decode就可以了

image-20251210091846537

然后放包

上传成功:

image-20251210091907404

右键打开看看

image-20251210092026409

ok完成

清空文件继续

image-20251210092042196

第十三关

image-20251210092130107

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

我们可以先分析一下这个文件包含漏洞

image-20251210093418080

这里的逻辑就是如果存在file参数,这个参数一般指的是文件路径,只要传递了这个参数,就会include进来作为php代码解析

所以我们可以上传一个在白名单内的文件上去,然后利用这个漏洞去解析

分析完这个文件漏洞的内容,我们分析上传的源码

image-20251210093639787

这里首先会对这个上传的文件的内容的头部字段进行判断,如果没有符合的字段那么就无法上传

其实就是简单的文件头判断,基础知识

我们只要在脚本的头部添加GIF89a这个头部就可以了

image-20251210093909602

上传成功

image-20251210093926630

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

image-20251210093954787

这里简单实验不用探究太多,这里的文件包含是允许远程文件包含的,我们可以直接使用这个url去包含这个脚本代码

传递参数file的值为刚才上传的的文件地址

image-20251210094045505

以后遇到不能远程包含的可以猜一下相对路径

这里就成功利用文件包含漏洞上传图片木马

清空文件下一关

第十四关

这里依然使用头部字段来判断图片的类型

image-20251210094509233

这不过判断的函数换了而已

所以原理还是一样的,判断头部的类型字段,我们一样加上GIF89a就可以了

然后抓包上传,利用文件包含解析我们的脚本代码即可

image-20251210094910524

image-20251210094919492

image-20251210094928438

image-20251210094947720

第十五关

image-20251210095120451

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

image-20251210095253813

清空继续下一关

第十六关

这里的主要逻辑是利用文件上传时候的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看效果就可以了

image-20251210103740793

image-20251210103751967

二次渲染成功绕过

第十七关

这里的代码很少

但是注意到有一个temp_file的变量

然后

image-20251210105009289

这里会把这个临时文件先保存到这个目录下,然后再去判断文件是否合法

不合法才执行删除操作

这里我们可以举个例子

在日常生活中存在我们在使用电脑删除文件的时候会提示删除失败,文件正在被什么程序使用中,导致我们不能删除这个文件

同样的,在这里服务器想要删除这个文件,如果我在删除之前打开了这个文件,他就无法删除,也就是我们在上传文件的同时访问这个文件,服务器就无法删除了

我们手速没那么快所以做不到上传的时候去访问

但是我们可以不断地重复的上传这个文件,然后我们只需要去访问这个文件这样就轻松很多了

实现这个方式有很多,python脚本跑一下

或者最简单的用bp不断上传这个文件即可

我们先抓这个上传文件的包

image-20251210105457329

然后随便找个地方加上我们的payload变量

然后再在payload修改我们的参数

image-20251210105543344

线程的话我的测试10个是够用的,觉得不够可以调整到20

现在开始发包

image-20251210105625364

image-20251210105641041

发包的同时访问这个文件,不断刷新就会有这个页面了

这里会有一个新的问题,如果我们再次刷新是不是就没了

为什么?因为bp一直在发包,所以服务器一直在删,导致访问了一次之后这个文件又被删除了

所以在合法的渗透的时候可以修改你的脚本,这个你们自己想吧,我可不能乱教

这里演示成功了

清空文件下一关

第十八关

代码很多

其实也是条件竞争

只不过这里的话只能上传图片了,得继续用到之前的文件包含漏洞

这里的条件竞争在于我们得在图片重命名之前去访问,否则会被删除

但是看上去是这样但是我直接上传图片马然后用文件包含漏洞一样可以通过,直接下一关吧

第十九关

这里其实就是允许我们指定保存的名字

但是一样不允许直接保存为php格式

不过没有对用户上传的文件内容做判断

只判断用户保存的文件名是否合法

这里利用的是

 pathinfo($file_name,PATHINFO_EXTENSION);

来获取文件扩展名的,获取的是点后面的内容

image-20251210112435897

这个函数在移动文件的时候会忽略末尾的/.

也就是我们可以把保存的名字写成

upload19.php/.

这样既能绕过黑名单,也能作为php文件保存

image-20251210112702158

image-20251210112712002

过关

第二十关

关键点在于

image-20251210112850520

他会把这个字符串用点分隔并返回一个数组

然后就是保存文件名的逻辑

image-20251210113037182

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

image-20251210113811031

image-20251210113847825

image-20251210113555489

右键查看

image-20251210113909113

成功

请先 登录 再评论