PHPCMS漏洞分析合集(下)
字数 1343 2025-08-27 12:33:37
PHPCMS漏洞分析与利用教学文档
1. PHPCMS v9.6.1 任意文件读取漏洞
1.1 漏洞位置
phpcms/modules/content/down.php 文件中的 download 方法
1.2 漏洞原理
- 漏洞点在于
file_down函数的第一个参数(文件路径)可控 - 文件路径参数经过加密处理,使用
$pc_auth_key作为加密密钥 - 文件后缀黑名单校验存在缺陷,可通过
><字符替换绕过(如.ph<p)
1.3 攻击链分析
- 加密字符串
$downurl通过模板输出到前台 - 加密字符串由
$i、$d、$s三个变量组成$i经过intval过滤$d和$s未过滤
- 加密过程与之前版本的SQL注入漏洞类似
1.4 绕过限制技巧
- 访问php文件或路径穿越:
- 后缀可设置为
ph>p - 路径符可变成
.>.
- 后缀可设置为
- 由于
safe_replace函数会进行替换,>字符需要双重编码:%25253e
1.5 漏洞修复分析
v9.6.2补丁将后缀匹配规则放在离下载文件最近的地方,但仍可通过Windows特性绕过:
- Windows系统下可绕过正则检查
2. PHPCMS v9.6.2 前台SQL注入漏洞
2.1 漏洞前提
需要先利用任意文件读取漏洞获取加密密钥
2.2 漏洞位置
phpcms/modules/member/classes/foreground.class.php
2.3 漏洞原理
- 程序直接将解密后的数据未经过滤直接带入SQL查询
- 待解密数据
$phpcms_auth和解密密钥$auth_key均可构造
2.4 攻击链分析
- 获取加密密钥:
- 通过任意文件读取获取
caches/configs/system.php中的auth_key
- 通过任意文件读取获取
- 构造
$phpcms_auth:- 从cookie中的
xxx_auth字段解密获得 - 默认使用
pc_base::load_config('system', 'auth_key')作为解密密钥
- 从cookie中的
- 构造
$auth_key:- 由
$prefix、auth_key和ip()决定 - IP可通过伪造获取
- 由
2.5 漏洞利用条件
- 只能在Windows系统上利用
- 需要先获取加密密钥
2.6 漏洞修复分析
v9.6.3补丁将解密后获得的 $userid 进行了强制类型转换
3. 漏洞利用总结与防御建议
3.1 漏洞利用总结
- 历史漏洞分析有助于发现新的攻击链
- 补丁可能只是临时修复,安全隐患可能仍然存在
- 新功能可能引入新的利用点,可与历史风险点结合
3.2 防御建议
- 对所有用户输入进行严格过滤
- 避免直接使用解密数据进入SQL查询
- 对文件路径进行严格校验,避免目录穿越
- 及时更新到最新版本
- 对加密密钥进行保护,避免泄露
3.3 代码审计要点
- 关注文件操作函数(如
file_down)的参数控制 - 检查加密/解密过程的数据过滤
- 注意黑名单机制的绕过可能性
- 跟踪用户输入的全流程处理
4. 附录:关键函数与代码片段
4.1 文件下载关键代码
// phpcms/modules/content/down.php
function download() {
// ... 省略其他代码 ...
$fileurl = str_replace(array('<','>'), '', $fileurl);
file_down($fileurl);
}
4.2 SQL注入关键代码
// phpcms/modules/member/classes/foreground.class.php
$phpcms_auth = sys_auth($_COOKIE[$this->session_var], 'DECODE');
$auth_key = get_auth_key('login');
$userinfo = explode("\t", sys_auth($phpcms_auth, 'DECODE', $auth_key));
$this->db->update($userinfo, array('userid'=>$userinfo[0]));
4.3 加密密钥获取
// 获取系统auth_key
pc_base::load_config('system', 'auth_key');
// 获取动态auth_key
function get_auth_key($prefix) {
$auth_key = $prefix.pc_base::load_config('system','auth_key').ip();
return $auth_key;
}