POC
这次干脆先放出poc吧。
这次根据参数的传入流程来进行分析。
漏洞
危害组件
3.7.0版本中出现了com_field组件,无需授权即可访问。查看...\components\com_fields\controller.php,在第27行左右,其相关代码如下:
可以看到它先判断通过view是否等于fields,layout是否等于modal,而这两个参数都是我们可控的。若满足则将会加载JPATH_ADMINISTRATOR中的com_fields组件,并且将base_path设置为 JPATH_COMPONENT_ADMINISTRATOR,之后调用父类的构造方法。
传入sql语句
在调用父类构造方法后,一路运行到...\Joomla370\libraries\legacy\controller\legacy.php中,约莫707行,这时会通过$this->$doTask调用display()函数。

跟进display()函数,它位于 ...\Joomla370\libraries\legacy\controller\legacy.php,接着运行至legacy.php的约莫671行左右,调用了视图(view)的display()函数。我们跟进一下,跳转进入...\Joomla370\administrator\components\com_fields\views\fields\view.html.php,

此时运行到,下面这条语句,给get()传入的参数为State
|
|
我们跟进这个get()函数,一直运行到422行,

之后将会调用 getState(),跟进,进入...\Joomla370\libraries\legacy\model\legacy.php

之后会调用filedsModel类中的populateState(),跟进后会发现调用其父类的populateState()函数,其定义在 ...\Joomla370\libraries\legacy\model\list.php中,约莫在第495行,相关代码如下:
这里我们先跟进一下getUserStateFromRequest(),它的定义在...\Joomla370\libraries\cms\application\cms.php中,在该函数结束后,它获取了我们通过get方法传入的参数,也就是说,我们成功的控制了fullordering的值。

在该函数运行完后,流程将会回到前面的那个定义在...\Joomla370\libraries\cms\application\cms.php中的populateState()函数。此时运行的代码如下:
如果数组的key不在黑名单(blacklisted)中,将会为$list变量根据相应的State进行注册,在这部分函数运行到结束部分,可以看见成功的控制了list数组的fullordering的值。

查看变量,如下:

注入过程
接下来继续运行,一直运行回到Joomla370\administrator\components\com_fields\views\fields\view.html.php中的display()函数中。

跟进这一行 $this->get('Items');,进入...\Joomla370\libraries\legacy\view\legacy.php,约莫在422行,这里的行为跟前面分析类似,此后将会调用getitem():

继续跟进,进入...\Joomla370\libraries\legacy\model\list.php,约莫在186行:
通过_getList调用了_getListQuery,继续跟进,进入...\Joomla370\libraries\legacy\model\list.php,约莫在 132行,
调用了 getListQuery(),继续跟进,进入 ...\Joomla370\administrator\components\com_fields\models\fields.php,一直运行到约莫在 305 行,调用getState方法,传入list.fullordering参数。相关代码如下:

查看变量表:

之后在第314行,将$listOrdering带入查询,相关代码如下:
在进行$query->order之前,会先进行一次过滤,跟进$db->escape,进入...\Joomla370\libraries\joomla\database\driver\mysqli.php,约莫242行,相关代码如下:
对于传入的$text通过mysqli_real_escape_string()进行过滤,只转义了一些字符。因此可以通过构造进行成功的注入。
成功注入
