0x00 前言
在威胁建模之绘制数据流图这篇文章中,已经讲了我们如何通过绘制数据流图来构建系统的模型。有了模型以后,我们就要基于模型进行发现威胁的工作了。
威胁建模的核心是威胁。 发现威胁的方法也很多,每种威胁发现的方法都各有优缺点,我们可以根据不同场景选择不同的方法,或者可以结合使用。 常见的威胁发现方法有如下2种:
1、STRIDE方法。一种启发式的方法,结构化程度低,更过依赖于安全人员的经验。
2、攻击树。从攻击者的视角梳理系统可能受到的攻击路径。
我们在前期绘制的数据流图的内容一定会存在缺失的问题,这个是在所难免的,我们只需要在发现威胁的阶段完善数据流图就可以了。
0x01 STRIDE方法
STRIDE是如下六种威胁的首字母的组合:
Spooling(仿冒)、Tampering(篡改)、Repudiation(抵赖)、InformationDisclosure(信息泄露)、Dos(拒绝服务) 和 Elevation of privilege (权限提升)
威胁 | 安全属性 | 定义 | 举例 |
---|---|---|---|
仿冒(S) | 可靠性(认证) | 冒充别的人或物 | XSS、CSRF |
篡改(T) | 完整性 | 修改磁盘、数据库或内存中的数据,代码 | 越权修改其他用户信息 |
抵赖(R) | 不可否认性 | 不承认做过某行为 | 日志未记录用户行为 |
信息被泄露(I) | 机密性 | 为没有权限的人提供信息 | 越权查看其他用户信息 |
拒绝服务(D) | 可用性 | 消耗服务资源 | 任意文件删除 |
权限提升(E) | 授权 | 允许用户去做未经授权的事情 | 后台rce,从webshell提权至root shell |
STRIDE方法是用来启发威胁建模人员从不同的角度来思考发现威胁的,不是用于对威胁进行分类的,我们很容易找到一些使用STRIDE方法无法分类的威胁。如篡改用户认证数据库表后假冒该用户的场景,应该将它分为篡改威胁还是假冒威胁呢?答案很简单:我们的最终目的是寻找威胁,既然已经发现了该威胁,那记录该威胁就可以了,何必花费精力去给它分类呢?
下面将对每种威胁进行详细举例说明。
1.1 仿冒威胁
威胁示例 | 攻击行为 | 备注 |
---|---|---|
在同一台机器上假冒一个进程 | 伪造一个恶意进程来欺骗或攻击应用系统 | 对于企业要求员工要安装使用B软件时,必须先安装进行终端管控的A软件。当B软件未校验A软件的进程,或校验方式存在缺陷时,员工就可以伪造一个A软件的进程来欺骗B软件。 |
伪造一个mysql服务 | java的mysql-jdbc反序列化漏洞。 | |
仿冒一个主节点对从节点进行攻击 | 通过构造合法的传输协议等手段来仿冒一个主节点。 | |
伪造一个应用系统诱骗用户填入账户信息 | 然而,目前还没有什么手段能够阻止别人建立假冒的应用系统。 | |
假冒文件 | 创建符号链接文件 | 如CVE-2018-15664,通过符号链接+条件竞争进行docker容器逃逸。即在校验文件和访冋文件之间修改文件。 |
假冒一台机器 | ARP欺骗 | |
DNS欺骗 | 如通过假冒DNS服务器,利用DNS Rebinding手段返回一个合法ip从而绕过ssrf的防御。 |
1.2 篡改威胁
威胁示例 | 攻击行为 | 备注 |
---|---|---|
篡改前端/客户端的请求数据包 | 通过篡改请求数据包中的订单信息实现0元购 | 应用安全性不依赖于前端/客户端的校验。 |
篡改升级包/插件包 | 构造恶意升级包/插件包,在其中写入恶意可执行脚本或sql语句 | 当应用只是简单对升级包/插件包进行hash校验时,攻击者可随意进行篡改。需通过加密进行防御,且需保证秘钥随机。 |
篡改网络 | 篡改流经网络的数据 | 篡改WiFi 、蓝牙等设备的无线协议。 |
重定向数据流到攻击者机器 | ||
篡改数据存储 | 越权修改其他用户的数据 | |
注入漏洞进行攻击 |
1.3 否认威胁
威胁示例 | 攻击行为 | 备注 |
---|---|---|
否认一种行为 | 宣称没有点击 | |
宣称没有收到 | ||
宣称有人仿冒自己 | ||
攻击日志 | 没有记录日志 | |
攻击者利用漏洞篡改日志 | ||
攻击者拿下系统权限后,删除日志 | 未进行日志转储 |
1.4 信息泄露威胁
威胁示例 | 攻击行为 | 备注 |
---|---|---|
针对进程的信息泄露 | 从报错页面中提取保密信息 | |
根据服务的响应时间、响应码等信息来提取保密信息 | ||
未授权访问 | ||
针对数据存储的信息泄露 | 利用错误的或缺失的ACL | 如将数据存储服务暴露在公网 |
越权查看其他用户信息 | ||
利用注入漏洞进行攻击 | ||
利用错误的数据库权限配置 | ||
在磁盘文件或程序代码中寻找密码 | 硬编码密码 | |
利用数据库中的明文密码登录用户账户 | ||
针对数据流的信息泄霹 | 通过中间人攻击在网络上读取明文的敏感数据 |
1.5 拒绝服务威胁
威胁示例 | 攻击行为 | 备注 |
---|---|---|
针对进程的拒绝服务 | 消耗内存或磁盘 | |
消耗CPU | ||
针对数据存储的拒绝服务 | 填满数据存储 | |
产生足够多的请求,使得系统的运行变得非常慢 | ||
针对数据流的拒绝服务 | 消耗网络资源 |
1.6 权限提升威胁
威胁示例 | 攻击行为 | 备注 |
---|---|---|
未做权限校验而提升权限 | 未授权访问 | |
绕过权限校验而提升权限 | 利用路径归一化问题提升权限 | Java应用中,当使用request.getRequestURI()方法获取用户请求路径,进而对请求路径进行权限校验时,由于获取到的请求路径没有做归一化处理,因此存在权限绕过风险。如: /js/..;/admin/addUser 或 /admin/addUser;.js |
利用身份令牌处理不当问题提升权限 | 1、硬编码Token。 2、生成Token时的签名秘钥硬编码于代码或者可预测。 3、通过构造特定数据包未授权创建Token。 | |
免密登录逻辑缺陷 | 当系统需要给第三方系统提供认证接口,通常存在此类问题。 1、HTTP头绕过(如XFF等) 2、硬编码Token或未授权获取Token | |
session伪造 | 当应用系统对用户session对象处理不当时,则会出现session伪造风险。如: 权限校验逻辑如下: Object user = request.getSession().getAttribute("user"); if (user != null) { //认为用户已登录 此时其他接口存在如下代码: request.getSession().setAttribute(request.getParameter("key"), request.getParameter("value")); | |
其他提升权限 | 利用后台RCE漏洞将webshell提权至root shell | |
利用操作系统/中间件漏洞提升权限 |
1.8 小节
虽然上面的示例中,既有业务层面的威胁,也有主机层面的威胁,但其实威胁建模的一个重要的意义,是帮助我们发现更多比较贴合业务的威胁,也就是充分挖掘特定业务场景下会存在的威胁,而其他比较通用的威胁,如中间件的安全配置,端口开放情况等都可以放在安全基线中进行管理。
对所有应用系统来说,STRIDE方法都有助于寻找威胁。整理一套符合自己业务场景的更详细的威胁列表也是很有必要的,这既可以为经验较少的同学提供帮助,也可作为日常威胁建模的参考资料 。
0x02 攻击树
攻击树,将对系统的攻击放置到了树结构中进行展现,把要达成的目标表示成根结点 ,把要达成这一日标采用的各种方法表示成叶结点。攻击树不但可以替代STRIDE,作为另一种寻找威胁的方法,也因为他可以直观的体现出一个完整的攻击路径,所以也可以用来整理用其他方法发现的威胁。
1、攻击树有“ 与” (AND)树和“ 或” (OR)树两种基本的表示方法:
“ 与” 树是指一个结点的状态依靠其下面所有结点都为真;
“ 或” 树是指如果子结点中的任何一个为真,那么这个结点就为真。
当然两种树也可以结合使用。
2、如何确定根节点,一般有如下三种方法:
(1)确定要实现什么样的攻击目标,然后将该目标作为根节点,子节点则描述如何实现根节点的目标。如实现在应用系统进行任意代码执行的目标
(2)设定一个场景,识别在该场景下,为攻击者开放了哪些攻击向量。这些攻击向量将作为根节点。如在用户凭据被窃取的场景下,攻击者有哪些攻击路径。
(3)将某个有问题的组件作为根节点,然后在子节点上标记根节点可能存在的威胁。
2.1 案例分析
该案例来自CNCF对k8s的威胁建模:
https://github.com/cncf/financial-user-group/tree/main/projects/k8s-threat-model
1、下图确定的攻击目标是:在k8s的工作负载中执行恶意代码。
为了实现这个目标,可以通过获取pull镜像的账户来push恶意镜像(当然需要该账户有push镜像的权限)、利用特权容器等方式来进行,详情可阅读下图。
可以看到下图中用圆角梯形表示与的关系,三角形表示或的关系,我们在实际绘制攻击树时,也可以选择其他图形来表示与和或,如果能够统一标准当然最好了。
2、下图则设定了一个场景:攻击者已经利用容器中运行的应用程序的漏洞拿下了容器的权限。这时攻击者可以做哪些事情。如使用和上图相同的思路来投放恶意镜像,对数据存储进行勒索等。
2.2 小节
攻击树,从攻击者的角度出发的来构建出一条完整的攻击路径,这有助于我们全面思考应用系统面临的威胁;同时我们通过阅读别人创建的攻击树,也可能会学习到一些新的攻击手法。
0x03 总结
我们在实施威胁建模时,为了提升效率,维护一个威胁清单是很有必要的,该威胁清单需要分为两大部分:
第一大部分是基线部分,即多数应用都通用的部分;
第二大部分则是不同的业务场景特有的部分。我们在遇到新的业务场景时,需要使用STRIDE方法或攻击树方法,来发现识别威胁,然后再将这些威胁补充到威胁清单。