前言
最近在练习文件上传漏洞,正好拿upload-labs靶场练手。这里是在windows系统环境下进行的,建议直接使用作者提供的windows集成环境(之前我自己搭建的环境因为中间件和PHP配置不同,有些上传漏洞无法复原)。
Pass-01 - 前端JS后缀名检测绕过
解题思路
首先常规思路,选择一个shell文件上传,同时用Burp Suit
抓包
提示文件不允许上传,同时观察Burp Suite
中并未抓到数据,说明此处是通过前端js
文件来检查文件类型的。在chrome
上用Network
功能抓包,发现并未有任何js
文件加载,于是猜测检测代码是直接写在当前页面的。
于是直接右键查看网站源代码,在源码底部可以看见我们需要的javascript
代码:
1 | <script type="text/javascript"> |
我们把shell文件后缀修改为jpg,然后再上传抓包,在filename
处将文件名后缀改回php。
上传成功,复制图像链接即可获得shell文件地址。
方法总结
主要是绕过前端javascript的文件名检测,可以先改成图片的格式,绕过js后通过抓包再修改回来。
Pass-02 - Content-Type绕过
解题思路
直接上传php文件,出现
Burpsuite
抓包发现被拦截,所以我们推测是后端代码检测文件类型。
Burpsuite
抓包后直接修改Content-Type
为image/gif
文件上传成功,成功绕过。
方法总结
根据其源码更好理解:
1 | $is_upload = false; |
可知其仅判断文件类型:$_FILES['upload_file']['type']
,使用Burp Suite
修改Content-Type
即可。
Pass-03 - PHP文件的其他格式绕过
解题思路
先直接上传一个shell.php
, 发现提示,抓包也抓到了,说明此处是后端检测后缀名,但它并未检测.phtml
, .php3
和.php5
这样的后缀,所以我们直接上传该格式即可。
如果不解析上述后缀,我们可以在httpd.conf
添加 AddType application/x-httpd-php .php .phtml .php3 .php5
方法总结
看代码:
采用黑名单时,过滤后缀不全,我们可以尝试.phtml
, .php3
和.php5
这样的后缀。
Pass-04 - .htaccess绕过(Apache 特性)
解题思路
先上传一个shell.php
,提示,抓包抓到了,说明此处时后端检测文件。
再次按第三关的思路上传.phtml
, .php3
和.php5
这样的后缀,发现也被检测了。于是我们尝试上传**.htaccess**文件,内容为:SetHandler application/x-httpd-php
再次上传任意后缀的shell木马,即可被解析成php文件
方法总结
概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
这一关我们就利用.htaccess
文件指定所有文件后缀均解析为php
,可见过滤.htaccess
也尤为重要
Pass-05 - 大小写绕过
解题思路
观察源码:
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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"); |
发现.htaccess
在黑名单了,但我发现PHP
并未被禁止,于是尝试抓包上传PHP后缀文件
成功上传并得到文件地址,使用菜刀连接即可。
方法总结
这关虽然过滤了.htaccess
,但与第四关不同的是,他去掉了$file_ext = strtolower($file_ext); //转换为小写
的操作,导致我们能使用大写字符绕过检测。再次证明,采用黑名单的形式来检测文件上传是不可靠的!
Pass-06 - 后缀名末尾的空格绕过(Windows特性)
解题思路
观察源码:
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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"); |
我们发现此处与之前的关卡相比,少了首尾去空的操作:$file_ext = trim($file_ext); //首尾去空
。
那么这关是怎么处理文件名的呢 - 先删除末尾的点,查找到 .
最后一次出现的位置,获取从该位置开始一直到文件末尾的字符,再转换成小写、去掉::$DATA
字符后得到最终的后缀名,去和上面的deny_ext
做对比。那么我们可以想办法构造它的后缀名。
在Windows中,后缀名最后是不能带空格的,那么我们可以构造shell.php .
,这样经过处理后,这里过滤器得到的后缀是.php[空格]
,而黑名单中并没有此文件,于是绕过了过滤。加上在Windows中,就算我们上传的后缀名尾部是带空格的,系统也会在保存文件的时候自动给我们去掉空格,这样我们可以直接访问shell.php
。
那么我们来测试下:
成功连接菜刀。
方法总结
学会阅读源码和查阅资料很重要。
比如
这里的
strrchr()
方法是指查找到指定字符最后一次出现的位置,并获取从该位置开始一直到文件末尾的字符。Windows中,后缀名最后是不能带空格的,会被自动去掉。
有能力通过了解作者的代码,找出逻辑漏洞,这是学会Web安全的必要条件。
Pass-07 - 后缀名末尾的点绕过(Windows特性)
解题思路
这一关,我们看源码,
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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的特性 - 后缀名最后的点会被自动去掉,我们可以构造文件名shell.php.
,这样获取到的后缀是.
,能够绕过黑名单。在文件被保存在windows
系统上后,后缀名最后的.
会被自动去掉,我们访问shell.php
即可。
演示:
菜刀连接成功:
方法总结
根据Windows的特性,后缀名最后的点会被自动去掉。利用逻辑漏洞解出题目。
Pass-08 - $DATA文件流绕过(Windows特性)
NTFS文件流
在做这关之前,我们需要了解以下NTFS
文件流。
NTFS
是微软NT
系列内核支持的较为安全先进的磁盘文件格式。NTFS
数据交换流(简称ADS
)是NTFS
磁盘的一个特性。每个文件都可以存在多个数据流,虽然我们无法看到数据流文件,但是它却是可以真实存在于我们的系统中的。
平时我们看见的文件,其实它的全名是这样的:
<filename>:<stream name>:<streamtype>
即
<文件名>:<流名称>:<流类型>
用户不能创建一个新的流类型,流类型都是以$开头。
所有的文件在NTFS
上,都至少包含一个流:主流(即DATA流)。
默认的DATA
流是没有stream name的,如果一个文件被指派了流,但该流没有stream type的话,在储存时会自动添加$DATA
,但在访问查询的时候需要去掉$DATA
。
对于文件夹而言,没有DATA
流,它的主流是directory
流,( stream type
为 $INDEX_ALLOCATION
), directory
流默认的 stream name
是 $130
。
尽管文件夹默认没有 data
流,但用户可以指派 data
流。
解题思路
观察源码:
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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
根据上文所讲,我们抓包修改上传文件名为shell.php::DATA
,即指定文件名为shell.php
,无流名,流类型为DATA
。
当我们上传以后,过滤器判断出后缀是.php::DATA
,黑名单中未查询到,于是我们可以绕过检测。但Windows文件在保存的时候,该数据流的格式名不会显示,所以实际上还是以shell.php
的名字保存在服务器上的。
那么我们就可以开始操作了:
连接菜刀成功!
方法总结
Windows上的NTFS文件流帮助我们绕过后缀检测。这个有时间要好好了解下,后期还会遇到和NTFS文件流有关的绕过。
Reference
Pass-09 - 点空格点绕过(Windows特性)
解题思路
观察源码,发现和pass07其实没有什么区别,这一关加了去掉末尾的点,但只去掉了一次。
1 | $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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"); |
如果我们文件名是. .
,删除文件名末尾的点后,文件后缀变成了.[空格]
,接着去掉空格,最终检测的后缀名为.
,这不是和Pass-09一样吗?
直接上burp修改:
上传成功。
上菜刀即可
方法总结
还是分析源码,找出逻辑问题。
了解Windows的特性,后缀名末尾的点或空格会被自动去掉。
Pass-10 - 关键字替换绕过
解题思路
我们直接上传一个php
文件shell.php
,发现上传成功。
复制看看文件地址,发现文件地址是http://127.0.0.1/upload/shell.
后面的php被去掉了,那么我们猜测应该是触发了黑名单,然后后缀名被替换为空了。
观察代码:
1 | $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); |
那么我们可以构造以下文件名
test.pphphp
这样检测到php
字段并替换为空,这样我们上传的文件名仍然为test.php
。
连接菜刀:
方法总结
直接替换非法后缀名是很不安全的,尽量使用白名单检测。
相对的,对于替换后缀名检测的方法,我们可以选择重复后缀进行绕过。
Pass-11
解题思路
直接上传PHP文件,发现只能上传图片格式
抓包看看: