文件上传漏洞
本Web安全基础推文系列旨在以平白的语言讲解漏洞原理,文章多数内容为我本人的学习笔记与总结,汇总供大家参考。
目录
1 文件上传漏洞
2 文件上传漏洞分类
3 文件上传漏洞防御
4 总结
5 参考链接
1 文件上传漏洞
1.1 什么是文件上传漏洞?
WEB应用在文件上传过程中没有对文件的安全性进行有效校验,导致攻击者上传恶意文件构造攻击。校验包括通过文件特征,如文件头字节,文件后缀名等判断是否是允许上传的文件。
攻击者可以通过上传 webshell、病毒、恶意脚本等恶意文件对服务器进行攻击。在已知文件路径的情况下,通过文件包含或者访问等形式使该恶意代码被后端执行,达到控制服务器的目的。上传漏洞经常出现于头像上传、相册上传、附件上传、新闻投稿等位置,产生的危害极大,可直接导致web服务器权限被攻击者控制。
webshell又称网页木马文件,以asp\php\jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称之为一种网页后门。根据开发语言的不同又分为ASP木马、PHP木马、JSP木马等,该类木马利用了脚本语言中的系统命令执行、文件读 写等函数的功能,一旦上传到服务器被脚本引擎解析,攻击者就可以实现对服务器的控制。
图片
常见的一句话木马有:
<?php @eval($_POST['para']);?>
para即为webshell连接的密码
1.2 常见的测试方法:
- 黑盒测试:通过工具扫描网站敏感文件、路径,以期获得文件上传地址。或者对存在上传图片的功能处进行漏洞测试。
- 白盒测试:审计代码,查找upload_file等功能,审计是否存在上传漏洞。通过抓包、上传等操作判断漏洞是否存在。
2 文件上传漏洞分类
文件上传漏洞分类
可以简单分为前端和后端的绕过。
图片
2.1 前端绕过
前端一般利用JavaScript对文件大小、后缀名等进行检验。其中后缀名使用黑名单或白名单拦截。然而恶意用户可以对前端javascript进行修改或者是通过抓包软件篡改上传的文件,就会导致基于js的校验很容易被绕过。
前端检测绕过方法有如下几种:
1.禁用js:通过火狐插件 NOscript 插件或者禁用IE中JS脚本;
2.删除代码:通过元素审查修改代码(如删除 onsubmit=”return checkFile()” 事件);
3.修改js代码:通过元素审查 javascirpt 脚本中添加上传文件类型;
4.burp改包:通过利用 burp 抓包改包,先上传一个 png 类型的木马,然后通过 burp 将其改为asp/php/jsp 后缀名即可。注意:这里修改文件名字后,请求头中的 Content-Length 的值也要改(burp默认会自动修改)。
2.2 后端绕过
主要包括检查后缀名绕过、检查内容和其他绕过。
后缀名绕过包括黑名单和白名单绕过:
2.2.1黑名单绕过
黑名单是通过设置禁止上传的文件名后缀,对可接受的文件格式进行限制,避免攻击者上传恶意代码文件。而过滤的方式存在一定的缺陷,比如存在过滤的黑名单不全,未考虑大小写,以及要上传文件的名称存在敏感字符。
特殊解析后缀
.htaccess绕过
大小写绕过
点绕过/空格绕过
::$DATA绕过
双后缀名绕过
1 解析漏洞:特殊解析后缀
Apache解析漏洞
IIS6.0解析漏洞
IIS7.0 | IIS7.5 | Nginx的解析漏洞
(1)Apache解析漏洞:
Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。比如test.php.a.b的“.a”和“.b”这两种后缀是apache不可识别解析,apache就会把test.php.a.b解析成test.php。
影响版本:apache 1.x apache 2.2.x
(2)IIS6.0解析漏洞:
IIS6.0解析漏洞分两种:
1、目录解析: 以xx.asp命名的文件夹里的文件都将会被当成ASP文件执行。
2、文件解析:xx.asp;.jpg 像这种畸形文件名在;后面的直接被忽略,也就是说当成xx.asp文件执行。
IIS6.0 默认的可执行文件除了asp还包含这三种 .asa .cer .cdx。
(3)IIS7.0 | IIS7.5 | Nginx的解析漏洞:
Nginx拿到文件路径(更专业的说法是URI)/test.jpg/test.php后,一看后缀是.php,便认为该文件是php文件,转交给php去处理。php一看/test.jpg/test.php不存在,便删去最后的/test.php,又看/test.jpg存在,便把/test.jpg当成要执行的文件了,又因为后缀为.jpg,php认为这不是php文件,于是返回Access denied。 这其中涉及到php的一个选项:cgi.fix_pathinfo,该值默认为1,表示开启。开启这一选项PHP可以对文件路径进行修理。
举个例子,当php遇到文件路径/1.jpg/2.txt/3.php时,若/1.jpg/2.txt/3.php不存在,则会去掉最后的/3.php,然后判断/1.jpg/2.txt是否存在,若存在,则把/1.jpg/2.txt当做文件/1.jpg/2.txt/3.php,若/1.jpg/2.txt仍不存在,则继续去掉/2.txt,以此类推。
漏洞形式:
www.xxxxx.com/UploadFiles/image/1.jpg/1.php
另外两种解析漏洞:
www.xxxxx.com/UploadFiles/image/1.jpg%00.php
www.xxxxx.com/UploadFiles/image/1.jpg/%20\0.php
2 .htaccess绕过
漏洞利用前提::
web具体应用没有禁止.htaccess文件的上传,同时web服务器提供商允许用户上传自定义的.htaccess文件。
原理:
.htaccess文件(或者”分布式配置文件”) ,全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法,即,在一个特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
利用方式:上传覆盖.htaccess文件,重写解析规则,将上传的带有脚本马的图片以脚本方式解析。
.htaccess文件内容: .htaccess文件解析规则的增加,是可以按照组合的方式去做的,不过具体得自己多测试。
<FilesMatch “evil.gif”>
SetHandler application/x-httpd-php
#在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
#在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
3 大小写绕过
1.代码只对后缀名为.php的文件进行了拦截,并未对.pHp后缀名的文件拦截
2.上传后缀名为.pHp的文件
4 点绕过/空格绕过
利用Windows的命名机制
shell.php. shell.php空格 在windows中,后缀名后面的点和空格都会被删除掉。
例如:
a.php\[空格](点)[空格]
a.php .
a.php(点)\[空格](点)
deldot删除最后一个点之后,不再进行删除,trim删除空格,那么最终上传的文件名为1.php.,利用Windows自动去除最后一个点,导致成功上传1.php;
5 ::$DATA绕过
背景原因:(windows特性)
在window系统下,如果上传的文件名为a.php::$DATA,它会在服务器上生成一个a.php的文件,其中内容和所上传内容相同,并被解析。
例如:phpinfo.php::$DATAWindows会自动去掉末尾的::$DATA变成phpinfo.php
利用示例:
通过BurpSuite截断 HTTP 请求之后,在对应的文件后缀名处添加::$DATA。
a.php::$DATA
注意,在windows下,无法直接测试::$DATA,因为windows不允许后缀名中存在特殊字符;
6 双后缀名绕过
有时候在检测时,后台会把敏感字符替换成空格,这个时候,我们可以使用双写进行绕过。比如:pphphp
2.2.2 后缀名白名单绕过
白名单检测:一般有个专门的 whitelist 文件,里面会包含的正常文件:jpg png GIF
(1)Content-Type 字段绕过
HTTP header的Content-Type 实体头部用于指示资源的 MIME 类型 media type 。
MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。
在响应中,Content-Type 标头告诉客户端实际返回的内容的内容类型。
检测:如果服务端代码是通过Content-Type的值来判断文件的类型,会检测文件的MIME类型,然后判断是否符合条件。那么就存在被绕过的可能,因为Content-Type的值是通过客户端传递的,是可以任意修改的 。
绕过;使用burp抓包,修改请求的Content-Type类型从而绕过检测,将content-type字段改为常见的图片类型,如image/gif,从而绕过校验,上传php文件。
如Content-Type: image/jpg,Content-Type: image/png,Content-Type: text/plain。
(2)截断上传
%00截断
0x00截断
0x0a截断
PHP%00截断
截断原理:由于00代表结束符,所以会把00后面的所有字符都截断
截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态
无论0x00还是%00,最终被解析后都是一个东西:chr(0)
在C语言中,空字符有一个特殊含义,代表字符串的拼接结束。这里我们使用的是php语言,属于高级语言,底层靠C语言来实现的,也就是说空字符的字符串拼接结束功能在PHP中也能实现。但是我们在URL中不能直接使用空,这样会造成无法识别;我们通过查看ASCII对照表,发现ASCII对照表第一个就空字符,它对应的16进制是00,这里我们就可以用16进制的00来代替空字符,让它截断后面的内容。
使用burpsuite进行抓包,因为这里是通过URL进行传递的文件上传后存储路径,所以需要对16进制的00进行URL编码,编码的结果就是%00,通过这种方式,就可以%00截断后面的内容,让拼接的文件名不再进行生效。
当一个字符串中存在空字符的时候,在被解析的时候会导致空字符后面的字符被丢弃。
在文件名中插入空字符进行00截断,只适合前端绕过,后端绕过无效。
使用00截断绕过后端验证,除非两个条件之一:
1.后缀检测,合格则进行上传路径拼接,文件名中还是包含截断字符的,路径拼好之后可以被截断成想要的.php。
2.文件路径可控,拼接路径和文件名,组成文件上传路径。比如我可以修改路径拼接的path时,比如抓到的包中存在path: uploads/,就可以直接把路径构造成uploads/xxx.php%00,先构造一个存在截断字符的后缀“等着”真正的文件名,或者后缀名,因为不管它是啥,都会被截断而丢弃,因为这里已经到了“最后阶段”,不会再有安检过程了,这里截断之后的结果就是最终上传的结果,比如下图中,抓到的包里发现了路径,那么使用上面的方法直接改它,就可以成功上传aa.php文件,不管被处理后的文件名是什么,在这里被截断才是真正的“截断”,因为这是在安检(后缀名校验)之后进行的截断,直接决定真实的文件后缀名。
2.2.3 文件内容检查绕过
(1)getimagesize绕过(检查文件头字节)
突破getimagesize:在文件内容的起始位置加上一个GIF89a,php的getimagesize()函数也以为我们上传的webshell文件是图片。
注意:下面的文件头的格式是16进制的格式:
GIF:47 49 46 38 39 61
png:89 50 4E 47 0D 0A 1A 0A
JPG:FF D8 FF E0 00 10 4A 46 49 46
在进行文件头绕过时,我们可以把上面的文件头添加到我们的一句话木马内容最前面,达到绕过文件头检测的目的。
s1.php
GIF89a
<?php phpinfo(); ?>
php引擎会将 <?之前的内容当作html文本,不解释而跳过,后面的代码仍然能够得到执行。
利用:找一个符合上传过滤类型的文件与脚本文件合并制作图片木马,后将新文件上传,再结合文件包含漏洞getshell。
制作图片木马
C:\Users\Desktop>copy a.png/b + s1.php/a img.gif
a.png
s1.php
文件头代码拦截示例:
1.文件上传接口,读取文件,并将文件转为输入流;
2.截取文件流的前四个字节,并将其转成16进制,并转为大写
3.比较截取的字符与常见的文件类型头部字符进行比对,返回文件的类型
4.正常通过,存在异常则报错;
(2)突破exif_imagetype
exif_imagetype()函数:读取一个图像的第一个字节并检查其签名,如果发现恰当的签名返回一个对应的常量,否则返回false。返回值和getimagesize()返回值的数组中的索引2的值是一样的,但本函数快的多。
制作图片木马绕过,结合文件包含漏洞进行利用。
(3)二次渲染漏洞:
1.二次渲染原理:
在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片并放到网站对应的标签进行显示。
2.绕过:
配合文件包含漏洞:将一句话木马插入到网站二次处理后的图片中,也就是把一句话插入图片在二次渲染后会保留的那部分数据里,确保不会在二次处理时删除掉。这样二次渲染后的图片中就存在了一句话,在配合文件包含漏洞获取webshell。
可以配合条件竞争:这里二次渲染的逻辑存在漏洞,先将文件上传,之后再判断,符合就保存,不符合删除,可利用条件竞争来进行爆破上传
2.2.4 其他绕过
(1)条件竞争漏洞:
条件竞争漏洞是一种服务器端的漏洞,由于服务器端在处理不同用户的请求时是并发进行的,因此,如果并发处理不当或相关操作逻辑顺序设计的不合理时,将会导致此类问题的发生。
上传文件源代码里没有校验上传的文件,文件直接上传,上传成功后才进行判断:如果文件格式符合要求,则重命名,如果文件格式不符合要求,将文件删除。
由于服务器并发处理(同时)多个请求,假如a用户上传了木马文件,由于代码执行需要时间,在此过程中b用户访问了a用户上传的文件,会有以下三种情况:
1.访问时间点在上传成功之前,没有此文件。
2.访问时间点在刚上传成功但还没有进行判断,该文件存在。
3.访问时间点在判断之后,文件被删除,没有此文件。
(2)WAF绕过
数据溢出绕过:
原理:数据范围都是有限,超过WAF的检测范围就不会往下检测
正常情况下
content-disposition:form-data; name="upload_file"; filename="xxxx";
content-type: image/jpeg
方法一:在content-disposition:字段里写入无用数据(直达WAF检测不出来)
可以在form-data前面添加无效数据
content-disposition: qwfasajhchsavhjfxjassbchmvjvxevcssasvad hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmn hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmnsvcyewgchvgegjcbwveyiwcvjsqwfasajhchsav hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmnsvcyewgchvgegjcbwveyiwcvjsqwfasajhchsav hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmnsvcyewgchvgegjcbwveyiwcvjs(直达WAF检测不出来) form-data; name="upload_file"; filename="xxxx.php";
content-type: image/jpeg
也可以在form-data后面添加无效数据
content-disposition: form-data qwfasajhchsavhjfxjassbchmvjvxevcssasvad hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmn hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmnsvcyewgchvgegjcbwveyiwcvjsqwfasajhchsav hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmnsvcyewgchvgegjcbwveyiwcvjsqwfasajhchsav hjhegvwchjsvnmcvejgabvxeyfwavcyefwkcbmnsvcyewgchvgegjcbwveyiwcvjs(直达WAF检测不出来) ; name="upload_file"; filename="xxxx.php";
content-type: image/jpeg
方法二:重复Content-Disposition字段,将恶意文件放在最后(直到绕过WAF)
content-disposition:form-data; name="upload_file"; filename="xxxx";
content-disposition:form-data; name="upload_file"; filename="xxxx";
……
content-disposition:form-data; name="upload_file"; filename="x.php";
content-type: image/jpeg
方法三:在filename处进行溢出,将恶意文件放在最后(直到绕过WAF)
content-disposition:form-data;
name="upload_file"; filename="vgdbcshjvebcvhascbwebckjbxc hewvcnx chjevwcj xn cec.xcne ccwe cewkccas e vgdbcshjvebcvhascbwebckjbxc hewvcnx chjevwcj xn cec.xcne ccwe cewkc esavcsaxAC dvdsce vgdbcshjvebcvhascbwebckjbxc hewvcnx chjevwcj xn cec.xcne ccwe cewkc ecsdv dvdsce vgdbcshjvebcvhascbwebckjbxc hewvcnx chjevwcj xn cec.xcne ccwe cewkc e dvdsc x.php";
content-type: image/jpeg
3 文件上传漏洞防御
1)代码层次:
前端检测(在前端用了JS 脚本做检测,如检测文件后缀名等)
服务器端检测:
①MIME类型检测(比如GIF图片MIME为image/gif,CSS文件的MIME为text/css)
②文件后缀名检测,如设置白名单,避免使用黑名单。
③文件内容检测
图片二次渲染。(最变态的文件上传漏洞防御方式)
检查文件上传路径。(避免被0x00截断、IIS6.0文件夹解析漏洞、目录遍历)
文件重命名,包括文件名及其扩展名(利用随机字符串或时间戳等方式进行命名,防止攻击者得到WebShell的路径)
将其存放路径和文件名存放在数据库中,系统使用文件时,通过查询数据库动态获取。
检验是否存在条件竞争的逻辑漏洞。
(2)管理层次:
部署WAF防火墙。
正确配置服务器请求类型。(禁止使用PUT请求方法)
及时更新系统、中间件、脚本、数据库、CMS或框架的漏洞补丁。(避免解析漏洞)
(3)设置权限
限制上传目录下拥有的执行权限
4 总结
文件上传漏洞是指由于服务器配置不当或者没有进行足够的过滤,WEB用户可以上传任意文件,包括恶意脚本文件、EXE程序。常见的绕过方法分为前端和后端,前端禁用js,后端有黑白名单绕过,除此之外还有二次渲染绕过,条件竞争等形式。
5 参考链接
https://blog.csdn.net/qq_53079406/article/details/125590572?spm=1001.2014.3001.5501
https://www.freebuf.com/articles/web/163058.html
https://blog.csdn.net/weixin_44840696/article/details/90581104
https://blog.csdn.net/m0_64378913/article/details/124895215