serVuln4 create_fucntion与可变函数
源码
|
POC
|
O:6:"Cancer":1:{s:3:"key";s:114:"a:2:{i:0;O:7:"GetFlag":2:{s:4:"code";s:16:"}system('ls');//";s:4:"func";s:15:"create_function";}i:1;s:6:"create";}";} |
注意:两个类实例化调用属性的顺序。
传入payload
,得到
Cancer::__destruct |
payload
被反序列化,触发Cancer
类的 destruct
方法,进而key
被反序列化,也就是unserialize(serialize(array($getflag, "create")))();
,这段代码会调用 GetFlag::create
方法。
这是因为在 PHP 中,array($getflag, "create")
创建了一个包含两个元素的数组,第一个元素是 GetFlag
类的一个实例 $getflag
,第二个元素是字符串 “create”。在 PHP 中,这样的数组可以被解释为一个回调函数,其中 $getflag
是要调用方法的对象,”create” 是要调用的方法名。
而array($getflag, "create")()
与call_user_func(array($getflag, "create"))
是等价的,可以看一个demo
|
回到题目,调用GetFlag::create
方法后,由于GetFlag
类中存在$a('', $this->code);
,这里为了减小难度,直接提示create_function('', $this->code)
,考虑 create_function
函数的特性,这里会创建一个新的匿名函数,并将其函数体作为字符串传递给 eval()
函数。eval()
函数会执行这个字符串中的 PHP 代码。
PS:这也是create_function
被移除的原因
对于"}system('chdir');//"
,这段代码以 }
开头,会导致 eval()
函数认为当前的函数体已经结束,然后执行后面的 system('chdir');
代码,其中//
并不是注释符的作用,而是为了防止"}system('chdir');"
被完整解析,导致语法错误,//
可以用#
、{
代替,有兴趣可以测试一下这个demo
|
可变函数与create_function
引用自PHP手册:
- PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现回调函数等等
create_function
通过执行代码字符串创建动态函数。该函数已自PHP 7.2.0
起被废弃,并自PHP 8.0.0
起被移除- 相关知识: