文章目錄
- 基礎知識
- 魔術方法:在序列化和反序列化過程中自動調用的方法
- 什么是 `__destruct()` 方法?
- 何時觸發 `__destruct()` 方法?
- 用途:
- 語法示例:
- 反序列化漏洞利用
- 前提條件
- 一些繞過策略
- 繞過__wakeup函數
- 繞過正則匹配
- 繞過相等邏輯判斷
- 利用大S的ascll碼繞過
- 反序列化字符逃逸
- 高級反序列化
- phar反序列化
- 什么是 PHAR 文件?
- 特點
- session反序列化
基礎知識
序列化:將對象轉化為一個可傳輸的字符串,serialize()
反序列化:將字符串重新轉化為對象
只有類的屬性可以序列化,方法不可以
如果屬性權限為private,那么序列化后,存儲的屬性名字為%00+類名+%00+屬性名
如果屬性權限為protected,那么序列化后,存儲的屬性名字為%00+*+%00+屬性名
<?php
類的屬性可以是類
class ctf{public $name;
}
class user{public $type='vip';
}
$c=new ctf();
$c->name=new user();
echo $c->name->type;
魔術方法:在序列化和反序列化過程中自動調用的方法
1. _sleep()方法在序列化時自動調用
2. _wakeup()方法在反序列化時自動調用
3. 反序列化時自動調用_destruct析構方法,方法內惡意代碼也會被執行
4. 執行類不存在的方法時自動調用_call方法,執行不存在的static方法時會調用_callstatic()方法
5. _get方法在訪問不存在屬性時自動調用,_set方法在寫入不存在屬性時自動調用
6. _isset()方法和_unset()方法
7. _tostring()方法,把對象和字符串拼接或者當字符串用時自動調用
8. _invoke()方法,當類的實例被當作函數調用
9. __set_state 方法,文檔中說執行 var_export時自動調用
10. __debugInfo 方法的屬性修飾符,執行var_dump時自動調用
11. __clone方法,當使用clone關鍵字 ,clone一個對象時,會自動調用
什么是 __destruct()
方法?
__destruct()
是 PHP 中的一個魔術方法(magic method),它用于在對象銷毀時自動執行一些清理操作,比如釋放資源或關閉數據庫連接。這個方法會在對象生命周期結束時自動調用,無需手動觸發。
何時觸發 __destruct()
方法?
__destruct()
方法在以下情況下被自動調用:
- 對象被銷毀時:當對象不再被使用時,PHP 會自動調用
__destruct()
。 - 腳本結束時:當腳本執行結束時,所有未銷毀的對象都會調用
__destruct()
。 - 手動銷毀對象:當調用
unset()
或者賦值null
給對象時,__destruct()
會被觸發。
用途:
- 釋放資源:比如關閉數據庫連接、關閉文件句柄、釋放內存等。
- 清理工作:可以用于日志記錄、清理臨時文件等。
語法示例:
class MyClass {public function __construct() {echo "對象創建了!\n";}public function __destruct() {echo "對象銷毀了!\n";}
}$obj = new MyClass(); // 輸出:對象創建了!
unset($obj); // 輸出:對象銷毀了!
反序列化漏洞利用
前提條件
- 存在反序列化提交的入口
- 有被反序列化的類的魔術方法
一些繞過策略
繞過__wakeup函數
條件:
- php5至php5.6.25 之間的版本可以繞過
- php7到php7.0.10 直接的版本可以繞過
繞過方法:
反序列化字符串中表示屬性數量的值大于大括號內實際屬性的數量時 ,wakeup方法會被繞過
繞過正則匹配
參數有過濾,不讓輸入O:數字的形式,試圖防止反序列化某個對象
O:數字 改為 O:+數字
就可以繞過上面的O:數字 過濾
繞過相等邏輯判斷
eg $a->name=&$b
采用&符號,使得a的值與b的值恒相等
利用大S的ascll碼繞過
大寫S可以支持ascll值的字符,可以借助這個特性繞過一些被過濾的字符
O:8:"backdoor":1:{s:4:"name";s:10:"phpinfo();";}O:8:"backdoor":1:{S:4:"n\97me";s:10:"phpinfo();";}
反序列化字符逃逸
在一些關鍵詞被替換后,描述中的字符數量是按照未替換之前的字符來計算,當替換后字符數量大于描述數量時,就可以逃逸出一些字符
高級反序列化
phar反序列化
什么是 PHAR 文件?
PHAR(PHP Archive)文件是一種將多個 PHP 文件、資源和其他數據打包成一個單一的歸檔文件的格式。它類似于 .tar
或 .zip
文件,允許將整個 PHP 應用或庫打包為一個文件,方便分發和部署。
特點
- 自包含:PHAR 文件可以包含 PHP 腳本和其他資源(如圖片、配置文件等),可以作為一個獨立的文件運行。
- 可執行:PHAR 文件可以像普通的 PHP 腳本一樣執行,通過
php archive.phar
來運行。 - 壓縮支持:PHAR 文件支持壓縮,可以通過
.tar
,.gzip
或.bzip2
等格式進行壓縮。
$phar->setmetadata($h);
metadata可以放一個類實例,生成phar后,會將這個類實例序列化字符串放到phar文件內,當使用phar協議加載phar文件時,會自動反序列化這個類的序列化字符串
include
file_get_contents
file_put_contents
.use.ini
等與文件相關的函數都可以包含phar協議,從而自動調用其魔術方法
phar協議哪里使用的多?
- 存在文件上傳點
- 能找到file_exists()等文件讀取函數,通過控制phar://頭,就能解析phar包來自動進行反序列化
session反序列化
-
php的session是存放在文件中的 默認位置是/tmp/sess_PHPSESSID
-
session 是可以放字符串,數字,也可以放對象
- session里面存放對象時,會自動進行序列化,存放序列化后的字符串
- session里面拿取對象時,會自動進行反序列化,執行對象的魔術方法
u|O:4:“user”:2:{s:8:“username”;N;s:8:“password”;N;} 屬于php處理器
以數組類型來存,屬于php_serialize處理器
如果用php_serialize處理器來存,就可以在username中注入|,但是如果用php處理器來取時,就會把|右邊的內容進行反序列化,反序列化之后就會調用惡意類的實例,在銷毀時就會調用析構方法