PHP 怎么威胁建模

wen PHP项目 2

本文目录导读:

PHP 怎么威胁建模

  1. 第一步:绘制数据流图
  2. 第二步:应用 STRIDE 模型分析威胁
  3. 第三步:针对 PHP 特有弱点的专项威胁分析
  4. 第四步:落地缓解措施(以威胁为驱动)
  5. 实战案例:一个简单的 PHP 登录系统威胁建模
  6. 推荐的威胁建模工具与工作流
  7. 总结:PHP 威胁建模的“三步走”

在 PHP 开发中进行威胁建模,通常不是指用某种特定的工具扫描代码,而是指在系统设计阶段,系统性地识别、分类并缓解潜在的安全风险

针对 PHP 项目,威胁建模的核心思路通常遵循 STRIDE 模型,并结合 PHP 特有的“坑”(如类型松散、超全局变量滥用、反序列化等)。

以下是针对 PHP 项目的系统性威胁建模指南,分为四个步骤:


第一步:绘制数据流图

这是最重要的一步,你需要明确:

  1. 数据入口: 用户输入($_GET$_POST$_COOKIE$_FILES)、API 请求、Webhook、队列消息、第三方服务回调。
  2. 数据出口: SQL 查询、文件写入、日志记录、API 响应、邮件发送、命令行执行(exec)。
  3. 信任边界: 浏览器与服务器之间、服务器与数据库之间、服务器与文件系统之间、不同微服务之间。

PHP 特有场景: 不要让数据直接进入以下危险函数而不经过过滤:

  • include $user_input(本地文件包含)
  • eval($user_input) / preg_replace/e 修饰符 / assert($user_input)
  • unserialize($user_input)(对象注入)

第二步:应用 STRIDE 模型分析威胁

针对每个数据流,使用以下六类威胁进行头脑风暴:

威胁类别 PHP 典型攻击实例 涉及的关键函数/特性
Spoofing(伪装) 会话固定会话劫持CSRF session_id()$_COOKIE、缺少 CSRF Token
Tampering(篡改) SQL 注入XSS文件上传绕过 字符串拼接 SQL、htmlspecialchars() 使用不当、MIME 类型校验缺失
Repudiation(否认) 缺少审计日志,或日志记录敏感信息(如原密码) error_log()file_put_contents()
Information Disclosure(信息泄露) 目录遍历路径泄露异常堆栈暴露 file_get_contents($path)ini_set('display_errors', '1')(生产环境)
Denial of Service(拒绝服务) 正则表达式灾难(ReDoS)、大文件上传无限制的循环/递归 preg_match() 嵌套量词、move_uploaded_file() 未限制大小
Elevation of Privilege(提权) 反序列化漏洞(POP链)、弱口令未授权访问后台 unserialize()__destruct()__wakeup() 魔术方法

第三步:针对 PHP 特有弱点的专项威胁分析

PHP 不像 Java 那么强类型,很多安全问题源于语言特性,威胁建模时必须加入以下专项检查:

魔术方法与反序列化(最危险)

  • 威胁: 用户控制 $_COOKIE$_POST 传入 unserialize(),攻击者构造恶意对象,利用 __destruct()__wakeup() 执行任意代码。
  • 缓解措施:
    • 永远不要反序列化用户输入。
    • 若必须,使用 allowed_classes 参数限制类白名单。
    • 考虑使用 JSON 替代 PHP 序列化。

类型松散比较( 与 )

  • 威胁: 0e 开头的字符串(如 "0e123")与 0 比较时结果为 true,这常用于绕过密码校验(MD5 哈希以 0e 开头)。
  • 缓解措施: PHP 8.0+ 已修复字符串与数字比较的弱点,但所有身份验证逻辑必须使用 (严格比较)。

文件包含与路径解析

  • 威胁: 远程文件包含(RFI)和本地文件包含(LFI)。include 变量未过滤,读取 /etc/passwd 或执行远程脚本。
  • 缓解措施: 使用 realpath() 解析路径,并严格校验白名单(switch($page) { case 'home': case 'about': } 而非 include $page)。

extract() / parse_str() 变量覆盖

  • 威胁: 未加第二个参数的 extract($_GET) 会覆盖 $is_admin 变量。
  • 缓解措施: 如果必须使用,使用前缀(extract($arr, EXTR_PREFIX_ALL, 'GET')),或者干脆不使用。

第四步:落地缓解措施(以威胁为驱动)

根据威胁清单,为每个高风险威胁制定具体的防御策略,并落实到代码中:

风险等级 威胁描述 PHP 具体防御策略
严重 SQL 注入 强制使用 PDO 预处理语句(参数化查询),禁用字符串拼接。
严重 反序列化 RCE 封禁 unserialize(),若必须使用,使用 allowed_classes 并校验 HMAC 签名。
XSS 存储型/反射型 输出时统一使用 htmlspecialchars($var, ENT_QUOTES, 'UTF-8');前端配合 CSP 头(Content-Security-Policy)。
文件上传 Webshell 使用 finfo_file() 检测 MIME 类型,不让用户控制文件名(重命名),文件存储目录禁止执行 PHP(Nginx 配置 location ~ \.php$ { deny all; })。
中等 CSRF 使用 hash_equals() 定时比较 Token(防时序攻击),配合 SameSite Cookie 属性。
中等 信息泄露 生产环境设置 display_errors=Off,日志写入 error_log 而非浏览器。

实战案例:一个简单的 PHP 登录系统威胁建模

数据流: 用户提交 POST → login.php → 验证 Session → 数据库查询 → 返回 JSON。

威胁 攻击点 缓解措施(代码级)
伪装 攻击者篡改 Cookie 中的 Session ID 设置 session_regenerate_id(true)(登录成功后),并设置 Secure; HttpOnly; SameSite=Lax
篡改 在用户名输入 ' OR 1=1 -- 使用 PDO::prepare()
信息泄露 数据库连接错误直接输出 try/catch 中只输出 “系统错误”,详细日志写入 $logger
提权 直接访问 admin.php 绕过登录 在控制器最顶部加中间件或 if ($_SESSION['role'] !== 'admin') { exit; }
拒绝服务 登录接口无频率限制,被爆破 引入 rate-limiter,且密码哈希使用 password_hash()password_verify()(不可逆)。

推荐的威胁建模工具与工作流

  1. 自动化扫描(结合建模):

    • 静态分析: 使用 PHPStan(Level Max)+ Psalm 检查类型问题,使用 PHP-CS-Fixer 检查敏感函数。
    • 依赖检查: 使用 Composer 的 composer audit 检查已知 CVE(漏洞库)。
  2. 动态验证(针对建模痛点):

    使用 OWASP ZAP 或 Burp Suite 测试 SQL 注入/XSS 是否被堵住。

  3. 团队协作文档:

    • 使用 OWASP Threat Dragon(免费开源)绘制 DF D图并标记 STRIDE 威胁。
    • 在代码仓库的 SECURITY.md 中明确“不允许使用的函数”清单(如 evalunserializeextract)。

PHP 威胁建模的“三步走”

  1. 画图: 找到所有 超全局数组的出入口。
  2. 套模型: 用 STRIDE 对照,特别关注 PHP 的“魔法特性”(反序列化、松散比较、文件包含)。
  3. 设防御: 核心逻辑里禁止拼接 SQL禁止 Unserialize 用户数据输出必须转义

威胁建模不是一次性的,而是在功能迭代时每次都过一遍的思维习惯,对 PHP 而言,“永远不信任 ” 就是最好的威胁建模基础。

抱歉,评论功能暂时关闭!