本文目录导读:

- 第一步:绘制数据流图
- 第二步:应用 STRIDE 模型分析威胁
- 第三步:针对 PHP 特有弱点的专项威胁分析
- 第四步:落地缓解措施(以威胁为驱动)
- 实战案例:一个简单的 PHP 登录系统威胁建模
- 推荐的威胁建模工具与工作流
- 总结:PHP 威胁建模的“三步走”
在 PHP 开发中进行威胁建模,通常不是指用某种特定的工具扫描代码,而是指在系统设计阶段,系统性地识别、分类并缓解潜在的安全风险。
针对 PHP 项目,威胁建模的核心思路通常遵循 STRIDE 模型,并结合 PHP 特有的“坑”(如类型松散、超全局变量滥用、反序列化等)。
以下是针对 PHP 项目的系统性威胁建模指南,分为四个步骤:
第一步:绘制数据流图
这是最重要的一步,你需要明确:
- 数据入口: 用户输入(
$_GET、$_POST、$_COOKIE、$_FILES)、API 请求、Webhook、队列消息、第三方服务回调。 - 数据出口: SQL 查询、文件写入、日志记录、API 响应、邮件发送、命令行执行(
exec)。 - 信任边界: 浏览器与服务器之间、服务器与数据库之间、服务器与文件系统之间、不同微服务之间。
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()(不可逆)。 |
推荐的威胁建模工具与工作流
-
自动化扫描(结合建模):
- 静态分析: 使用 PHPStan(Level Max)+ Psalm 检查类型问题,使用 PHP-CS-Fixer 检查敏感函数。
- 依赖检查: 使用 Composer 的
composer audit检查已知 CVE(漏洞库)。
-
动态验证(针对建模痛点):
使用 OWASP ZAP 或 Burp Suite 测试 SQL 注入/XSS 是否被堵住。
-
团队协作文档:
- 使用 OWASP Threat Dragon(免费开源)绘制 DF D图并标记 STRIDE 威胁。
- 在代码仓库的
SECURITY.md中明确“不允许使用的函数”清单(如eval、unserialize、extract)。
PHP 威胁建模的“三步走”
- 画图: 找到所有 超全局数组的出入口。
- 套模型: 用 STRIDE 对照,特别关注 PHP 的“魔法特性”(反序列化、松散比较、文件包含)。
- 设防御: 核心逻辑里禁止拼接 SQL、禁止 Unserialize 用户数据、输出必须转义。
威胁建模不是一次性的,而是在功能迭代时每次都过一遍的思维习惯,对 PHP 而言,“永远不信任 ” 就是最好的威胁建模基础。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播