PHP项目统计区域防守漏洞出现次数的分析方法
你这个问题比较笼统,我理解你可能是想统计PHP项目中某个功能区域(如登录、上传、API等)存在的防守类漏洞出现次数,下面给你一套可落地的思路和代码示例。

先明确"区域"和"漏洞"的定义
| 概念 | 说明 |
|---|---|
| 区域(区域防守) | 按业务模块划分:登录区、支付区、上传区、后台区、API区等 |
| 防守漏洞 | 指防御措施缺失/失效的漏洞,如:未校验、未过滤、未鉴权、未限流、未加密等 |
常见"防守漏洞"类型:
- SQL注入(未参数化)
- XSS(未转义)
- CSRF(无token)
- 越权(无权限校验)
- 文件上传(无类型/大小校验)
- 暴力破解(无验证码/限流)
- 敏感信息泄露(未脱敏)
方案一:基于代码静态扫描统计
如果你要统计代码里这些漏洞出现几次,可以用正则+AST扫描。
示例:扫描SQL拼接漏洞
<?php
// scan_defense.php —— 统计各区域防守漏洞出现次数
$regions = [
'login' => __DIR__ . '/app/Login',
'upload' => __DIR__ . '/app/Upload',
'api' => __DIR__ . '/app/Api',
'admin' => __DIR__ . '/app/Admin',
];
// 漏洞规则:模式 => 类型
$rules = [
'/\$_(GET|POST|REQUEST|COOKIE)\s*\[/' => '未过滤输入',
'/mysql_query\s*\(/' => 'SQL注入风险',
'/->query\s*\(\s*[\'"].*\$/' => 'SQL拼接',
'/echo\s+\$_(GET|POST|REQUEST)/' => 'XSS输出未转义',
'/move_uploaded_file\s*\(/' => '上传未校验',
'/md5\s*\(\s*\$_(GET|POST)/' => '弱哈希',
];
$result = [];
foreach ($regions as $name => $dir) {
if (!is_dir($dir)) continue;
$result[$name] = array_fill_keys(array_values($rules), 0);
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir)
);
foreach ($it as $file) {
if ($file->getExtension() !== 'php') continue;
$code = file_get_contents($file->getPathname());
foreach ($rules as $pattern => $type) {
$count = preg_match_all($pattern, $code);
$result[$name][$type] += $count;
}
}
}
// 输出统计表
printf("%-10s", '区域');
foreach (array_values($rules) as $t) printf("%-18s", $t);
echo PHP_EOL;
foreach ($result as $region => $types) {
printf("%-10s", $region);
foreach ($types as $c) printf("%-18d", $c);
echo PHP_EOL;
}
// 汇总总数
$total = 0;
foreach ($result as $types) $total += array_sum($types);
echo "\n漏洞总数: {$total}\n";
运行:
php scan_defense.php
输出示例:
区域 未过滤输入 SQL注入风险 XSS输出未转义 上传未校验
login 3 1 2 0
upload 5 0 1 4
api 8 6 3 0
admin 2 2 1 1
漏洞总数: 39
正则扫描误报较多,生产环境建议用 PHPStan / Psalm / Semgrep 做AST级扫描。
方案二:基于日志统计实际攻击次数
如果你想统计线上实际被攻击/触发防守漏洞的次数,需要记录日志。
在防护点埋点
function logDefense($region, $type, $detail = '') {
$line = sprintf(
"[%s] region=%s type=%s ip=%s uri=%s detail=%s\n",
date('Y-m-d H:i:s'),
$region, $type,
$_SERVER['REMOTE_ADDR'] ?? '-',
$_SERVER['REQUEST_URI'] ?? '-',
$detail
);
file_put_contents('/var/log/defense.log', $line, FILE_APPEND);
}
// 使用示例:登录区
if (!preg_match('/^[a-zA-Z0-9_]{4,20}$/', $_POST['user'])) {
logDefense('login', '非法用户名', $_POST['user']);
}
统计脚本
<?php
$log = file('/var/log/defense.log', FILE_IGNORE_NEW_LINES);
$stat = [];
foreach ($log as $line) {
if (preg_match('/region=(\S+) type=(\S+)/', $line, $m)) {
$stat[$m[1]][$m[2]] = ($stat[$m[1]][$m[2]] ?? 0) + 1;
}
}
foreach ($stat as $region => $types) {
echo "【{$region}】 共 " . array_sum($types) . " 次\n";
arsort($types);
foreach ($types as $t => $c) echo " - {$t}: {$c}\n";
}
输出:
【login】 共 128 次
- 非法用户名: 90
- 密码错误过多: 38
【upload】 共 45 次
- 非法文件类型: 40
- 超大文件: 5
方案三:数据库统计(推荐用于系统化)
CREATE TABLE defense_log (
id INT AUTO_INCREMENT PRIMARY KEY,
region VARCHAR(50), -- 区域
vuln_type VARCHAR(100), -- 漏洞类型
ip VARCHAR(45),
uri VARCHAR(255),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX(region, vuln_type)
);
-- 按区域统计各漏洞出现次数
SELECT region, vuln_type, COUNT(*) AS cnt
FROM defense_log
GROUP BY region, vuln_type
ORDER BY region, cnt DESC;
-- 只看总数
SELECT region, COUNT(*) AS total FROM defense_log GROUP BY region;
建议选择
| 你的目标 | 推荐方案 |
|---|---|
| 评估代码质量 | 方案一(Semgrep/PHPStan) |
| 监控线上攻击 | 方案二(日志埋点) |
| 长期运营统计 | 方案三(数据库) |
| 两者结合 | 埋点写库 + SQL聚合 |
如果你能告诉我:
- 是扫描代码还是统计线上日志?
- "区域防守"具体指哪些区域(登录/支付/上传…)?
- "漏洞"具体指哪些类型?
我可以给你写出可直接运行的完整脚本。