Joomla 3.9.13 二次注入分析(CVE-2019-19846)
字数 1595 2025-08-26 22:11:45
Joomla 3.9.13 二次SQL注入漏洞分析(CVE-2019-19846)教学文档
漏洞概述
本漏洞是Joomla 3.9.13版本中存在的一个需要管理员权限的二次SQL注入漏洞(CVE-2019-19846)。漏洞存在于components/com_content/models/articles.php文件中,由于对用户输入参数date_field未进行充分过滤,导致攻击者可以通过精心构造的输入执行SQL注入攻击。
漏洞分析
漏洞位置
漏洞核心代码位于components/com_content/models/articles.php文件的第458行左右:
$dateFiltering = $this->getState('filter.date_filtering', 'off');
$dateField = $this->getState('filter.date_field', 'a.created');
switch ($dateFiltering) {
case 'range':
$startDateRange = $db->quote($this->getState('filter.start_date_range', $nullDate));
$endDateRange = $db->quote($this->getState('filter.end_date_range', $nullDate));
$query->where(
'(' . $dateField . ' >= ' . $startDateRange . ' AND ' . $dateField .
' <= ' . $endDateRange . ')'
);
break;
// ...
}
漏洞成因
date_field参数从getState('filter.date_field')获取后未经任何过滤直接拼接到SQL查询中- 虽然默认值为
a.created,但可以通过特定方式修改此值 - 当
date_filtering设置为range时,构造的恶意SQL会被执行
利用链分析
- 漏洞触发点:
articles模型中的SQL拼接点 - 参数来源:通过
mod_articles_popular或mod_articles_category模块设置 - 数据流:
- 攻击者通过后台编辑模块参数
- 恶意参数被保存到数据库的
modules表中 - 当模块被渲染时,从数据库读取参数并传递给
articles模型 - 恶意参数被拼接到SQL查询中执行
利用条件
- 需要超级管理员(super user)权限
- 需要能够编辑模块参数
- 由于有token校验,无法进行CSRF攻击
详细利用步骤
方法一:通过mod_articles_popular模块
- 以管理员身份登录系统
- 访问首页模块编辑界面
- 找到"热门文章"模块(mod_articles_popular)
- 修改以下参数:
- 设置
date_filtering为range - 设置
date_field为恶意SQL代码
- 设置
- 保存修改
方法二:通过mod_articles_category模块(更优)
- 以管理员身份登录系统
- 访问首页模块编辑界面
- 找到"分类文章"模块(mod_articles_category)
- 修改以下参数:
- 设置
date_filtering为range - 设置
date_field为恶意SQL代码 - 设置
article_ordering为1(绕过order by限制)
- 设置
- 保存修改
注入优化
通过mod_articles_category模块可以实现更好的注入效果,因为:
list.ordering参数可控,可以设置为1避免order by错误- 可以实现union注入获取数据回显
补丁分析
在Joomla 3.9.14版本中修复了此漏洞,主要修改是在模块的XML配置文件中为相关字段添加了validate="options"属性:
<field name="date_field" type="list" default="a.created" label="JFIELD_DATE_FIELD_LABEL" description="JFIELD_DATE_FIELD_DESC" validate="options">
<option value="a.created">JCREATED</option>
<option value="a.modified">JMODIFIED</option>
<option value="a.publish_up">JSTART_PUBLISHING</option>
<option value="a.publish_down">JFINISH_PUBLISHING</option>
</field>
补丁原理
validate="options"会触发OptionsRule验证- 验证时会检查输入值是否在预定义的option列表中
- 如果不在列表中,则拒绝保存
验证流程:
- 从XML配置中读取所有合法的option值
- 使用
in_array()或array_diff()检查用户输入 - 只有输入值在合法列表中时才允许保存
防御建议
- 对所有用户输入进行严格的过滤和验证
- 使用参数化查询或预处理语句
- 遵循最小权限原则,限制管理员权限
- 及时更新到最新版本
总结
CVE-2019-19846是一个典型的二次SQL注入漏洞,虽然需要管理员权限才能利用,但仍然存在潜在风险。漏洞的根本原因在于对用户输入缺乏充分验证,直接将用户可控参数拼接到SQL查询中。开发者应引以为戒,对所有用户输入(包括管理员输入)都进行严格验证,并使用安全的数据库查询方式。