callback噩梦:解析著名CMS框架Drupal SQL注入漏洞

Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由内容管理系统(CMS)和PHP开发框架(Framework)共同构成。连续多年荣获全球最佳CMS大奖,是基于PHP语言最著名的WEB应用程序。

前几天爆了一个 Drupal 的 SQL Injection 注入漏洞,但是这个漏洞不止与 SQL 注入这么简单,还可以利用其来 RCE(远程代码执行)。知名安全研究人员StefanEsser 在 Twitter 上也有提及,可是没有透露细节。 

14144811757999.png!small

不过今天再看的时候发现,远程代码执行的 exp 已经放出,那我也不藏着掖着了,把挖掘的过程记录一下,算是本人第一次代码审计的产物好了。

SE 说的是 Drupal 的 callbacks 造成的 RCE。那么我们审计的 point 就要在 callback 上。PHP 内置的一个函数 call_user_func_array 可以做到这一点,其中接受参数如下:

 

第一个参数是 function 的名称,第二个参数是要调用的参数的参数。

利用这几个特性,可以实现 Drupal 的各种花式 getshell。我只审计出来一种,还有很多方式并没有去实现(毕竟渣渣看不出来)。

Drupal特性引发漏洞

Drupal 有一个特性,可以让管理员添加 PHP tag 来写文章,叫做 PHP filter。这个特性默认是关闭的。当然,由于 PDO 可以执行多行 SQL 语句的特性,我们可以直接添加管理用户然后登录上去,打开 PHP filter 的 Module,然后发表文章,最后 getshell。

想要自动化也简单,那就是把从打开 PHP filter 到发表文章的所有执行过的 SQL 语句合在一起当作 Payload,最后 getshell。这个思路的 POC 我也做过,可惜太过于繁琐,最后 Payload 出来很长很长,一点也不优雅,而且并没有利用到 callback 的特性。为了钻个牛角尖,咱就来审计一下如何花式 getshell。

上文中说了 PHP filter 是一个可以执行 PHP 代码的特性,而 PHP filter 所在的文件是/modules/php/php.module这个文件,其中:

 

这个函数就是用来执行 custom php code 的函数。

callback引发命令执行

对于审计的工具,我这种渣渣直接就 find 然后 grep 定位文件,在用 phpstorm + ideavim(plugin of phpstorm),来跟踪函数,轻松愉快ow<。

我们很确定的是我们要找 call_user_func_array 这个函数,利用如下命令来查找:

其实我们可以进一步缩小范围,因为第一个函数是我们调用的函数,而如果我们想利用的话,call_user_func_array这个函数的第一个参数我们要可以控制,那么进一步缩小范围:

14144829757764.png!small

我们接下来就要查看上下文,看从哪里可以控制那个变量。经过逐一排查,我定位到/include/menu.inc这个文件中的menu_execute_active_handler函数。

阅读可以发现,我们可以控制$_GET['q']这个参数,接着进入menu_get_item这个函数。这个函数的核心代码是这里:

在 menu_router 里查询我们输入的$_GET['q'],然后从返回所有字段。接着回到menu_execute_active_handler函数。

 

这里取出router_item中的include_file,然后用require_once来包含。这里是一个 point,因为 Drupal 默认不开启 PHP filter,这里包含了就可以不用开启 PHP filter 了

接着取出router_item中的page_callback,带入call_user_func_array执行。

到此为止整个流程我们已经很清楚了。

需要注意的是page_arguments的第一个参数才会被执行,而第一个参数正是$_GET['q']的值。

利用测试

通过注入向 menu_router 表中插入一段数据

访问地址即可造成 RCE。

我们来测试一下。首先在数据库执行语句:

然后访问http://192.168.1.109/drupal/?q=%3C?php%20phpinfo();?%3E。

14144832192003.jpg!small

exp 已经放出了,地址戳,咱刚刚下了一个本子特赞,撸去了。