public function __call($method, $args){ if (function_exists($method)) { return call_user_func_array($method, $args); }}但是,像上面这种形式的__call方法,是很难利用的,因为$method在反序列化链中通常是不能控制的,但是师傅不愧是师傅,漏洞作者发现了Request对象中的__call方法是这么写的:
public function __call($method, $args){ if (array_key_exists($method, $this->hook)) { array_unshift($args, $this); return call_user_func_array($this->hook[$method], $args); } throw new Exception('method not exists:' . static::class . '->' . $method);}同样的,这里的$method不可控,但是$this->hook可控呀....那咱不就已经RCE了吗 。
别着急,我们好像忘了什么东西,这里还对$args进行了一波array_unshift操作,直接把$this放到了$args数组的最前面,到这里可能大家已经忘了$args是多少了,根据我最开始提供的poc,他的值就是["calc.exe","calc"],但是现在前面插了一个$this,$this现在代表的是那个对象呢,就是Request的实例,此时,如果我们控制$this->hook[$method]的值为['某个对象','方法'],那么这一处call_user_func_array,经过反序列化调用就变成了
某个对象->方法($this,"calc.exe","calc"),而且这个$this代表的是request类的实例 。到这里,如果是我挖到了这里,按我这个菜鸟的思路,我可能会寻找某个类中是否有一个方法,这个方法内调用了一些类似eval,system,call_user_func等危险函数,并且正好是用的方法的后两个参数,也就是这里的 calc.exe, calc这两个位置的参数中的某一个,如果找不到,俺就没有办法了 。但是师傅就是师傅啊~他们还知道tp有filter这一用法,于是理所当然的继续构造攻击链

文章插图
此时此刻,我哪怕是能说出,俺也一样~,也是值得自豪的呀,奈何只能靓仔落泪,和大佬比起来,除了帅,我一无所有
虽然我不知道这个师傅是怎么想到filter的,也不知道filter有啥用,但是在我分析的过程中,我悟出了在遇到这种情况下的另一种思路,既然找不到我上面说的那种类,那么是否可以找到一个类中的方法,这个方法里面调用了危险函数,而且这个危险函数不用我刚刚call_user_func_array传过去的$args,但是这个危险函数的参数又都是我们可控的?
听起来是不是有点绕?而且貌似有点难操作,但是要记得我们这是在利用啥漏洞,这是反序列化呀,如果危险函数的参数全是使用的它所在的对象的属性,那么是不是有得搞?为了方便理解,我构造一个小demo:
<?phpclass Test{ public $name; public $age; public function show($height=180){ eval($name+":"+$age); }}例如像上面这个例子是不是就是不用任何传参,而且我们可以控制eval中的内容?而这个利用链接下来要做的事其实就是找到这个函数,只不过作者找这个函数的过程我觉得很牛逼,因为这个函数藏的挺深的,说到这,我又想哭了
文章插图
在这里插入图片描述
为了方便叙述我们还是跟着poc来吧,可以看到poc中出现的类已经都在我的文章中登场了,所以最后的RCE触发点也必然产生在这几个类中,现在唯独还没有摸清楚的类就是Request了,可以看到POC中的request类$this->filter为system,所以我们也就猜测肯定是反序列化过程中在request类中的某一个方法里调用了代码执行的危险函数(eval、call_user_func、call_user_func_array、preg_replace、array_map等等),然后我采取的策略就是在Request这个类中搜索这些危险函数,发现Request类中有四个方法调用了危险函数call_user_func,分别是__call、token、cache、filterValue,首先排除__call,然后token以及cache里调用的call_user_func的参数我们都是不可以控制的,虽然一眼看过去filterValue()函数处的参数value我们也不可以控制,但是filterValue()被Request类中的其他方法调用了,我们回溯一下,看看调用处的传参我们是否可以控制呢 。
为了便于理解,下面贴出filterValue函数(可以看到,如果要实现代码执行,我们需要完全控制call_user_func的参数,但是如果我们直接在__call方法中直接调用filterValue(),那么现在$value的值始终是[$this,xxx,xxx]形式的,导致我们无法实现RCE,所以我们是不能直接调用filterValue函数实现RCE的,那么我们就要看看是不是能够通过间接调用filterValue实现)
推荐阅读
- 《金铲铲之战》黎明最强阵容是什么?
- 古茶树不能承受之重,古曼撒之冷庙古树茶
- 工夫红茶是什么意思,功夫红茶与工夫红茶字之差
- 父亲节走心茶礼,厨心熟茶品质口碑和品牌之路
- 广州旅游攻略之必去景点
- 高桥银峰的作用有哪些,高桥银峰营养成分分析
- 十大名菜之首 抗癌防癌并有“富硒食品”之称
- 凤宁号茶叶加盟信息,佛山市南海区春之茗茶叶加盟八方茶园
- 贡眉是福鼎白茶之,福鼎大白与福鼎大毫的关系
- 各用沏茶用水知识解说,沏茶用水之软水
