前言
Joomla! 是一套全球知名的内容管理系统,由 PHP 加上 MySQL 数据库所开发的软件系统。近日,Joomla! 3.7.0 Core 版本被发现存在 SQL 注入漏洞,漏洞出现在此版本新引入的 com_fields 组件,这个组件对访问者身份没有限制,也就是说任何人都可以访问到这个组件,并发起带有 SQL 注入语句的恶意请求。
我使用了由 phithon 维护的一套开源漏洞靶场,在本地搭建了 joomla 3.7.0 版本环境,并下载了该版本的建站源码进行了简单的分析。
漏洞靶场环境:https://github.com/phith0n/vulhub/tree/master/joomla/CVE-2017-8917 建站源码下载:https://downloads.joomla.org/
漏洞复现
首先搭建漏洞靶场环境。

按照要求进行初始设置后,我们对index页面做如下请求:
/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml(1,concat(0x3e,user()),0)
此时成功引发数据库报错,如下:

漏洞分析
0.根据 POC 可知,漏洞出现在 com_fields 组件,在 Joomla 3.7.0 版本的 com_fields 组件中,其控制器函数如下:

1.当请求中参数 view 为 fields 并且 layout 为 modal 时,会从 JPATH_ADMINISTRATOR 中加载 com_fields,管理员的 com_fields 组件中 models/field.php 文件内有一个 getListQuery 函数,关键代码如下:

2.程序通过 getState 函数获取到 list.fullordering,将内容赋值给 listOrdering 变量,该变量经过 $db->escape 函数处理后传入到 $query->order 函数中。首先来看下 escape 函数:

3.mysql_real_escape_string 为 PHP 的一个转义函数,转义下面的一些特殊字符,可以看到,除了对单引号双引号等常见特殊字符进行了转义,并没有对更多的字符进行过滤。

4.而经过 mysql_real_escape_string() 转义的字符串传入到 $query->order 函数,该函数也没有对传入的内容做更多的过滤就将字符串拼接到 order by 后带入了数据库进行查询。再回到 2 看看如何对 list.fullordering 进行控制。list.fullordering 会在视图的 display 中进行设置:

5.state 调用了 get 函数,该函数定义如下:

6.在416行处可以看到 $method 为 get 与传入的 $property 拼接后的内容,根据上一张图可知传入的实参为 State,拼接后为 getState,getState 作为方法被调用,下图为 getState 函数定义:

7.此处调用了 populateState() 函数,我们看下该函数的定义。

8.这里调用了父类的 populateState 方法,父类在 /libraries/legacy/model/list.php 文件中定义:

9.其中程序通过 $app->getUserStateFromRequest 获取一个 list,list 被赋值给 $list,这时再看我们的注入语句:
/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml(1,concat(0x3e,user()),0)
可以看到 list 中的 fullordering 被赋值为 updatexml(1,concat(0x3e,user()),0),然后通过 2 提到的 getState 函数处理,最终经过 $db->escape 函数将内容传入到 $query->order 函数,与 order by 拼接后带入数据库,从而造成 SQL 注入。
作者: JenI 转载请注明出处,谢谢
Comments !