什么文件上传
文件上传是一个网站的常见功能,多用于上传照片、视频 、文档等许多类型文件。一般文件上传的流程如下:
- 前端选择文件,进行提交
- 浏览器形成POST MultiPart报文发送到服务器
- 服务器中间件接受报文,解析后交给相关后端代码进行处理
- 后端代码将上传的文件内容写到临时文件中(PHP特有)
- 写入到文件中,文件名为提交的文件名或以一定规则生成的文件名
文件上传代码
前端
<form action="" method="post" enctype="multipart/form-data" name="upload">
请选择要上传的文件:<input type="file" name="file"/>
<input type="submit" name="submit" value="上传" />
</form>
后端
move_uploaded_file($_FILES['upfile']['tmp_name']),$uploaddir . '/' . $_FILES['upfile']['name'])
什么是文件上传漏洞
文件上传的地方未对文件进行严格的校验和过滤,导致任意文件的上传,包括一些动态的文件(asp/php/jsp等等)
如果上传的目标目录没有限制执行权利,就会导致所上传的动态文件(比如webshell)可以正常执行并且可以访问,即造成了文件上传漏洞
文件上传漏洞的必要条件
- 存在上传点
- 可以上传动态文件
- 上传目录有执行权限,并且上传的文件可执行
- 可访问到上传的动态文件
文件上传检测的流程
文件上传漏洞绕过方法
前端检测绕过
提交报文修改检测(前端检测通用)
- 首先选择正常的文件进行上传
- 从而通过burpsuite进行捷报该报或该报重放完成文件上传
这种方法前端绕过检测中通用,无需理会具体前端的检测代码,直接绕过前端进行上传报文的修改并提交
客户端检测绕过
- JavaScript检测:通过浏览器提交上传请求前,触发检测用JS脚本进行检测
- Flash AS脚本检测:上传用Flash中,提交上传请求前,触发检测用AS脚本进行检测
- APP上传检测:检测卸载APP客户端代码中,或者所调用的HTML页面中
客户端检测一般只检测文件扩展名
客户端进行的检测,可通过对客户端代码的一些修改或直接拦截修改报文即可绕过
前端JavaScript检测绕过
查看onchange、oncubmit等事件
- onchange事件会在域的内容改变时发生
- onsubmit事件会在表单中的确认按钮被点击是发生
删除掉相关事件中的检测函数
服务器检测绕过
文件名、MIME/TYPE、文件内容、黑白名单验证
MIME类型检测绕过
MIME是一个互联网标准,是描述消息内容类型的因特网标准,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,浏览西可以更具上传的扩展名,对应到相应的MIME类型上
可以通过抓包,修改Content-type的类型来绕过检测
常见的MIME类型(通用型):
- 超文本标记语言文本 .html text/html
- xml文档 .xml text/xml
- XHTML文档 .xhtml application/xhtml+xml
- 普通文本 .txt text/plain
- RTF文本 .rtf application/rtf
- PDF文档 .pdf application/pdf
- Microsoft Word文件 .word application/msword
- PNG图像 .png image/png
- GIF图形 .gif image/gif
- JPEG图形 .jpeg,.jpg image/jpeg
- au声音文件 .au audio/basic
- MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
- RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
- MPEG文件 .mpg,.mpeg video/mpeg
- AVI文件 .avi video/x-msvideo
- GZIP文件 .gz application/x-gzip
- TAR文件 .tar application/x-tar
- 任意的二进制数据 application/octet-stream
文件内容检测绕过
文件头检测
文件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分,用来标记文件类型
如果是那种简单的只对文件头进行简单的匹配的方法,可以通过在要上传的文件前添加合法的文件头进行绕过
完整文件结构检测
通过调用图像函数(getimagesize/imagecreatfromgif等),进行检测文件是否为图像,这需要文件有完整的图片内容,所以单单使用添加文件头的方法是无法绕过的
getimagesize(string $filename [,array &$imageinfo]) //获取图像信息,返回一个数组
imagecreatefromgif(string $filename) //返回一图像标识符,代表了从给定的文件名取得的图像
针对这种,可以将一张图片和我们想要上传的文件进行合并来绕过检测(尽量使用较小的图片)
可以使用copy命令将图片与文件进行合并
恶意文件内容检测
检测提交的文件中是否有webshell的函数/关键字(eval/base64_encode/assert/java.lang.runtime/java.lang.ProcessBuilder)
可以使用kali自带的weevely https://github.com/sunge/Weevely
或者使用开源的webshell收集项目:https://github.com/tennc/webshell
黑名单验证
黑名单定义了一系列扩展名,服务器端在接受文件后,与黑名单扩展名对比,如果发现文件扩展名和黑名单里的扩展名相同,则认为文件是不合法的
绕过方法
可解析的特殊后缀名绕过
攻击者可以从黑名单中寻找开发人员忽略但是能够被解析的扩展名
- php扩展名:php3/php4/php5/php7/phptml
- jsp扩展名:jspx
- asp扩展名:cer/asa
使用扩展名大小写绕过
如果没有存在strtolower()这个函数就使用大小饶过如: PHP .Php .PHp 等扩展名
文件结尾添加"."或者空格绕过
在windows系统下,如果文件名以”.“或者是空格结尾时,系统会自动去除".“和空格,所以可以把想要上传的文件后面加上”."或者是空格
上传.htaccess文件绕过
如果.htaccess中有如下配置, 可以将扩展名.xxx当做php执行
AddType application/x-https-php xxx
双写绕过
以pphphp为扩展名,中间的php被替换了,还剩下php为后缀
%oo截断
要求:php版本必须小于5.3.4,并且php.ini中的magic_quotes_gpc设置为Off
以php%00.jpg为后缀会被解析成php
白名单验证
白名单验证和黑名单验证则相反,白名单定义了一系列扩展名,服务器端在接受文件后,与白名单里的扩展名进行对比,若相同则认为文件是合法的,若不同则不允许上传
可以配合解析漏洞进行绕过或者使用%00截断进行绕过
一些小技巧
文件可以加一些filename属性:如果文件上传过程中,存在waf去拦截了一些扩展名,可以尝试添加多个filename属性
目录可控时,可以尝试使用目录穿越的方法(…/)
扩展名检测类型可控
- 可以从后台修改允许/禁止的扩展名类型
- 提交参数中存在允许/禁止的扩展名类型
- 前端单独抽出了文件扩展名进行了提交
文件解析漏洞
1.IIS解析漏洞(5.x/6.0)
目录解析:当建立*.asa、.asp格式的文件夹时,其目录下的任意文件都将被IIS当做sap文件来解析 文件解析:当文件为.asp;1.jpg时IIS6.0同样会以ASP脚本来执行,IIS 6.0默认的可执行文件有asp/asa/cer/cdx
2.Apache解析漏洞
Apache在解析文件时有一个原则,当碰到不认识的扩展名时,将会从后向前解析,知道碰到认识的扩展名为止,然后再将其解析,如果都不认识,则会暴露其源代码
3.PHP CGI解析漏洞(Nginx、IIS 7.0、IIS 7.5、Lighttpd)
在PHP的配置文件中有一个关键的选项:cgi.fi x_pathinfo。这个选项在某些版本中默认是开启的,在开启时访问URL,比如xxx.com/x.txt/a.php,a.php是不存在的文件,所以PHP将会向前递归解析,将x.txt当做x.php解析,于是造成了解析漏洞。
4.Nginx文件名逻辑漏洞(0.8.411.4.3/1.5.01.5.7)
上传一个以空格(%20)为结尾的文件,例如“boy.jpg”
当访问boy.jpg%20%00.php时,会将刚刚上传的"boy.jpg"文件,当做PHP进行执行,而boy.jpg%20被当做了文件名
如何判别服务器类型
F12,点击network
在name里面选择网站
点击header
在里面就可以看到服务器类型了
|