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()
进行过滤,只转义了一些字符。因此可以通过构造进行成功的注入。