本文目录导读:

针对PHP项目的代码审计,特别是使用Fortify这类静态应用安全测试(SAST)工具,需要结合工具的特点和PHP语言的特性来进行,以下是一套系统性的操作指南和关注重点:
Fortify在PHP审计中的核心能力与局限
核心能力:
- 数据流分析:追踪用户输入(
$_GET、$_POST、$_COOKIE)到敏感函数(eval、mysql_query、include)的路径。 - 语义分析:识别PHP特有漏洞模式(如变量覆盖、Type Juggling)。
- 配置识别:自动识别
php.ini中的危险配置(如allow_url_fopen=On)。
主要局限:
- 动态调用:难以处理可变函数(
$func())、call_user_func、反射API。 - 加密/混淆代码:无法分析
eval(base64_decode(...))这种多层编码。 - 框架特性:对Laravel的Facade、Symfony的Dependency Injection等高级特性支持不完整。
Fortify扫描前的环境准备
项目配置优化
<!-- fortify-sca.properties --> com.fortify.sca.ProjectRoot=/path/to/php/project com.fortify.sca.PhpVersion=8.1 com.fortify.sca.EnableDynamicCodeAnalysis=false com.fortify.sca.EnableControlFlowSensititivity=true
- 禁用动态分析:避免对
eval等执行大量假阳性探查。 - 设置PHP版本:新版本(7.4+)的空安全运算符、属性类型提示等语法需要对应版本解析器。
依赖库处理
# 将第三方库移出扫描范围,避免噪音 --exclude "vendor/" --exclude "node_modules/" --exclude "public/assets/"
Fortify报告的关键PHP漏洞类型分析
高危漏洞(需100%人工复核)
| 漏洞类型 | Fortify典型规则ID | 示例代码 | 审计要点 |
|---|---|---|---|
| SQL注入 | SQL Injection | $sql = "SELECT * FROM users WHERE id = " . $_GET['id']; |
检查是否使用预处理语句(PDO/MySQLi) |
| 命令注入 | Command Injection | exec("ping " . escapeshellcmd($_GET['ip'])); |
escapeshellcmd不够安全,应用escapeshellarg |
| 文件包含 | Path Manipulation | include("/var/www/".$_GET['page'].".php"); |
检查是否有basename()或白名单验证 |
| 反序列化 | Insecure Deserialization | $obj = unserialize($_COOKIE['data']); |
确认是否使用了allowed_classes参数 |
| SSRF | URL Redirector Abuse | file_get_contents($_POST['url']); |
检查是否有域名白名单或协议限制 |
典型误报处理
Type Juggling误报:if ($_GET['auth'] == "admin")会被标记为弱比较,但若输入仅为字符串则无害。Header Injection误报:header("Location: ".$user_input)若输入经urlencode()处理则为误报。Cookie Security:未设置HttpOnly标记时,若框架默认添加(Laravel默认开启),可标记为已修复。
人工审计的重点补充区域
Fortify遗漏的常见PHP安全场景:
伪全局变量覆盖
extract($_GET); // Fortify可能标记,但常误报
// 以下代码Fortify可能忽略:
foreach ($_GET as $key => $value) { $$key = $value; }
审计:检查extract、parse_str、import_request_variables的使用。
Phar反序列化漏洞
$phar = new Phar('test.phar');
// 当phar文件内容可控时,触发phar://反序列化
审计:所有file_exists、is_dir等文件操作函数若参数含phar://则危险。
PHP-FPM配置错误
; Fortify无法检测 security.limit_extensions = .php ; 允许上传.php文件
审计:检查Nginx/Apache配置是否限制上传目录的PHP执行权限。
修复建议与验证闭环
修复优先级矩阵
高影响 + 低利用难度 = 立即修复(如未过滤的$_GET直接拼接SQL)
高影响 + 高利用难度 = 重点规划(如反序列化需要特定类存在)
低影响 + 高利用难度 = 记录但不紧急(如某页面URL重定向的开放重定向)
验证步骤:
- 重新扫描:修复后对修改文件增量扫描,确认漏洞归零。
- 渗透测试:Burp Suite验证:
- 发送
?id=1' OR '1'='1确认SQL注入 - 发送
?file=../../etc/passwd确认路径穿越
- 发送
- 代码审查:人工检查修复是否引入新问题(如过滤过于严格导致功能异常)。
自动化审计脚本示例
结合Fortify结果,使用PHP_CodeSniffer自定义规则:
// 自定义嗅探规则:禁止使用双引号中的变量
$sniff = new PHP_CodeSniffer();
$sniff->registerRule('Generic.PHP.DisallowDoubleQuoteVariable');
集成CI/CD:
# GitLab CI
php-audit:
script:
- sourceanalyzer -b myapp -scan -f results.fpr
- BIRTReportGenerator -format PDF -source results.fpr -output report.pdf
- Fortify是高效的“警卫”而非“侦探”:它能快速发现明显的SQL注入、XSS,但需要人工补充审计动态调用和业务逻辑漏洞。
- 重点关注“输入流到输出流”的完整链路:即使看似安全的参数也可能通过
$_SERVER、getenv()等间接来源进入危险函数。 - PHP版本适配:PHP8.0的
match表达式、8.1的枚举类型可能绕过Fortify旧版规则,需升级扫描器。
建议定期运行以下命令生成增量报告以跟踪修复进度:
sourceanalyzer -b myapp -scan -f latest.fpr -filter "Category:SQL Injection"