开源CMS源码审计基础,查找代码安全缺陷
开源CMS源码审计是通过阅读代码来发现安全缺陷的过程,尤其适合使用WordPress、DedeCMS、PbootCMS等系统的运维人员。
你不需要是安全专家,只要会基本的Linux命令和PHP语法,就能用grep和代码审计工具找出SQL注入、XSS跨站脚本、文件包含等常见漏洞。
本文从环境准备到漏洞定位,一步步带你完成第一次代码安全排查。
审计前需要准备的工具和环境
把源码下载到本地或测试服务器,不要在线上生产环境直接操作。
推荐用Docker快速搭建一个和线上一致的PHP运行环境,避免污染现有系统。
docker run -d --name audit-env -p 8080:80 -v /root/cms-src:/var/www/html php:7.4-apache
常用审计工具包括:
- grep、find、sed:系统自带,用于快速搜索危险函数和变量
- Seay源代码审计系统:Windows下的图形化工具,适合新手初步扫描
- RIPS:PHP专用静态分析工具,可检测复杂漏洞链
- phpStorm或VS Code:配合xdebug进行动态调试
建议先用grep做一轮快速过滤,再针对高风险文件人工精读。 自动化工具会输出大量误报,最终判断仍需人工确认。
从危险函数入手定位可疑代码
开源CMS的漏洞大多集中在几类函数上。
打开终端,进入源码根目录,执行以下命令搜索常见危险模式:
# 搜索可能直接执行SQL的语句
grep -rn "mysql_query\|mysqli_query\|->query" --include="*.php" . | grep -v "function" | head -50
# 搜索文件包含相关函数
grep -rn "include\|require\|include_once\|require_once" --include="*.php" . | grep -v "function" | head -50
# 搜索文件上传和写入操作
grep -rn "move_uploaded_file\|file_put_contents\|fwrite" --include="*.php" .
# 搜索直接输出GET/POST变量的位置
grep -rn "echo \$_GET\|echo \$_POST\|print \$_GET\|print \$_POST" --include="*.php" .
执行后重点看变量是否经过过滤。
如果$_GET['id']直接拼接到SQL语句中,基本可以判定存在注入风险。
例如:
$id = $_GET['id'];
$sql = "SELECT * FROM articles WHERE id = $id";
$result = mysqli_query($conn, $sql);
这段代码没有使用intval()或预处理语句,攻击者可以通过?获取数据库内容。手动审计时,优先检查所有接收用户输入并直接拼接进SQL、文件路径或输出到页面的变量。
id=1 UNION SELECT ...
人工精读高风险模块
自动化搜索只能提供线索,真正确认漏洞需要阅读上下文。
重点关注后台管理目录、文件上传接口、模板渲染文件和API接口文件。
以文件上传为例,找到上传处理文件(常见路径如/admin/upload.php或/api/upload.php),检查是否验证了文件类型和扩展名:
// 不安全示例:仅判断MIME类型
if ($_FILES['file']['type'] == 'image/jpeg') {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
}
// 相对安全的做法:白名单验证扩展名并重命名
$allow = ['jpg', 'png', 'gif'];
$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
if (in_array($ext, $allow)) {
$newName = md5(uniqid()) . '.' . $ext;
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $newName);
}
如果上传目录可以通过URL直接访问且允许PHP执行,
攻击者就能上传webshell。审计时要确认上传目录是否有执行权限限制,
比如在Nginx中配置location ~* /uploads/.*\.php$ { deny all; }。
避开审计过程中的常见陷阱
新手容易犯几个错误。
第一,只依赖工具扫描结果,不读代码上下文,导致漏报或误报。
第二,在线上环境直接测试漏洞,可能触发告警或影响业务。
第三,忽略CMS版本差异,不同版本的过滤函数可能完全不同。
执行任何测试前,请确认:
- 源码版本与官方发布版本一致,必要时核对文件哈希值
- 测试环境已断开外网访问或限制在隔离网络内
- 已备份数据库和源码,避免测试导致数据损坏
- 不要使用真实用户数据作为测试参数
如果发现疑似漏洞,建议先到CMS官方仓库搜索是否已有修复补丁,再决定是否自行修复或升级。 不建议在公开渠道直接披露未修复的漏洞细节。
验证审计结果是否准确
找到可疑代码后,需要构造无害的测试请求来验证。
例如,怀疑article.php?存在SQL注入,可以在测试环境尝试:
id=
curl "http://localhost:8080/article.php?id=1' AND SLEEP(3)-- "
如果响应时间明显延长,说明注入存在。
对于XSS,可以提交``观察是否被原样输出。
验证过程必须使用无害的payload,禁止在真实站点上测试删除、写入等破坏性操作。
审计完成后,
整理一份缺陷清单,
记录文件路径、
行号、
风险类型、
验证结果和修复建议。源码审计的目标不是找出所有漏洞,
而是建立持续排查的习惯,
在每次CMS升级或安装新插件后快速复查关键文件。
常见问题
没有PHP基础能学源码审计吗? 可以,但需要先了解变量、函数、数组和基本语法。
建议花两天时间过一遍PHP官方手册的入门章节。
grep搜索太慢怎么办? 限定文件类型和目录范围,比如只在/admin和/api目录下搜索,或者使用ripgrep替代grep,速度更快。
审计出的漏洞可以直接公开吗? 不可以。
应先联系CMS官方或厂商,给予合理修复时间,遵循负责任的披露流程。
有没有自动化审计工具推荐? 可以尝试RIPS、Seay或CodeQL,但工具结果必须人工复核,不能直接作为漏洞报告。