文件上传漏洞----服务器端两种绕过方式(MIME+getimagesize)
当浏览器对一个文件进行识别的时候,会给这个文件定义一个类型,同时将这个类型放在Http的头里面。有一个字段叫做content-type,
它会将这个类型放到字段content-type里面。这个类型一般是什么样的?
例如:我们浏览器上传的是一个图片,它就会对这个文件进行识别,识别之后,会在content-type里面加入image/jpeg,不同文件的MIME类型是不一样的。
1:有关MIME简要介绍:
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,
是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件的打开。
每个MIME类型有两部分组成,前面是数据的大类型,例如声音Audio,图像image等,后面具体定义具体的种类,
常见的MIME类型,例如:
超文本标记语言文本,.html, .html text/html, 比如:
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
GIF图形 .gif image/gif
JPEG图形 .ipeg, .jpg image/jpeg
在php里面有一个全局的方法————————$FILES()
这个方法可以从客户端向服务器上传文件的时候,它可以获取文件的一些相关信息
例如:可以得到文件的名字,类型,文件的大小,有没有发生错误等
这个方法是如何获取文件的相关信息的?
实际上是通过Http头里面的信息来获取的,例如获取文件的类型,他会去读http头里面content-type字段。
文件上传漏洞-----$_FILES()函数
文件上传漏洞之MIME类型验证————实验演示
上传一个图片
得到结果
上传php文件:
查看服务器端源码
关键点在于:通过$FILES获取文件的类型,然后将这个类型和它定义好的类型$MIME进行比较。
为什么会存在问题?
因为$FILES这个全局的方法它是从浏览器的Http头里面获取content-type进而获取文件类型,而content-type这个是前端用户可以控制的,显然,这个信息获取是不靠谱的,很容易被绕过。
****演示过程如下:
先上传图片,抓包:
**********响应:
*********上传Php 并抓包,如下:
发送至Repeater
我们将content-type手动改成下面的类型,因为我们知道后端的$file()是通过Http头里面的content-type来获取文件的相关信息的,而前端http头的信息是可以修改的。
尽管我们上传的是一句话木马文件,但是我们将其改为image/png
改掉之后,上传成功,这样我们通过对前端Http头的修改绕过了后端mime的限制
一句话木马上传成功之后,我们可以通过访问这个木马文件,通过传参来控制后台服务器,这点和上面的php木马上传之后是一样的。
2:文件上传漏洞之getimagesize类型验证————实验演示
Getimagesize()返回结果中有文件大小个文件类型,如果用这个函数来获取类型,从而判断是否是图片的话,会存在问题。
是否可以绕过呢?可以,因为图片头可以被伪造
上面这个函数是如何判断目标文件的类型??
对目标文件的十六进制进行一个读取,看看十六进制头几个字符串是否符合图片的要求
固定的图片文件十六进制头部的几个字符串是一样的
Linux xxd命令是看一个文件的十六进制,
例子:如果你前边几个字符串是89504e47,就会被认为是png图片。
思路:我们是不是可以伪造一个图片,也就是说16进制的前几个都是一样的,
但是后面插入一些恶意的代码,然后再把这个图片传上去,这样是不是就可以绕过
Getimagesize()
演示:利用getimagesize()来判断你上传的是否是一个图片?
如何制作一个恶意代码的图片?
图片木马的制作过程如下:
方法1:直接伪造头部GIF89A
方法2:CMD:copy /b test.png + muma.php cccc.png
方法3:使用GIMP(开源的图片修改软件),通过增加备注,写入执行命令
嵌入木马文件的图片。
上传带有木马文件的图片:可以上传成功
3:不安全的文件上传漏洞---防范措施
1:不要在前端使用JS实施上传限制策略
2:通过服务器端对上传文件进行限制
(1)进行多条件组合检查:比如文件的大小,路径,扩展名,文件类型,文件完整性
(2)对上传的文件在服务器上存储时进行重命名(制定合理的命名规则)
(3)对服务器端上传文件的目录进行权限控制(比如只读),限制执行权限带来的危害。