文章目錄
- 幾種常用的魔術方法
- 1、__destruct()
- 2、__tostring()
- 3、__call()
- 4、__get()
- 5、__set()
- 6、__sleep()
- 7、__wakeup()
- 8、__isset()
- 9、__unset()
- 9、__invoke()
- 三種變量屬性
- 極客2019 PHP
- php原生類
幾種常用的魔術方法
1、__destruct()
當刪除一個對象或對象操作終止時被調用,其最主要的作用是拿來做垃圾回收機制。當對象銷毀時會調用此方法,對象銷毀:1.用戶主動銷毀對象,使用unset()
函數;2.當程序結束時由引擎自動銷毀。
2、__tostring()
在對象當作字符串的時候會被調用。但是需要注意的是,執行完__toString()
之后,會有返回值。
3、__call()
調用某個方法,若方法存在,則直接調用;若不存在,則會調用__call()
方法。
4、__get()
讀取一個對象的屬性時,若屬性存在,則直接返回屬性值;若不存在,則會調用__get()
魔術方法。
5、__set()
設置一個對象的屬性時,若屬性存在,則直接賦值;若屬性不存在或者無法訪問(私有)的屬性時,則會調用__set()
函數。
__set($name, $value)
- 用來為私有成員屬性設置屬性值;
- 第一個參數為需要設置值多的屬性名,第二個參數為需要設置的屬性值,
__set
方法沒有返回值。
6、__sleep()
serialize()
之前被調用,可以指定要序列化的對象屬性。
7、__wakeup()
反序列化恢復對象之前調用該方法,也就是使用unserialize()
之前會先調用__wakeup()
。
var_dump
會輸出反序列化內容。
8、__isset()
檢測對象的某個屬性是否存在時執行該函數,當對不可訪問屬性調用isset()
或empty()
時,觸發__isset()
。
9、__unset()
在不可訪問的屬性上使用unset()
時觸發, 或銷毀對象的某個屬性時執行此函數。
unset()
函數不僅觸發__unset()
,而且會觸發__destruct()
。- 三種對象變量屬性:
public
:在本類內部、外部類、子類中都可以訪問;protected
:只在本類或子類或父類中可以訪問;private
:在本類內部可以訪問。- 序列化數據顯示:
private
屬性序列的時候格式是%00類名%00成員名
protected
屬性序列的時候格式是%00*%00成員名
- 使用
new
是創建外部類(測試類),子類是通過繼承extends
父類得到的。
9、__invoke()
當調用函數的方式調用一個對象時觸發。
三種變量屬性
- 三種對象變量屬性:
public
:在本類內部、外部類、子類中都可以訪問;protected
:只在本類或子類或父類中可以訪問;private
:在本類內部可以訪問。
- 序列化數據顯示:
private
屬性序列的時候格式是%00類名%00成員名
protected
屬性序列的時候格式是%00*%00成員名
極客2019 PHP
反序列化利用大概分為三類:
- 魔術方法的調用邏輯,如觸發條件;
- 語言原生類的調用邏輯,如
SoapClient
; - 語言自身的安全缺陷,如
CVE-2016-7124
.
首先,通過目錄掃描可以發現網站源碼保存在www.zip
中(這里就不作敘述);
index.php
中包含flag.php
,并且接收select
傳參,并且對傳參內容進行反序列化。
在flag.php
中存在一個className
,而且flag在__destruct()
魔術方法中,有兩種方式觸發__destruct()
魔術方法:1.用戶主動銷毀對象,使用unset()
函數;2.當程序結束時由引擎自動銷毀。也就是說,當程序執行完,必定會觸發__destruct()
魔術方法。因此,我們只需要滿足__destruct()
魔術方法中的兩個條件:username=admin&password=100
。由于__wakeup()
的存在,使得index.php中的unserialize
執行之前,就會自動觸發__wakeup()
。
故獲取flag的關鍵在于:繞過__wakeup()
。這里可以使用CVE-2016-7124進行繞過__wakeup()
。CVE-2016-7124:對象中的屬性個數超過實際屬性個數會繞過__wakeup()
。
class Name{private $username = 'nonono';private $password = 'yesyes';public function __construct($username,$password){$this->username = $username;$this->password = $password;}function __wakeup(){$this->username = 'guest';}function __destruct(){if ($this->password != 100) {echo "</br>NO!!!hacker!!!</br>";echo "You name is: ";echo $this->username;echo "</br>";echo "You password is: ";echo $this->password;echo "</br>";die();}if ($this->username === 'admin') {global $flag;echo $flag;}else{echo "</br>hello my friend~~</br>sorry i can't give you the flag!";die(); }}
}
將2
改為3
,即可獲取flag。
php原生類
php原生類
-
PHP有哪些原生類
//查找PHP所有原生類 <?php $classes = get_declared_classes(); foreach ($classes as $class) {$methods = get_class_methods($class);foreach ($methods as $method) {if (in_array($method, array('__destruct','__toString','__wakeup','__call','__callStatic','__get','__set','__isset','__unset','__invoke','__set_state'))) {print $class . '::' . $method . "\n";}} }
-
常見使用的原生類
淺析PHP原生類 -
配合官方文檔利用php原生類
-
反序列化字符逃逸
[安恒月賽]反序列化字符逃逸