练习题目的地址:https://github.com/c0ny1/upload-labs
靶机包含漏洞类型分类

判断上传漏洞类型

前端JS校验
有些文件上传表单,会在前端JS里进行文件的校检,而后端因为前端已经校检了,所以没有在二次校检。
我们知道,只要是客户端限制都能绕过的,所以这种方式限制非常容易绕过:通过抓包修改、开发者工具修改JS代码等等。
1 | <form enctype="multipart/form-data" method="post" οnsubmit="return checkFile()"> |
校验文件MIME类型
MIME
多用途互联网邮件扩展类型,浏览器通常使用MIME类型(而不是文件扩展名)来确定如何处理文档,每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类。也就是通过MIME可以确认文件的类型。
常见的MIME类型
- 普通文本 .txt:text/plain
- 超文本标记语言文本 .html:text/html
- GIF图形 .gif:image/gif
- JPEG图形 .jpeg,.jpg:image/jpeg
如果,文件上传接口后端是通过校检文件的MIME类型,也可以通过抓包修改文件的MIME类型进行绕过即可。
1 | if (($_FILES['upload_file']['type'] != 'image/jpeg') || ($_FILES['upload_file']['type'] != 'image/png') || ($_FILES['upload_file']['type'] != 'image/gif')) { |
校验文件头类型
不同的文件都有不同的文件头,文件头就是为了描述一个文件的一些重要的属性,它告诉了打开并处理该文件的程序这些属性。有些上传接口会检测你上传的文件头信息以此来判断是否为正真的文件类型。那么此时只需要在上传的文件开头部分添加图片的文件头即可,这也是制作图片木马的由来,就是为了绕过文件头检测机制和文件大小检测机制。
1 | $file = fopen($filename, "rb"); |
校验文件大小
有对文件大小进行了限制,如果不达到文件大小的要求,则不能上传,这种破解也很简单,在上传数据里不断填充垃圾数据或制作图片木马进行绕过。
1 | $types = '.jpeg|.png|.gif'; |
黑名单校验文件后缀名
如果后端是通过黑名单形式校检文件后缀名,也是存在绕过的可能,因为黑名单难免会有遗漏的文件类型发生。
比如:在某些PHP环境中,后缀名为php1、php2、php3、php4、php5、phtml等文件,也能当作php文件执行。如果可执行文件类型都过滤了,也可以上传html网页文件,里面包含钓鱼、xss等代码也能进行利用,所以建议不采用黑名单形式进行校检。
1 | $deny_ext = array('.asp','.aspx','.php','.jsp'); |
.htaccess文件绕过
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过.htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。
如果能上传htaccess文件,那么可以通过配置htaccess,使其上传图片文件也能当作可执行文件操作。
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf"); |
先构造一个.htaccess文件,内容如下
1 | AddType application/x-httpd-php .jpg |
上传1.htaccess文件,抓包改文件名为.htaccess

再上传一个后缀名改为jpg的php文件

后缀名大小写绕过
黑名单形式限制,如果开发者忘记对文件后缀名进行小写转换,那么可通过大写来进行绕过,如PhP。
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); |
后缀名空格绕过
黑名单形式限制,如果开发者忘记对文件后缀名进行首尾去空,那么可以在后缀名中加入空格绕过黑名单限制,如1.php 。但是只能在首尾,如果在后缀名中间加入空格则不能当作可执行文件了。
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); |
后缀名.号绕过
黑名单形式限制,如果开发者忘记对上传文件后缀名进行.号处理,利用windows特性,会自动去掉后缀名中最后的”.”,那么可在后缀名中加”.”进行绕过。
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); |
后缀名::$DATA绕过
黑名单形式限制,如果开发者忘记对上传文件后缀名进行::$DATA处理,利用windows的NTFS文件流特性,可在后缀名中加” ::$DATA”进行绕过。
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); |
后缀名双写绕过替换限制
黑名单形式限制,这里用str_ireplace()函数,对黑名单中的文件类型替换成空,但是我们可以利用双写绕过这个限制,如1.pphphp,替换php为空,则剩下为php了。
1 | $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); |
0x00截断绕过
根据白名单形式进行限制,也是大多数开发者采用的措施。如果文件保存的路径是采用拼接方式进行的(可自定义文件保存路径或不重命名文件名),那么可导致通过截断攻击绕过限制。
1 | $ext_arr = array('jpg','png','gif'); |
首先理解下截断的原理,在C/PHP等语言中,截断的核心,就是chr(0)这个字符,这个字符不为空(Null),也不是空字符(“”),更不是空格!当程序在输出含有chr(0)变量时,chr(0)后面的数据会被停止,换句话说,就是误把它当成结束符,后面的数据直接忽略,这就导致漏洞产生。
那么 %00截断和0x00截断有啥区别呢?其实他们的截断原理都一样,只是在GET请求中,%00会被自动解码,而在POST请求中,不会自动解码,故在POST请求中,我们需要手动对它的十六进制改写为0x00。
比如:upfilename=path & file
如果path可控,那么upfilename=upload/1.php%00 & 1.jpg => upfilename=upload/1.php
如果file可控,那么upfilename=upload/ & 1.php%00.jpg => upfilename=upload/1.php
条件竞争
如果开发者设置的是先上传文件进行保存,在验证文件,如果不通过则删除文件。这样就可以利用批量提交请求,使其服务器端在删除文件之前执行木马。(和删除文件进行竞争,利用删除文件时间差)。
1 | if(isset($_POST['submit'])){ |
解析漏洞
如果WEB服务器存在解析漏洞,那么也可以利用文件解析漏洞绕过文件上传限制。
IIS6.0文件解析漏洞
目录解析漏洞:
xx.asp/xx.jpg 服务器会把xx.asp目录下的文件解析成asp文件
文件解析漏洞:
xx.asp;.jpg 服务器默认不解析;后的内容,因此xx.asp;.jpg 变成了xx.asp文件
IIS7/7.5文件按解析漏洞
IS7/7.5在Fast-CGI运行模式下,在一个文件路径(/xx.jpg)后面加上/xx.php会将/xx.jpg/xx.php 解析为 php 文件。
Apache文件解析漏洞
低版本的Apache解析文件的规则是从右到左开始判断的,如果遇到后缀名为不可解析的,就在往左判断。利用这个特性,可以上传如xx.php.a。
Nginx文件解析漏洞
这个和iis7.5的畸形解析漏洞类似,都是由于开启了Fast-CGI模式,导致在一个文件路径(/xx.jpg)后面加上/xx.php会将/xx.jpg/xx.php 解析为 php 文件。
Windows系统解析漏洞
这在上面已讲过:
xx.php.
xx.php(空格)
xx.php::$DATA