upload文件上传靶场
这段时间看了一下文件上传漏洞的知识点,然后把upload的靶场打完了,记录了一下过关的路程。文章最后还有一张我对于文件上传漏洞的总结哦。
前言
我用的这个文件上传的靶场,是c0ny1的upload-labs。下载地址贴一下:https://github.com/c0ny1/upload-labs
听我学长的话,咱下载完成一个东西后,先看看它的readme文档或者其他要求的文档。
这个靶场的php环境推荐5.2.17,那我就乖乖把我的php调到这个版本,然后开始打靶场罗。
1、PASS-01——js绕过
上传php后缀文件时,弹出不允许上传,查看源代码,发现这是前端js拦截。

那就先上传一个正常的11.jpg,然后用burp抓包将11.jpg改成22.php,然后将图片的内容改成想要的PHP文件内容就可以啦。修改点击发送,发现已经上传成功啦。

2、PASS-02——content-type检测绕过
上传2.php时,提示文件类型不正确,查看源码,发现对content-type做了限制。
那就先上传2.php,然后用burp抓包,将content-type改成其中一个合法的就行。
抓包获取到的:

修改成合法的(image/jpeg或image/png或image/gif):

上传成功:

3、PASS-03——其他后缀名绕过
上传2.php,发现出现提示信息:

这很有可能是设置了黑名单,查看一下源代码。
既然源代码中只设置了这几种可执行后缀的黑名单,那就直接尝试上传其他可执行后缀的文件
1 | $deny_ext = array('.asp','.aspx','.php','.jsp'); |
上传2.php3文件,抓包,可显示图片路径,成功上传:

4、PASS-04——.htaccess解析绕过
上传php文件,查看源代码,发现还是设置了黑名单,只是这次好像把能禁用的后缀都禁用掉了:
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini"); |
发现它没有禁止上传.htaccess后缀,那就尝试上传这个,
.htaccess的内容为(.htaccess不能起名字,它就是.htaccess文件):
1 | SetHandler application/x-httpd-php |
(代码意思:无论上传哪种类型的文件,他就会被解析为.php)
所以,我们先上传.htaccess文件:

此时,再上传一张正常的jpg图片,利用Burp抓包,将1.jpg图片的内容替换成php代码,点击发送:

此时,访问1.jpg就会转换成php文件:

5、PASS-05——点空格点绕过
上传一个php代码,显示此文件类型不允许上传。查看源代码,黑名单限制,这题把.htaccess后缀也限制了。感觉都被限制了呀,但好像那些限制条件都只限制了一次,先去除文件后缀点再去除空格。若此时设置为文件名点空格点(即2.php. .),删掉一个点一个空格,还剩下2.php.
1 | $file_name = deldot($file_name);//删除文件名末尾的点 |
Burp抓包,修改2.php为2.php. .文件成功上传:

6、PASS-06——大小写绕过
上传php文件不被允许上传,查看源代码,仔细观察,发现这题居然没有设置大小写转换,那我就直接尝试大小写绕过啦。其实PASS-05的思路这题同样适用。
抓包,修改2.php为2.Php,成功上传:


7、PASS-07——空格绕过
php文件不允许上传,我们还是来看源代码吧,一看没有写去掉末尾空格的代码呀,那就直接空格绕过上传咯。Burp抓包,将2.php修改成2.php 发现成功上传

8、PASS-08——点绕过
直接上源代码,发现这题没有设置删除文件末尾的点的代码,那就在文件后面加点绕过啦。
这里点绕过的原理其实是利用windows的特性,在windows下,2.php.和2.php的效果是一样的。
Burp抓包,将2.php修改成2.php.成功上传。

9、PASS-09——::$DATA绕过上传
查看源代码,发现这里没有去除字符串::$DATA的代码,于是我们可以使用::$DATA绕过上传。
Burp抓包,将2.php修改成2.php::$DATA,发现成功上传


10、PASS-10——点空格点绕过
这关的源代码和第五关一样,所以采用点空格点就能绕过。
Burp抓包,将2.php修改为2.php. .成功上传

11、PASS-11——双写绕过
查看源代码,发现将图片的后缀用空白代替了。这时可以双写后缀名绕过。
1 | $file_name = str_ireplace($deny_ext,"", $file_name); |
用burp抓包,将2.php修改成2.pphphp成功上传

12、PASS-12——目录可控%00截断绕过(GET)
上传一个php文件,出现提示信息:

说明可能设置了白名单,查看源代码:
1 | $ext_arr = array('jpg','png','gif'); |
看到的确是设置了白名单,可以采用%00截断。
满足%00截断的两个条件:
1 | 条件1:php版本小于5.3.4 |

上传1.jpg,burp抓包,将save_path=../upload/修改为save_path=../upload/2.php%00,并且将jpg图片内容改为php内容,这样就相当于上传了2.php,并对后面的图片1.jpg进行了截断,成功上传

13、PASS-13——目录可控%00截断绕过(POST)
上传一个php文件,也显示只允许上传.jpg|.png|.gif类型文件。应该也是设置了白名单,查看源代码。这题的代码好像跟PASS-12差不多耶,先抓包看看,发现明显不同,上一题中的save_path路径以GET方式直接显示出来了,这里的save_path明显是POST方式。所以我们可以用POST方式的%00截断绕过。
两者的区别就是GET会自行解码,POST不会自行解码,所以POST方式的需要我们手动将%00经过decoode进行解码。
上传正常的jpg图片,Burp抓包,将../upload/修改为../upload/2.php%00,将jpg图片内容改为php内容,
然后选中%00按如下方式进行decode,解码成功之后%00会看不见,实际存在。

修改完成之后,点击发送,文件上传成功:

