本文目录导读:

- 使用 Semgrep(最灵活、社区活跃)
- 使用 PHPStan(原生强类型检查 + 扩展规则)
- 使用 Psalm(内置安全检查器)
- 使用 SonarQube(企业级 UI 界面)
- 手动审计 + 自定义扫描脚本(低成本方案)
- 总结:如何选择策略?
在 PHP 项目中进行代码审计时,自定义新增审计策略通常是为了匹配业务特有的风险或框架特定的不安全写法,不同的静态分析工具(如 SonarQube、Semgrep、PHPStan、Phan、RIPS 或商业化的 Fortify/Checkmarx)实现方式各异。
以下是针对主流工具和手动审计流程,如何自定义新增审计策略的详细步骤:
使用 Semgrep(最灵活、社区活跃)
Semgrep 是目前最适合自定义规则的开源工具,支持模式匹配、数据流追踪和污点分析。
- 规则文件格式:YAML
- 存放位置:通常放在项目根目录的
.semgrep/或单独创建rules/文件夹。
步骤:
-
创建规则文件:
custom-php-rules.yaml。 -
编写规则模板:
rules: - id: php-custom-unsafe-deserialize pattern: | unserialize(...) message: "发现不安全的反序列化调用,可能导致远程代码执行" languages: [php] severity: ERROR metadata: cwe: CWE-502 -
编写高级策略(结合数据流和上下文):
rules: - id: php-custom-ssrf-curl patterns: - pattern-either: - pattern: | curl_setopt($ch, CURLOPT_URL, $url) - pattern: | file_get_contents($url) - pattern-inside: | $url = $_GET['url']; ... - pattern-inside: | $url = $_REQUEST['url']; ... message: "来自用户输入的URL直接传入HTTP请求函数,可能导致SSRF" languages: [php] severity: WARNING -
运行:
semgrep --config custom-php-rules.yaml .
使用 PHPStan(原生强类型检查 + 扩展规则)
PHPStan 侧重于静态类型分析和控制流,但可以通过PHP 扩展自定义审计规则。
- 最佳实践:编写自定义 PHPStan 规则扩展。
- 存放位置:
src/Rules/Audit/
步骤:
-
安装 PHPStan:
composer require phpstan/phpstan --dev -
创建 PHP 类实现规则接口:
// src/Rules/Audit/NoEvalRule.php use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; class NoEvalRule implements Rule { public function getNodeType(): string { return Node\Expr\FuncCall::class; } public function processNode(Node $node, Scope $scope): array { if ($node->name instanceof Node\Name && strtolower($node->name->toString()) === 'eval') { return ['禁止使用 eval() 函数,存在代码注入风险']; } return []; } } -
注册规则:在
phpstan.neon中配置:rules: - App\Rules\Audit\NoEvalRule
-
运行:
vendor/bin/phpstan analyse src/
使用 Psalm(内置安全检查器)
Psalm 同样支持自定义审计策略,通过插件机制。
- 推荐方式:使用 Psalm 插件。
- 存放位置:
Psalm/Plugin/
步骤:
-
创建插件类:
// Psalm/Plugin/CheckShellExec.php use Psalm\Plugin\PluginEntryPointInterface; use SimpleXMLElement; class CheckShellExec implements PluginEntryPointInterface { public function __invoke(RegistrationInterface $registration, ?SimpleXMLElement $config = null): void { require_once __DIR__ . '/Internal/ShellExecChecker.php'; $registration->registerHooksOnClass(ShellExecChecker::class); } } -
编写检查器(监听函数调用事件)。
-
配置
psalm.xml:<plugins> <pluginClass class="Psalm\Plugin\CheckShellExec" /> </plugins>
使用 SonarQube(企业级 UI 界面)
SonarQube 允许通过 规则模板 或 自定义规则(Java 或 JavaScript) 来添加 PHP 安全策略。
- 使用规则模板(最简单):
- 进入:Quality Profiles → 选择 PHP 规则集 → 点击“Create”。
- 定义:输入规则名称、描述(检测直接使用
$_GET[‘password’]”)和正则表达式模式(如\$_GET\['password'\])。
- 编写插件:
- 开发一个 SonarQube 插件(Java 或 JS)。
- 继承
AbstractCheck类,重写scanFile或使用AstWalker。
手动审计 + 自定义扫描脚本(低成本方案)
如果不想依赖复杂工具,可以编写简单的 Shell / Python / PHP 脚本 实现自定义规则。
示例:检测危险函数调用
#!/bin/bash # custom_audit.sh echo "=== 自定义审计:检测危险函数 ===" grep -rn --include="*.php" "\b(eval|assert|preg_replace.*/e|exec|system|passthru|shell_exec)\b" . | grep -v "vendor/" | grep -v ".git/"
示例:检测 SQL 拼接
grep -rn --include="*.php" '$sql.*\$' . | grep -v vendor/ | grep -i 'SELECT\|INSERT\|UPDATE\|DELETE'
如何选择策略?
| 场景 | 推荐工具 | 自定义方式 | 复杂度 |
|---|---|---|---|
| 快速、轻量、团队协作 | Semgrep | YAML 模式匹配 + 数据流 | 低 |
| 深度静态分析、类型安全 | PHPStan / Psalm | PHP扩展 + 插件 | 高 |
| 企业级集成、可视化 | SonarQube | 模板 / Java插件 | 中 |
| 临时、紧急、无CI/CD | Grep / Bash 脚本 | 正则表达式 | 极低 |
核心建议:对于大多数 PHP 团队,Semgrep 是最高性价比的选择,你可以从编写简单的模式规则(如禁止 extract($_GET))开始,逐步过渡到编写跨文件的数据流规则(如 $_GET -> 执行)。