什么是序列化
序列化可以實作將物件壓縮并格式化,方便資料的傳輸和存盤,
為什么要序列化?
PHP 檔案在執行結束時會把物件銷毀,如果下次要參考這個物件的話就很麻煩,所以就有了物件序列化,實作物件的長久存盤,物件序列化之后存盤起來,下次呼叫時直接調出來反序列化之后就可以使用了,
學習序列化要了解的基本內容,
類(Class): 類的定義包含了資料的形式以及對資料的操作,
物件:物件是類的實體,
方法:類中定義的函式,
<?php
//創建一個類 Test
class Test
{ //定義 3 個屬性,最后序列化后看一下這 3 個屬性序列化后的結果,
private $a = "private";
public $b = "public";
protected $c = "protected";
}
//創建一個物件,物件是類的實體,
$test = new Test();
//序列化 test 這個物件
$data = https://www.cnblogs.com/ZZslBl0g/archive/2022/08/20/serialize($test);
//列印序列化后的物件
echo $data;
?>
展示結果(前提條件,php只有再apache下可以運行,之前我創建了txt,發現無法運行,避免踩坑)
序列化之后的結果,每個字符都具有具體含義

O:4:"Test":3: {s:7:"Testa";s:7:"private"; s:1:"b";s:6:"public"; s:4:"*c";s:9:"protected";}
O Object 物件
4 名字長度為 4 Test(物件名稱)
3 表示物件中存在3個屬性
s:7:"Testa"; 變數名字
s:7:"private"; 值
- s string 字串
- 7 變數名長度為7 private私有的,會在Testa前后添加\00 ,即
\X00Test\X00a(因此長度為7) - s string 字串
- 7 變數的值長度為7 private 值
s:1:"b";
s:6:"public"
- s string
- 1 名字長度 1
- b 變數名字
s:4:"*c";
s:9:"protected";
- s string
- 4 名字長度 4
- *c 變數名字
\x00*\x00c
序列化的程序:
通過classTest創建一個物件,然后把這個物件進行序列化,列印出來
反序列化:
PHP 反序列化漏洞又叫做 PHP 物件注入漏洞,成因在于代碼中的 unserialize() 接收的引數可控,從上面的例子看,這個函式的引數是一個序列化的物件,而序列化的物件只含有物件的屬性,那我們就要利用對物件屬性的篡改實作最終的攻擊
代碼如下:
(注意:Testa和*c的部分要留出空格來,與前面的的長度相符合)
輸出要用var_dump而不是echo
<?php
$data = 'https://www.cnblogs.com/ZZslBl0g/archive/2022/08/20/O:4:"test":3:{s:7:" Test a";s:7:"private";s:1:"b";s:6:"public";s:4:" * c";s:9:"protected";}';
$free = unserialize($data);
var_dump($free);
?>
結果如下:
object(__PHP_Incomplete_Class)#1 (4) {
["__PHP_Incomplete_Class_Name"]=>
string(4) "test"
[" Test a"]=> //名字
string(7) "private" //值
["b"]=> //名字
string(6) "public" //值
[" * c"]=> //名字
string(9) "protected" //值
}
反序列化造成漏洞的原因:
- 反序列化一般都是用戶傳遞過來惡意代碼,通過反序列化執行
- 反序列化的字串用戶可以控制
- 內容長度改變以后,前面的長度也需要跟著改變
序列化-魔術方法
魔術方法介紹:
方法:類中定義的函式,
上面我們演示了如何進行序列化和反序列化,但是我們僅使用了屬性,也就是變數,變數我們可以當
做資料來看待,而編程就是對資料進行一些列的操作和處理,操作和處理資料的程序我們一般通過函式來
定義,函式在面向物件編程中我們一般稱之為方法,所以后續如果老師說到方法就等于說的是函式功能,
特殊的方法-魔術方法,
PHP 將所有以 __(兩個下劃線)開頭的類方法保留為魔術方法,這些都是 PHP 內置的方法,
__construct 當一個物件創建時被呼叫,
__destruct 當一個物件銷毀時被呼叫,
__wakeup() 使用 unserialize 時觸發
__sleep() 使用 serialize 時觸發
__call() 在物件背景關系中呼叫不可訪問的方法時觸發
__callStatic() 在靜態背景關系中呼叫不可訪問的方法時觸發
__get() 用于從不可訪問的屬性讀取資料
__set() 用于將資料寫入不可訪問的屬性
__isset() 在不可訪問的屬性上呼叫 isset()或 empty()觸發
__unset() 在不可訪問的屬性上使用 unset()時觸發
__toString() 把類當作字串使用時觸發,回傳值需要為字串
__invoke() 當腳本嘗試將物件作為函式呼叫時觸發
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/502322.html
標籤:其他
