1. LmxCMS 漏洞分析与复现
本章节主要针对 LmxCMS 的 MVC 架构特征及其存在的二次 URL 编码 SQL 注入漏洞进行分析。
1.1 MVC 路由特征识别
在对 MVC 框架进行审计时,首先需要识别其路由分发模式。LmxCMS 支持多种 URL 模式,这是构造 Payload 的基础。
- 1.1.1 路径模式 (Path Info):
- 结构:
/index.php/content/id/1.html或/index.php/content/id/1 - 特征:参数以路径形式传递。
- 结构:
- 1.1.2 参数模式 (Query String):
- 结构:
/index.php?m=list&a=index&classid=1 - 特征:传统的
m(Module/Model) 和a(Action) 参数传递。
- 结构:
1.2 双重 URL 编码注入原理
在 Tags 模块中,为了绕过某些过滤或满足代码逻辑,需要对 Payload 进行双重 URL 编码。
-
1.2.1 原始攻击代码 (PoC):
SQL
1' and updatexml(0,concat(0x7e,user()),1)# -
1.2.2 编码流程分析:
- 一次编码 (%27):如果仅进行一次编码,浏览器可能会将其视为合法字符发送,或者被服务器中间件(如 Apache/Nginx)自动解码,导致进入 PHP 代码时直接变为单引号
',容易被 GPC 或 WAF 拦截。 - 二次编码 (%2527):
- 客户端发送:
%2533%31...(对%再次编码为%25)。 - 中间件层:服务器接收请求时,进行第一次解码,
%25变回%。此时 PHP 接收到的字符串包含%27(即 URL 编码后的单引号)。 - 应用层:代码逻辑中存在自定义的解码函数或处理逻辑,对
%27进行了第二次解码,还原为单引号',从而触发 SQL 注入。
- 客户端发送:
- 一次编码 (%27):如果仅进行一次编码,浏览器可能会将其视为合法字符发送,或者被服务器中间件(如 Apache/Nginx)自动解码,导致进入 PHP 代码时直接变为单引号
-
1.2.3 浏览器行为观测:
- 在 Burp Suite 中可以看到完整的二次编码 Payload。
- 在浏览器地址栏输入 Payload 回车后,视觉上可能看到结尾变成
%2529%2523,这是浏览器为了用户体验进行的视觉解码,实际发出的请求包需要通过抓包确认。
1.3 代码审计追踪
通过白盒审计追踪漏洞产生的根源。
- 1.3.1 漏洞入口:
- 文件:
TagsModel.class.php - 方法:
getNameData - 关键调用:
return parent::oneModel($param);
- 文件:
- 1.3.2 向上溯源:
- 在
TagsAction.class.php的__construct方法中调用了getNameData。 - 确定参数
$name可控且未经过滤直接传入。
- 在
- 1.3.3 向下挖掘:
- 搜索 SQL 关键字
SELECT。 - 定位
db.class.php中的$sql="SELECT ..."语句,确认$field或$We(where条件) 直接拼接了变量。
- 搜索 SQL 关键字
2. Rockoa MVC SQL 注入审计
本章节记录 Rockoa 系统中基于 insert 操作的 SQL 注入挖掘过程。
2.1 漏洞挖掘思路
采用关键词搜索与调用链追踪相结合的方式。
-
2.1.1 关键词定位:
-
全局搜索
insert关键字。 -
定位到
webmain/task/openapi/opendkqAction.php中的addkqjs方法:PHP
$uarr['id'] = m('kqjsn')->insert($uarr); -
确认
include/Model.php中的insert方法最终执行了 SQL 语句。
-
-
2.1.2 私有方法利用分析:
- 障碍:
addkqjs是一个私有或受保护的方法,无法直接通过 URL 访问。 - 突破口:寻找类内部调用
addkqjs的位置。
- 障碍:
2.2 调用链追踪 (Call Stack)
通过“右击用法”或全局搜索,还原完整的调用路径。
-
2.2.1 第一层调用:
- 方法:
senddata(位于opendkqAction.php) - 代码:
$snrs = $this->addkqjs($sn); - 状态:
senddata可能仍受访问控制或参数限制。
- 方法:
-
2.2.2 第二层调用 (Public Entry):
-
方法:
zktimeAction(位于opendkqAction.php) -
代码逻辑:
PHP
if(...) { $carr = $this->senddata(9); } -
结论:
zktime是对外公开的 Action,只要满足if条件,即可触发senddata,进而触发addkqjs中的 SQL 注入。
-
2.3 Payload 构造
根据 MVC 的路由规则构造最终攻击 URL。
-
2.3.1 路由格式:
- 域名:
http://www.cx770.local:1572 - 模块与动作:
m=opendkq|openapi(对应文件路径task/openapi/opendkqAction.php),a=zktime。
- 域名:
-
2.3.2 最终 URL 结构:
Plaintext
/index.php?a=zktime&m=opendkq|openapi&d=task&ajaxbool=true&rnd=717830(注:具体注入参数需根据 insert 中的 $uarr 数组构造 POST 或 GET 数据)