1、php面向對象基本概念
類的定義:
類是定義了一件事物的抽象特征,它將數據的形式以及這些數據上的操作封裝住在一起。(對象是具有類類型的變量,是對類的實例)
構成:
成員變量(屬性)+成員函數(方法)
成員變量的值對外不可見,需要通過成員函數訪問。
2、類與對象
實例化和賦值:再給實例化進行賦值的時候要首先確保類里面定義過這個屬性
類的修飾符介紹:
在類中直接聲明的變量稱為成員屬性(也可以成為成員變量)。
可以在類中聲明多個變量,即“對象”中可以有多個成員屬性,每個變量都存儲"對象’不同的屬性信息。
常用訪問權限修飾符:(對屬性的定義)
public:公共的,在類的內部、子類中或者類的外部都可以使
用,不受限制;
protected:受保護的,在類的內部、子類中可以使用,但不能
在類的外部使用;
private:私有的,只能在類的內部使用,在類的外部或者子類中
都無法使用。
類與對象的關系:
類是對象的抽象,而對象是類的具體實例。
類是想法,把類實例化(new),調用具體值后就變成了對象。
類的成員方法:
在類中定義的函數被稱為成員方法。函數實現的是某個獨立的功能;
成員方法實現的是類中的一個行為,是類的一部分。
可以在類中聲明多個成員方法,成員方法的聲明和函數聲明完全一樣,只
不過在聲明成員方法時可以在function關鍵字前加一些訪問權限修飾符,
如public、protected、private(可以省略,默認為public)
3、序列化
對象的序列化:不能序列化‘類’,可以序列化‘對象’,只序列化成員變量不序列化成員函數
private私有屬性序列化時在變量前加空格(就是url編碼中的%00類名%00)
protected受保護屬性序列化時在變量名前加%00*%00
4、反序列化特性
1、反序列化之后的內容為一個對象
2、反序列化生成的對象里的值,又反序列化里的值提供,與原有類預定定義的值無關。
3、反序列化不觸發類的成員方法;需要調用方法后才能觸發
5、反序列化漏洞
簡單例題:
首先定義了一個test類,其中有成員變量a和成員方法(調用displayvar)并輸出,通過get傳入benben,并將其反序列化后復制再次調用displayvar。因此可以利用get傳入的參數來完成所需要的指令。如果要執行system(‘ls’)指令,就需要將其寫為序列化的形式通過get上傳。
payload:
?benben=o:4:"test":1:{s:1:"a";s:13:"system('id');";}
6、魔術方法
定義:
一個預定好的,在特定情況下自動觸發的行為方法
作用:
特定條件下自動調用相關方法,達到觸發代碼
實例:
_construct():構造函數,在實例化一個對象時,首先會去自動化執行的方法
觸發時機:實例化對象
功能:提前清理不必要的內容
_destruct():析構函數,在對象的所有引用被刪除或者當對象被顯式銷毀時執行的魔術方法。(實例化對象結束后會被銷毀,也會觸發析構函數)
_sleep():序列化serialize()函數會檢查類中是否存在一個魔術方法_sleep()如果存在,該方法會先被調用,然后才執行序列化操作。
觸發時機:序列化serialize()之前
將benben的值傳給cmd,然后對user進行實例化,此時觸發_construct(),對user進行序列化觸發_sleep(),因此想要通過命令執行獲得信息就可以在benben中傳入任意命令進行執行。
_wakeup():unserialize()會檢查是否存在一個_wakeup()方法,如果存在,則會先調用_wakeup()方法,預先準備對象需要的資源。
觸發時機:unserialize()反序列化之前
_wakeup():在反序列化unserialize()之前
_destruct():在反序列化unserialize()之后
_toString():表達方式錯誤導致魔術方法觸發
觸發時機:把對象當成字符串調用
_invoke():格式表達錯誤導致魔術方法觸發
觸發時機:把對象當成函數調用