14、PASS-14——图片马绕过
本题要求:
1 | 上传图片马到服务器。 |
首先,制作图片马,在cmd中输入:
1 | copy 1.jpg/b+2.php/a 3.jpg |
生成包含webshell的3.jpg,直接上传3.jpg。
本题直接说明存在文件上传漏洞:

于是,上传之后,抓包,查看文件路径,

访问:

.png和.gif的后缀按照同样的方法制作图片马,并上传,能够成功访问:


15、PASS-15——getimagesize()图片马绕过
本关卡要求和上一关一样,首先查看源代码,发现有:
1 | $info = getimagesize($filename); |
getimagesize()函数会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求的。还是制作图片马上传即可。
制作图片马:
1 | copy 1.jpg/b+2.php/a 3.jpg |
分别上传,使用文件包含漏洞访问上传的图片马中的恶意代码:

16、PASS-16——exif_imagetype()图片马绕过
查看源码,exif_imagetype() 读取一个图像的第一个字节并检查其签名。
1 | $image_type = exif_imagetype($filename); |
本题需要开启php_exif模块

解题过程跟PASS-14和PASS-15一样,利用图片马上传绕过。
使用文件包含漏洞访问上传的图片马中的恶意代码:

17、PASS-17——图片二次渲染绕过
查看源码,发现图片经过了二次渲染。
1 | $im = imagecreatefromjpeg($target_path); |
imagecreatefromjpeg()函数,二次渲染是会创建一个新图像,导致图片马的数据丢失,上传图片马失败。所以要绕过imagecreatefromjpeg()函数进行上传。
关于gif的图片比较简单:
1 | 原理大致就是先上传一张正常的gif图片,将经过二次渲染的图片下载下来。然后利用工具找到两张图片渲染前后相同的部分,在相同部分写入webshell,再上传,即可成功绕过二次渲染。 |
具体步骤,首先,先上传一张正常的图片2.gif,将生成的32421.gif与原来的2.gif进行对比,查找渲染前后没有变化的部分。用一个可以查看十六进制的工具,我用的是winhex,将两张图片放进去,然后在查看处选择同步和比较。

这种白色的都是相同的,黑色部分则是不相同的。

只需要在2.gif的白色部分,即相同部分,插入恶意代码即可。

将其另存为22.gif,然后上传到服务器。利用文件包含漏洞即可绕过二次渲染。

至于jpg和png的,用上面这种方法是不行的,你会发现当你在比较渲染前后图片相同位置时,都是一些断断速速的点,根本插不进去的。这里具体的实现还是要利用一些写的脚本,将webshell插入进去。具体实现可以参考[这篇文章](upload-labs之pass 16详细分析 - 先知社区 (aliyun.com))
18、PASS-18——条件竞争绕过
查看源代码,发现本关卡是先将图片上传到服务器,再判断文件后缀是否在白名单,在则重命名,不在则删除。
1 | $upload_file = UPLOAD_PATH . '/' . $file_name; |
那我们就可以利用条件竞争来绕过。看看谁比谁快(bushi)。如果我们在上传上去的一瞬间访问这个文件,那他就不能对这个文件删除。这就相当于我们打开了一个文件,然后再去删除这个文件,就会提示这个文件在另一程序中打开无法删除。
上传一个2.php文件,burp抓包,将其发送给测试器Intruder,在position处清除负载。在payloads选择没有负载(Null payloads),有效载荷选项(payload options)选择无限期地重复(continue indefinitely)。在options处将线程数调高一点,如20。


点击攻击,这边在不停的上传:

我们打开另一个浏览器,访问2.php的路径,找不到我就一直访问,总有你还没来得及删掉的时候吧,然后我第二次就直接访问到啦:

19、PASS-19——条件竞争绕过
查看源代码,这关是检查了后缀名,然后上传,然后再进行二次渲染。所以我们只能上传图片马,然后配合解析漏洞(即访问地址加上include.php?file)即可成功绕过。
这题的上传路径有点问题,没有上传到upload/upload目录下,所以我们先打开PASS-19的myupload.php修改一下路径:

先制作一张包含恶意代码的图片马:
1 | copy 1.jpg/b+2/php/a 3.jpg |
然后上传3.jpg,并用burp抓包,其他操作跟PASS-18一样,发送到测试器,对它不断进行上传。

然后打开另一浏览器,不断访问图片地址(http://192.168.56.1:8099/upload/include.php?file=upload/3.jpg)

20、PASS-20——/.绕过
查看源代码,本题是设置了一个黑名单,然后发现有一个move_uploaded_file()函数。这个函数有个特性,就是会忽略文件末尾的 /. (或者用.也可以)
也就是说,我们先上传一张正常的图片1.jpg,然后用burp抓包,将upload-19.jpg改为2.php/.此时会上传2.php文件,并自动忽略/.后面的内容,即忽略1.jpg

还有一个方法。这个函数的img_path是由post参数的save_name控制的。所以可以利用POST方式的%00截断。
先上传一张正常的图片1.jpg,并用burp抓包,找到save_name,将upload-19.jpg改为2.php%00,并将%00进行url的decode,上传成功

21、PASS-21——数组绕过
查看源码,如果是数组的话就不会检查后缀。
1 | if (!in_array($ext, $allow_suffix)) { |
采用第一个数组和第二个数组拼接
1 | $file_name = reset($file) . '.' . $file[count($file) - 1]; |
那就可以利用数组绕过。
在这里,数组的下标不能相邻就行,比如第一个数组下标为0,第二个就要大于1,才不会被拼接起来。
首先,构造表单,能够数组上传,然后上传一张正常的照片1.jpg

Burp抓包,点击发送,成功上传

22、总结
最后,放上一张关于文件上传漏洞的总结图
