文件上传漏洞upload-labs靶场练习(buuctf平台upload-las-linux)

靶场下载

1
https://github.com/Tj1ngwe1/upload-labs

靶场在这里下载,放到phpstudy环境里面直接可以跑的

访问会有个报错提示,忽略即可

如果不想自建环境,直接去buuctf上面拿现成的靶机即可

Pass-01-前端js检查

直接传php文件不允许,有白名单

看源码这里有个checkFile()函数,前端js检测的,直接删掉即可

尝试上传可能会提示没有upload文件,不知道是不是我这边靶场没下载完整,反正没有就自己新建一个即可

成功

Pass-02-MIME检测

怀疑是MIME检测,抓个包

改个类型,好像jpg不行,改成image/png上传成功

Pass-03-黑名单绕过

先传一个普通的

发现是黑名单过滤

文件名改成php3即可

虽然上传成功了,但是访问不了

查看页面源代码发现无法被解析

这是apache服务器的原因

更改Apache httpd.conf 配置文件,添加.php3 和 phtml,取消前面注释,保存并退出

这样才可以,我自己的环境就不改配置文件了,直接去buuctf上面的环境打这题,因为它的apache是配置了的

这里有个坑要注意一下,就是我们上传上去的文件名不是存储到服务器上面的文件名,服务器上面的文件名是重命名了的,看右边的返回包里的img地址

这样就顺利解出了这道题

Pass-04-.htaccess绕过

可能还是黑名单绕过

看提示发现第三题的绕过方法都不行了,这个确实也是黑名单绕过

但是我们发现.htaccess的后缀名没有在黑名单里面

这个绕过方式是有前提条件的:它只适用于apache(1.mod_rewrite模块开启。2.AllowOverride All)

不过这题这个条件肯定是开了的,就是让我们去利用的

先上传一个名为.htaccess的文件,内容如下:

1
SetHandler application/x-httpd-php

这样所有文件都会当成php来解析

注意传这个文件的时候要把后缀前面的1删掉

然后再上传一个1.jpg,内容为webshell代码

(这里刚开始试了好几次1.jpg都访问不了,不知道什么原因再试一次成功了,然后重新开了一台靶机一次也就成功,证明方法是没问题的)

Pass-05-大小写绕过

这题看提示还是黑名单

但是把.htaccess也拉黑了

和之前的源码对比发现把输入转换为小写的函数没有了,那就大小写绕过

没有意外就是大小写绕过

Pass-06-空格绕过(windows)

这题的话也是黑名单,上一题的大小写函数补上了,看源码发现首尾去空的函数不在,可以用空格绕过

利用Windows系统的文件名特性。文件名最后增加空格,写成2.php ,上传后保存在Windows系统上的文件名最后的一个空格会被去掉,实际上保存的文件名就是2.php

注:这题的话靶机必须是windows的,在linux上面无效

加个空格传上去然后访问一下图片地址即可

Pass-07-点绕过

看这题的源码发现少了一个删除文件末尾的点的函数

利用windows特性,会自动去掉后缀名中最后的”.”,可在后缀名中加”.”绕过(仅限windows)

然后我们就可以访问upload文件夹里面的2.php文件了(后面没有点,因为windows会自动去掉)

