在理解這個漏洞前,你需要先搞清楚php中serialize(),unserialize()這兩個函式。
序列化serialize()
序列化說通俗點就是把乙個物件變成可以傳輸的字串,比如下面是乙個物件:
class反序列化unserialize()就是把被序列化的字串還原為物件,然後在接下來的**中繼續使用。s $s=new s(); //
建立乙個物件
serialize($s); //
把這個物件進行序列化
序列化後得到的結果是這個樣子的:o:1:"
s":1:
o:代表object
1:代表物件名字長度為乙個字元
s:物件的名稱
1:代表物件裡面有乙個變數
s:資料型別
4:變數名稱的長度
test:變數名稱
s:資料型別
7:變數值的長度
pikachu:變數值
$u=unserialize("o:1:"s":1:");反序列化我們需要了解php的類和魔術方法,這裡舉個簡單的例子用到的魔術方法是echo $u->test; //得到的結果為pikachu
__destruct
銷毀乙個類之前執行執行析構方法。
當物件建立後輸出我們的$a
變數的值。那麼我們把它的值改變後用serialize()
看看
可以看見這是我們12345序列化之後的值o:4:"test":1:
那麼我們傳入o:4:"test":1:
o:4:"test":1:
是我們序列化的值,然後unserialize($_get['id']);
傳入我們改變的值o:4:"test":1:
成功列印了我們的改變的值,因為反序列化我們可以控制類屬性且這個過程會觸發這些能夠觸發的魔術方法
__wakeup() //使用unserialize時觸發
__sleep() //
使用serialize時觸發
__destruct() //
物件被銷毀時觸發
__call() //
在物件上下文中呼叫不可訪問的方法時觸發
__callstatic() //
在靜態上下文中呼叫不可訪問的方法時觸發
__get() //
用於從不可訪問的屬性讀取資料
__set() //
用於將資料寫入不可訪問的屬性
__isset() //
在不可訪問的屬性上呼叫isset()或empty()觸發
__unset() //
在不可訪問的屬性上使用unset()時觸發
__tostring() //
把類當作字串使用時觸發
__invoke() //
當指令碼嘗試將物件呼叫為函式時觸發
<?php我們看到在foo2中class
foo1
}class
foo2
}?>
evaltest()
函式中存在eval,而foo1中呼叫了函式evaltest()
,我們就想可不可以讓foo1呼叫foo2中的evaltest()
函式順邊還把它的$str
中的值改寫了。
我們看到在foo2中evaltest()
函式中存在eval,而foo1中呼叫了函式evaltest()
,我們就想可不可以讓foo1呼叫foo2中的evaltest()
函式順邊還把它的$str
中的值改寫了
PHP反序列化學習
利用反序列化漏洞的有兩個條件 1.unserialize 函式的引數可控 2.php中有可以利用的類並且類中有魔術函式 魔術方法就是在某些條件下自動執行的函式 序列化 sites array google runoob facebook serialized data serialize sites...
PHP反序列化學習筆記
方法名 作用 construct 建構函式,在建立物件時候初始化物件,一般用於對變數賦初值 destruct 析構函式,和建構函式相反,在物件不再被使用時 將所有該物件的引用設為null 或者程式退出時自動呼叫 tostring 當乙個物件被當作乙個字串被呼叫,把類當作字串使用時觸發,返回值需要為字...
反序列化學習筆記
什麼是序列化,就是將物件轉換為字串。什麼是反序列化,就是將字串轉化為物件。為什麼會有序列化機制?在傳遞變數的過程中,有可能遇到變數值要跨指令碼檔案傳遞的過程。如果乙個指令碼中想要呼叫之前乙個指令碼的變數,但是之前的指令碼已經執行完畢,所有變數和內容被釋放掉了序列化與反序列化一些簡單例子 demo n...