数据流图绘制:DFD 的要素、绘制方法与威胁建模应用

数据流图,简称 DFD,是威胁建模里最基础也最核心的工具。说白了,它就是一张“系统怎么动起来”的蓝图。我刚开始做安全设计时,总觉得画图浪费时间,直接上手写代码多痛快。结果呢?后来做威胁分析,发现漏了一堆边界和交互点,补起来比画十张图还累。

今天咱们就聊聊 DFD 的三个核心问题:它由什么组成?怎么画?画完怎么用在威胁建模里?

DFD 的四大要素

DFD 的符号其实不多,就四种。但每一种都对应着威胁建模里的关键角色。

要素 符号形状 威胁建模中的含义 我见过的坑
外部实体 矩形 数据来源或终点,通常是用户、第三方系统 有人把数据库也画成外部实体,其实它是数据存储
过程 圆形/圆角矩形 数据处理单元,比如认证模块、支付服务 过程太粗,一个圆里塞了十件事,分析时根本看不清
数据存储 开口矩形(两条横线) 数据停留的地方,数据库、文件、缓存 漏掉日志存储,结果日志泄露成了大漏洞
数据流 带箭头实线 数据在实体、过程、存储之间的移动 箭头方向画反,威胁分析全错位
我的习惯:画 DFD 时,我会在每根数据流旁边标注数据内容,比如“用户凭证”、“订单信息”。这样后面做威胁分析时,一眼就能看出敏感数据流经了哪些节点。

如何绘制 DFD:三步法

画 DFD 不是一蹴而就的。我一般分三步走,从粗到细,逐步展开。

第一步:画上下文图(Level 0)

上下文图是整个系统的“全景图”。只有一个过程节点,代表整个系统。外部实体和系统之间的数据流,就是系统的边界。

举个例子,一个简单的登录系统:

  • 外部实体:用户
  • 过程:登录系统
  • 数据流:用户发送“用户名+密码”,系统返回“登录结果”

这一步的关键是:明确信任边界。系统内部的东西,全藏在那个圆里。外部实体和系统之间的交互,就是威胁建模的起点。

我曾经踩过的坑:画上下文图时,把内部模块(比如数据库)也画成外部实体。结果信任边界完全乱了,威胁分析变成了“内部打架”。记住:上下文图里,系统内部只有一个圆。

第二步:分解为 Level 1 图

把上下文图里的那个圆拆开,露出里面的过程、数据存储和数据流。这一步要遵循一个原则:每个过程只做一件事。

还是登录系统的例子,Level 1 图可能包含:

  • 过程:用户输入验证、密码哈希比对、会话生成
  • 数据存储:用户凭证库、会话缓存
  • 数据流:验证请求、哈希结果、会话令牌

你想想看,如果我把“用户输入验证”和“密码哈希比对”画成一个过程,那后面做威胁分析时,就分不清是输入校验出了问题,还是哈希算法出了问题。拆得越细,分析越准。

第三步:按需继续分解(Level 2+)

对于复杂模块,可以继续分解到 Level 2 甚至 Level 3。但别贪多。我个人的经验是:分解到每个过程能对应一个代码模块或一个微服务为止。再往下画,就变成代码流程图了,那是开发的事。

核心原则:DFD 的粒度,以“能清晰识别威胁”为准。画得太粗,威胁漏掉;画得太细,分析成本太高。平衡点在哪里?我的判断标准是:如果两个过程之间的数据流涉及敏感数据或跨信任边界,就必须拆开。

DFD 在威胁建模中的应用

DFD 画完,不是用来挂墙上的。它是威胁建模的“作战地图”。

1. 识别信任边界

DFD 里的每个过程、数据存储、外部实体,都有其所属的信任域。数据流跨越信任边界的地方,就是威胁的高发区。

举个例子,用户浏览器(外部实体)到 Web 服务器(过程)之间,是互联网边界。这里需要 HTTPS、输入校验、防 CSRF。而 Web 服务器到数据库(数据存储)之间,是内部网络边界。这里需要 SQL 注入防护、最小权限。

2. 应用 STRIDE 模型

STRIDE 是微软提出的威胁分类模型,每个字母代表一种威胁类型。把 DFD 的每个元素和 STRIDE 对照,就能系统性地发现威胁。

DFD 元素 STRIDE 威胁 典型问题
外部实体 欺骗 (S) 身份伪造、重放攻击
过程 篡改 (T)、拒绝服务 (D) 代码注入、资源耗尽
数据存储 信息泄露 (I)、篡改 (T) 数据泄露、未授权修改
数据流 信息泄露 (I)、篡改 (T) 中间人攻击、数据窃听
我的做法:在 DFD 上直接标注 STRIDE 威胁。比如在数据流“用户凭证”旁边写个“I”,提醒自己这里可能泄露。这样一张图,既是架构图,又是威胁清单。

3. 生成威胁清单

把 DFD 上标注的威胁整理成清单,就是安全需求的输入。每个威胁对应一个或多个缓解措施。

比如:

  • 威胁:数据流“用户凭证”可能被窃听 → 缓解:使用 TLS 加密
  • 威胁:过程“密码哈希比对”可能被篡改 → 缓解:代码签名、运行时完整性校验
  • 威胁:数据存储“用户凭证库”可能泄露 → 缓解:加密存储、访问控制

你看,威胁清单不是凭空想出来的,而是从 DFD 上一步步推导出来的。这就是“数据流图驱动威胁建模”的核心思想。

一张图总结 DFD 与威胁建模的关系

下面这张 SVG 图,展示了 DFD 如何与威胁建模流程衔接。我习惯把它贴在团队的白板上,每次评审时都过一遍。

DFD 驱动威胁建模流程 绘制 DFD 识别信任边界 应用 STRIDE 生成威胁清单 导出安全需求 核心思想:DFD 是威胁建模的“骨架”,STRIDE 是“肌肉”,两者结合才能生成完整的安全需求 每张 DFD 图都应该经过 STRIDE 逐元素扫描,不漏掉任何一个威胁面

避坑指南:画 DFD 时常见的五个错误

这些年我评审过不少团队的 DFD,发现几个反复出现的问题。列出来,大家画图时对照一下。

  1. 过程太粗:一个圆里塞了“用户管理”、“订单处理”、“支付结算”。这种图没法做威胁分析。拆!
  2. 数据流没标注内容:光画箭头,不写传什么数据。后面分析时,根本不知道哪些是敏感数据。
  3. 漏掉数据存储:尤其是日志、缓存、临时文件这些“隐形”存储。我曾经见过一个系统,日志里存了明文密码,但 DFD 上根本没画日志存储。
  4. 信任边界画错:把内部网络和外部网络混在一起。记住:每一条跨越信任边界的数据流,都是威胁建模的重点。
  5. 只画 Level 0,不往下分解:上下文图只能看到系统边界,看不到内部威胁。至少分解到 Level 1。
我曾经遇到的一个真实案例:一个支付系统,DFD 上只画了“支付网关”一个过程。结果上线后,发现支付回调接口没有做签名校验,攻击者可以伪造回调。如果当时把“支付网关”拆成“发起支付”、“处理回调”、“更新订单状态”三个过程,这个威胁在 Level 1 图上就能被发现。所以,别偷懒,该拆就拆。

好了,DFD 的核心内容就这些。记住:DFD 不是画给领导看的,是画给自己做威胁分析用的。画得越认真,后面的安全需求就越扎实。