我这边使用了buuctf靶机是linux的,上面这种方法当然不行,因为是windows的特性,但是发现在linux中后面加一个点的文件可以被保存,并且可以被执行,所以这个点绕过同样适用于linux,只不过原理不一样(windows是加点之后可以绕过黑名单,保存到服务器上会自动把点删掉,linux是加点之后绕过黑名单,这个点不会被删掉,但是文件依然可以以点号前面的文件格式运行

如下图,访问的是2.php.

可以发现这样的文件后缀是可以以正常的php文件运行的

Pass-08-::$DATA绕过(windows)

这题还是一个windows特性——::$DATA文件流特性绕过

在window的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名

例如:”phpinfo.php::$DATA”Windows会自动去掉末尾的::$DATA变成”phpinfo.php”

如果代码中没有对::$DATA进行处理,就是黑名单过滤的时候,这种方法是可以用的

发包的时候改一下文件名如图

上传后的文件是没有::$DATA的,所以访问2.php即可

Pass-09-点+空格+点绕过(windows)

先看源码

代码先是去除文件名前后的空格,再去除文件名最后所有的.,再通过strrchar函数来寻找.来确认文件名的后缀,但是最后保存文件的时候没有重命名而使用的原始的文件名,导致可以利用1.php. .(点+空格+点)来绕过

所以这题是点+空格+点绕过

然后访问2.php的地址即可

注意这题也是windows特性,只能在windows靶机里面成功,刚刚虽然说了点绕过可以在linux里面成功,但是这里还有空格,这个linux是不行的

Pass-10-双写绕过

这题还是黑名单绕过,但是看源码可以发现

它将黑名单里的后缀名替换为空且只替换一次,因此可以用双写绕过

Pass-11-%00截断(get)

查看源码发现使用了白名单,只允许jpg,png,gif文件的上传,所以前面使用的方法都不适用,然后我们发现路径img_path函数是让文件位置(save_path)加时间随机数(rand)的方法生成文件位置和文件名称,所以这里我们可以尝试在save_path的地方使用%00的方法截断后面的语句,burpsuite抓包发现,是可以更改save_path的,不过此方法是需要满足截断条件的即php版本小于5.3.4,php的magic_quotes_gpc为OFF状态

我们抓包后需要改两个地方

这里改成2.jpg因为有白名单

这里改成../upload/2.php%00

就是这样一个请求,但是这里发现上传出错

怀疑buuctf上面的php版本高于5.3.4

看一下之前传上去的phpinfo看到是7.2.21

所以这题用buuctf平台做不了,自己搭一个php版本小于5.3.4的靶场就可以了,这里不演示了,解题方法就是这样的

Pass-12-%00截断(post)

这题很上一题的区别就是一个,这里是通过post传参的,而上一题是get方式,通过源码看出

但是因为POST不会像GET一样对%00进行自动解码,所以需要我们手动对它进行解码

解码之后是看不到%00的

然后传上去即可

Pass-13-图片马绕过

这题直接告诉我们了需要上传图片码

之前学习文件上传漏洞的时候介绍过,就是用16进制编辑器把一句话木马写在图片末尾

上传成功之后,这个图片马需要配合文件包含漏洞,因为直接访问图片不会以php代码执行

据说这样也可以做一个图片马

点击这里进入文件包含漏洞

在地址栏包含图片的地址即可

Pass-14-getimagesize()图片马

这题是用getimagesize函数判断文件类型,还是可以图片马绕过,方法和上一题一样

Pass-15-exif_imagetype()图片马

这里用到php_exif模块来判断文件类型,用图片马绕过,方法和前两题相同

Pass-16-二次渲染绕过

查看源码,发现它对图片进行了二次渲染,即PHP的imagecreatefromgif函数。我们上传上去的图片它会把这张图渲染一次,如果我们是图片马,那么藏在里面的webshell就会被渲染,渲染类似编码,那么我们的webshell就无效了

这是我们上传的图片马

我们上传之后再从服务器下载下来

可以发现最后的webshell消失了

在源码中我们还发现它分别对png,jpg,gig单独进行渲染

那么我们的办法就是上传一个正常的图片给它渲染,然后看一下它渲染之后的图片里面有没有什么地方是没有被渲染的,如果有,我们就把webshell放到这个地方,这个地方的webshell就不会被渲染了。

一般情况下文件头部的几行代码是不被渲染的,但是如果修改头部的几行代码会导致图片损坏,但是这题损坏的文件上传上去依然没事,直接可以成功

虽然提示不是png格式的图片,但是依然上传成功了

对于二次渲染,上传gif是最方便的,因为比如png还需要crc校验

这里不演示了,详细的分析看这篇文章

Pass-17-条件竞争

这题是条件竞争

看源码知道他是先把文件上传到服务器之后,在服务器上进行文件判断,看一下是否在白名单,如果在白名单就重命名保存,如果不在就删除。

我们就可以利用这样一个时间差,我们不断向服务器传文件,它判断需要时间,越多文件需要判断它需要的时间就越多,它没判断完就不会删,所以这样我们就可以执行我们的马了

可以用burp来批量上传

它必须要有payload,所以我们就在php代码后面加个数字

循环这个数字从1到10000,然后开始攻击

访问/upload/2.php

buuctf这个靶机可能顶不住,算了就不测试了,反正方法就是这样

除了burp还可以用python脚本,最好用多线程(这里用一个hackhttp请求可以直接把burp上面的请求包直接发送,不需要我们重新构造,方便很多)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import hackhttp
from multiprocessing.dummy import Pool as ThreadPool

def upload(lists):
hh = hackhttp.hackhttp()
raw = """POST /Pass-17/index.php HTTP/1.1
Host: 0b3e636a-5f77-4620-a584-d8af7e832bdc.node4.buuoj.cn
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://0b3e636a-5f77-4620-a584-d8af7e832bdc.node4.buuoj.cn/Pass-17/index.php
Content-Type: multipart/form-data; boundary=---------------------------4185396531387004046442012937
Content-Length: 362
Cookie: UM_distinctid=17aecb3a84d74a-0ba25eac168a3d8-495768-384000-17aecb3a84e492
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

-----------------------------4185396531387004046442012937
Content-Disposition: form-data; name="upload_file"; filename="2.php"
Content-Type: text/php

<?php
echo phpinfo();
?>
-----------------------------4185396531387004046442012937
Content-Disposition: form-data; name="submit"

上传
-----------------------------4185396531387004046442012937--
"""
code, head, html, redirect, log = hh.http('http://0b3e636a-5f77-4620-a584-d8af7e832bdc.node4.buuoj.cn/Pass-17/index.php', raw=raw)
print(str(code) + "\r")


pool = ThreadPool(10)
pool.map(upload, range(10000))
pool.close()
pool.join()

Pass-18-条件竞争(图片马结合)

这题相比于上题就是在上传的时候会检测文件,所以这个需要上传图片马要配合文件包含漏洞

还有一个问题就是如果上传成功之后会进行重命名,因为条件竞争可能来不及重命名,所以会存在没有重命名的文件保存在服务器,所以我们就可以访问那个文件


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!