本节书摘来自华章计算机《威胁建模:设计和交付更安全的软件》一书中的第1章,第1.1节,作者:[美] 亚当·斯塔克 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
第1章 潜心开始威胁建模
谁都可以学习威胁建模,更进一步说,每个人都应该学习威胁建模。威胁建模是利用模型来发现安全问题,这意味着通过提取大量细节对安全问题进行全面检查,而不是代码本身。之所以要构建模型,是因为模型能让你在没构建系统之前即可发现问题,以及在问题出现前提早发现问题。最后,威胁模型可以预见可能侵袭你的威胁。
首先,威胁建模是一门实用科学,本章系统地描述其实用性。尽管本书为你提供了很多有价值的定义、理论、观点、有效的方法和技术,但你还是希望能将这些用于实践。因此,本章内容主要从实践经验展开,未涉及大量的理论。
举一个例子,当你开始操作一个乐器,就要通过弹奏乐器培养能力和感觉。起初,可能听上去没那么好,有时还会令人沮丧,但是在练习的过程中,你会逐渐发现越来越轻松。慢慢地开始娴熟。同样,如果你按照书中第一部分到第三部分提出的如何威胁建模的简单四步法练习,你也会练就威胁建模能力。你可能听说过一个老段子:纽约街头音乐人被一个人拦住,问:“我怎么才能进入卡内基音乐厅表演?”回答当然是“练习、练习、再练习”。这过程中包括遵从、练习、培养对各个步骤的理解。长此以往,你就能理解威胁建模涉及的各种任务和技术是如何结合在一起的。
在本章中,你将找到设计中可能存在的安全缺陷,进而解决它们。你将学习如何通过针对带有后端数据库的简单的网络应用查找缺陷。你将了解哪里有可能会出错,如何解决,以及如何检查。在本章中,你将学会如何玩权限提升游戏,旨在帮助你开始威胁建模。最后,你将有机会实际动手构建自己的威胁模型,本章结尾将为你提供一组检查列表帮助你开始进行威胁建模。
1.1 学习威胁建模
威胁建模重点是解决如下4个问题:
1.你正在构建什么?
2.哪些地方可能会出错?
3.发现错误时应该怎么解决?
4.是否做了完整的分析?
解决这些问题的开始和结束是所有技术人员所熟悉的:在白板上画图、管理漏洞。在这里,本书将介绍多种可以用于思考威胁的新技术。当你在解决问题的过程中遇到困难时,就回过头想想这4个问题。
本章内容旨在帮你解答这些问题。首先,以三层架构网络应用程序为例解答这些问题。之后,你该回顾一下这些步骤,尝试对自有的软件进行威胁建模,可以是你正在构建或部署的软件或者是你正考虑获取的软件。如果你不确定要对什么进行建模,可以使用本章中的一个样本系统或是在附录E中选择。
第二次读本章的时候,你需要有一副权限提升威胁建模游戏纸牌。需要2~4个朋友或同事与你一起玩这个游戏。
首先从构建示意图开始,这是威胁建模涉及的4个主要动作之一,在下一部分内容会涉及。其他3个动作分别是寻找威胁、解决威胁和检查工作。
1.1.1 你正在构建什么
用示意图来回答这个问题是一种好方法。为软件做示意图也有很多种方法,可以先从在白板上画开始,画一画数据流是如何在系统中流动的。在这个例子中,处理对象是一个简单的网络应用程序,包含网络浏览器、Web服务器、业务逻辑和一个数据库(见图1-1)。
图1-1 示意图
在这里,一些人会开始思考有什么问题。例如,你怎么知道网络浏览器由你所预期的人使用?如果有人修改数据库里的数据会怎样?从一个方框移动到另一个方框时不需要信息加密吗?你可能愿意花时间想一想这里可能出错的细节,因为这些问题会引领你问:“这是经过允许的吗?”如果你能多考虑一些“谁控制什么”,你就能构建出比现有更好的模型。这是针对整个互联网还是针对内部网络?数据库是在线上站点还是在网络提供者?
对于这个例子,首先假定你正在创建一个互联网站点,用的是虚拟Acme存储系统(在这里我用了具体的产品,但是我会弄错一些细节,某些人——当然不是你,会纠缠于这些,就不会关注威胁建模内容了,我们此后就称为Acme,假设按照我说的方式进行工作,多谢,你们懂的)。
用添加边界的方式表达谁控制着什么是改进示意图的简便方法。你可以很容易发现跨越那些边界的威胁可能是非常重要的,可能是识别威胁的最佳位置。这些边界称为信任边界,无论在什么地方由不同的人控制不同的事,你就该画上边界。以下列出一些不错的示例:
- 账户(UNIX系统的用户名UID,Windows系统的安全识别符SIDS)
- 网络接口
- 不同的物理计算机
- 虚拟计算机
- 组织机构边界
- 你可以拥有不同权限的几乎所有地方
- 信任边界与攻击面
你可能会遇到的相近概念是攻击面。例如,船的外壳是经受鱼雷打击的攻击面。受到攻击时,船的侧面会比这艘船的船头攻击面要大。这只船会有内部“信任”界面,比如隔水舱、船长的保险箱。暴露很多接口的系统呈现的攻击面大于暴露很少API或其他接口的系统的攻击面。网络防火墙是有用的边界,因为它们可以减少外部攻击者的攻击面。然而,就像船长的保险箱,在防火墙以内还有信任边界。信任边界和攻击面是对同一事物的非常相似的概念。攻击面是一个信任界面,是攻击者可以发动袭击的方向。很多人认为这两者可互换。本书主要使用“信任边界”。
在你的示意图中,用边框来画信任边界(见表1-2),用标签(比如企业数据中心)放在边框处显示每个信任边界里有些什么。
https://yqfile.alicdn.com/e360600a525f8ed8f5b0ddb7573f69c3a77ada9d.png
" >
图1-2 在示意图基础上加入信任边界
随着示意图中的内容越来越多,越来越复杂,就会越容易错过某一部分,或者对数据流中的标签感到困惑。因此,给每个程序、数据流、数据存储标上序号会更有帮助,如图1-3。(因为每个信任边界有个与众不同的名字,所以这些就没必要标序号了。)
https://yqfile.alicdn.com/5cd4826bf1d86e711039412a8f8f5e6e98277055.png
" >
图1-3 在示意图基础上加入序号和信任边界
至于示意图的形式,你可以选择适合你的程序的:可以是白板示意图和手机照片,可以是Visio、OmniGraffle或其他绘图程序。你应该想到威胁建模示意图是开发流程的一部分,因此需要将它们和其他一起保存在代码控制中。
有了示意图,你很自然会问,这是正确的吗?到目前为止,有个简单的答案:我们假设它是正确的。本章后面会提供一些小窍门和检查表,还有一部分内容关于更新示意图,不过,在这一阶段,你已经有了足够好的图表来开始识别威胁,这就是你买这本书的价值所在。所以我们开始出发吧。
1.1.2 哪些地方可能会出错
有了示意图,你就可以开始寻找可能出错的地方。这很有趣,所以我将这转化到一个名为权限提升的游戏上。附录D中有更多有关游戏的内容,那里分析了每一张牌,第11章包含了该游戏的历史及设计理念。不过,现在通过一些简单的指示你就可以开始玩了。
一些人不适应在工作的时候玩游戏,还有一些人开始玩新游戏的时候可能会带着恐惧心理,尤其是看到很长、很复杂的游戏说明的时候。不过,权限提升游戏说明不多,可以试试。
如何玩权限提升游戏
权限提升游戏旨在帮助你威胁建模。图1-4中显示一张纸牌,跟玩普通纸牌一样,纸牌的左上角会有数字,纸牌上半部还有威胁实例的文字介绍。只要根据提示玩即可。
1.洗牌(可选)。
2.首轮拿到3篡改牌的人先出(在这样的纸牌游戏中,一轮也可以称为“一把”或“一手”)。
3.每一轮这样玩:
A.从先出牌的人开始沿着顺时针方向出牌,每人出一张牌。
B.出牌时,说出是什么牌,并尝试决定它能否影响你们正在制作示意图的系统。如果能联系起来,写下来,得一分,然后下一个人继续。
C.每个人都出了一张牌后,牌最大的人赢得本轮,本轮赢者在下轮先出。
4.所有牌都出完,游戏结束,得到分数最高的人赢得整个游戏。
5.如果你们是在对正在构建的系统进行威胁建模,那么把你们发现的任何漏洞都归档。
https://yqfile.alicdn.com/8cdd8723b1cbf91025e37333f70e9c619ac24e01.png" >
有的人甚至占用睡眠时间学习这个内容,十分着迷。但不是所有人都这样,没关系。威胁建模不是非常复杂的科学,从事软件开发的人都能够学会。只不过不是所有人都愿意用睡眠时间
学习。
对很多人来说,识别威胁听起来可能有点吓人,如果你是这样的,不要担心。本部分内容就是帮你慢慢了解威胁识别,记得享受其中的乐趣。一位评论家说:“玩权限提升游戏应该是很有趣的,不要贬低它,我们每周五都玩,很有趣,也很放松,同时还有商业价值。”
游戏之外,你可以通过思考可能出错的地方进一步威胁建模。比如,你怎么知道网络浏览器被你所预期的人使用?如果有人修改数据库里的数据会怎样信息从一个方框移动到另一个时不用加密?你不必盯着表、托着下巴苦思这些问题,(我反正没有!)你可以用简单的有助于记忆的STRIDE来识别威胁,这在下一部分会具体介绍。
使用便于记忆的STRIDE方法寻找威胁
STRIDE是个助记符,可以帮助查找不安全的地方。它是几个词或词组的首字母缩写,代表假冒(Spoofing)、篡改(Tampering)、否认(Repudiation)、信息暴露(Information Disclosure)、拒绝服务(Denial of Service)、权限提升(Elevation of Privilege)。
假冒:假装成并非自己真实身份的人或物。
篡改:修改你不应该修改的东西。包括有线网络(或者无线网络)的数据包、磁盘上的信息或者内存中的信息。
否认:宣称自己没做什么事(不管你是否做了还是没做)。
拒绝服务:旨在阻止系统提供正常服务的攻击,包括使系统崩溃、让它变得运行缓慢而且无法使用,或者占满内存。
信息暴露:将信息暴露给没有授权查看这些内容的人。
权限提升:指一个程序或者用户在技术上可以做其本来不能做的事情。
回忆一下之前提到的三种威胁范例:
- 你怎么知道网络浏览器被你所预期的人使用了?
- 如果有人修改数据库里的数据会怎样?
- 信息从一个方框移动到另一个时不用加密?
这些都是假冒、篡改和信息暴露的例子。使用STRIDE可帮助你检查图表,选出威胁范例。再加上一些安全知识和适当的技术手段,你就能更快、更可靠地找到重要的威胁。如果你在开发软件时保证了威胁模型开发和威胁记录,将大大提升软件的安全性。
既然有了STRIDE工具,再查看一下你的图表,寻找更多威胁,这次运用这个助记符。列出遇到的威胁及图表中其会影响到的因素(总体来说,软件、数据流或是存储会受影响,而非信任边界)。以下显示每一类威胁的例子。
假冒:有人会假装成其他用户,因此你需要有验证用户身份的方式;有人还会假装成你的网站,所以你必须使用加密套接字协议层(SSL)证书,而且保证所有页面使用单一的域名(帮助部分用户通过URL网址来确认自己是不是访问了正确的网站地址)。还有人可能在你的网站放置深层的链接,比如logout.html或placeorder.aspx。在采取相应措施前要检查Referrer引用字段。这并不是应对跨站请求伪造(Cross Site Request Forgery,CSRF)攻击的全部解决办法,只不过是一个开始。
篡改:有人可能会篡改Acme后端的数据。有人可能会对数据中心之间的数据流数据进行篡改。程序员可能会未经测试即替换网络前端的执行代码,将它们上传到暂存区域。一个愤怒的程序员可能添加优惠码“PayBobMore”,将所有商品以八折优惠出售。
否认:之前的那些操作到底操作了什么内容。有系统审计记录吗?正确的信息被有效地记录了吗?这些记录能防止篡改吗?
信息暴露:如果Acme读取你的数据库会发生什么?任何人都能连接到数据库、读取或者写信息吗?
拒绝服务:如果1000个客户同时点击一个网站会怎样?Acme出故障了会怎样?
权限提升:可能网络前端是用户唯一应该访问的地方,是什么在强制执行呢?是什么阻止他们与业务逻辑服务器直接连接或者上传新代码?如果有防火墙,它是否配置正确?是什么控制着访问你的Acme的数据库,或者如果有Acme员工犯了错误,甚至想编辑你的文件呢?
以上提到的可能情况不是每个威胁入侵表现的完整列表。第3章中会介绍更多内容。不过,本节内容足以让你入门,基于图1-2所示的简单图表,主要关注你可能需要研究的内容。还记得前文提到的弹奏乐器的类比吧。如果你刚学弹钢琴的时候就学习拉威尔的《夜之加帕斯》(被认为是最难的钢琴曲之一),那你可就要抓狂了。
识别威胁窍门
不论你是用权限提升游戏还是STRIDE,抑或是两者皆用来识别威胁,下面这些都要牢记在心,它们可以帮助你走对路,找出哪里出错了。
从外部实体开始:如果你不知道从哪里开始入手,那么就从外部实体或是驱动活动的事件开始。当然,也有很多其他的有效途径:你可能从网络浏览器开始寻找假冒,以及篡改等。也可能从业务逻辑开始,可能该组件的主要开发人员也同在一个房间内。不管你选择从哪里开始,以及满足一定级别的组织机构。你也可以按照图表中的“STRIDE次序”(“STRIDE order”)进行。如果没有一定的组织机构,很难说你何时已经完成,不过,小心不要加入太多结构,否则会限制创造性。
不要因为不是你目前要找的威胁而忽略任何一个威胁。你可能在查看别的项目类别时发现一些威胁,记下来再返回解决。比如,你可能会在寻找假冒威胁的时候想着信息暴露威胁:“会有人连接到我们的数据库吗”,如果是这样就太棒了。非常不错。出现一些冗余可能是比较乏味,但是可以避免遗漏。如果你发现自己在考虑“没有授权的人连接数据库读取信息”是假冒还是信息暴露,答案是谁关心啊?记录下来,继续下一项。STRIDE是引导你发现威胁的工具,不是让你给你所发现的威胁进行分类;不管怎么说,这是令人厌烦的分类问题。(意思是说,有很多安全问题都可以争论到底属于哪类。用严格的分类标准去比较、对比,就像给生命分类,有没有脊椎?有的话,那就是脊椎动物。)
关注可能的威胁:在发现威胁过程中,你可能会遇到一些这样的威胁——某人可能在芯片厂植入了后门,或者有人可能雇用了我们的守卫人员插入了硬件按键记录器、窃取了你所有密码口令,这是真实存在的可能情况,但是相比使用漏洞攻击尚未安装补丁的漏洞,或者假冒使用人安装软件,上面情况是不太可能发生的。另外还有怎么解决威胁的问题,这会在下一部分中介绍。
1.1.3 解决每个威胁
现在,你应该有一个数量可观的威胁列表,或者有多个威胁列表。威胁建模的下一步就是仔细检查列表,解决每一个威胁。对于每个威胁,有四种应对措施:缓解、清除、转移、接受。下面的列表中对这几种方法做了大致介绍,接着在后续的“哪里会出错”部分,你可以学到如何解决STRIDE列表中每个特定的威胁。在第8章和第9章中,会有解决这些威胁的策略和技术的更多细节。
减缓威胁:采取措施让别人更难利用这个威胁。控制登入的时候需要提供密码可以减缓假冒威胁。添加复杂的或者有时间限制的密码控制,可以减小密码被猜到或者被盗后可用的概率。
清除威胁:通常可以通过清除功能来实现。如果有个威胁,某人可能通过访问/admin/URL来访问网站的管理功能,你可以通过设密码或者其他身份认证技术来缓解,但是,这个威胁仍然存在。你可以利用/j8e8vg21euwq/这样的URL,使其增加被访问的难度,但是威胁依然存在。为了清除威胁,可以通过移除界面接口,仅通过命令行进行管理操作(不同的命令行登录方式也会存在威胁,远离HTTP使得威胁更易通过控制攻击面来减缓。两种威胁都可在完整的威胁模型中发现)。
转移威胁:让别人或者别的东西来处理威胁。比如,你可以将认证威胁转移到操作系统或者从信任边界转移到防火墙。你也可以将威胁转移到客户,比如,可以通过要求他们点击很多难懂的对话框,之后才可以做他们想做的。这当然不是个很好的解决办法,但是有时人们知道能促成安全权衡。比如,他们可能知道他们只是连上了咖啡馆的无线网络。如果你认为这个人有安全意识,你应该帮助她做决定。第15章会介绍更多内容。
接受威胁是解决威胁的最后选择。对大多数组织来说,在大多数时间内不值得用搜查进出大楼的每个员工来牺牲他们的尊严和工作满意度。(然而,钻矿和一些政府机构会选择不同的方法。)同样,阻止某人在主板插入后门的代价是很高的,因此在这些时候,你可能会选择接受威胁。而且,一旦你接受了,就不该再为之担心。有时,担心就表示你没有完全接受威胁,或者说接受威胁是不合适的。
表1-1列出的策略举例说明了解决威胁的方法。你的首选方法应该是缓解威胁。总体来说,缓解是最容易的,也是对客户来说最好的选择。(可能看上去接受威胁更容易,但久而久之你会发现缓解是更容易的。)缓解威胁是份辛苦活,不要认为这些例子就是全部。解决每个威胁经常会有其他有效方法,有时在选择解决威胁的方法上要做出权衡。
解决假冒威胁
表1-1展示了假冒的目标、解决假冒的减缓策略以及如何实施这些缓解方法。
当你担心可能会有人被假冒时,保证每个人都有独特的用户名和验证方法,传统方法就是设置密码,虽然这种方式存在各种问题,但其很多优点也难以复制。密码相关内容详见第14章。
当访问磁盘文件时,不要用open(file),而应该使用open(/path/to/file)。如果文件敏感,打开后,检查文件说明符中的安全因素(例如完全解析的名字、授权和所有者)。为了避免竞争,要检查文件说明符。如果文件是可执行文件则执行两次(applies doubly),虽然打开后检查可能会比较棘手,这可能帮助确保可执行权限不会被攻击者修改。无论如何,你几乎从来不会想要求执行如下命令:exec./file。
当你担心联网时系统或者计算机会被假冒,你会想用DNSSEC、HTTPS/SSL、IPSec或是组合使用上述协议来保证你连接了安全正确的地方。
解决篡改威胁
表1-2展示篡改的目标、解决篡改的缓解策略以及如何实施这些缓解方法。
篡改文件:如果攻击者在同一台机器有账户或者在网络上通过服务器请求文件时篡改文件很容易。
篡改内存:当一个程序没有你的特权高或者未获信任时却可以修改内存,这是令人担心的。例如,如果你从共享内存段获取数据,是否添加了ACL允许另一个进程可以查看?对于一个网络应用程序,通过AJAX(Asynchronous JavaScript and XML的缩写)获取数据,在你拉入(pull)正确的数据量后,确保你获取到的数据是你所想要的。
篡改网络数据:防止篡改网络数据需要应付假冒和篡改。否则,想要篡改的人就可以简单地假装是另一端,即所谓的使用中间人攻击。对此最常见的解决方法是SSL,IPsec也逐渐成为另外一种解决方式。SSL和IPsec两个都能解决机密性和篡改,也可以帮助解决假冒。
篡改网络反模式:人们希望可以隔离网络,从某种意义上讲,这是很正常的,因此不必担心篡改威胁。但是长此以往也很难保持隔离,隔离的效果没有你想象的好。比如,隔离的美国机密互联协议路由网(SIPRNet)完全被恶意软件袭击了,而清理干净则花了14个月时间(Shachtman,2010)。
一个项目加载后不能检查自己是否真实可信,或许可以依赖“可信引导装载程序”(trusted bootloaders)提供一连串签名,但是安全策略不应包含在代码中。
解决否认威胁
解决否认威胁的主要办法是确保你的系统有记录,并确保这些记录得到保存和保护。可以通过简单的步骤来实现这点,比如利用可靠的协议传输日志数据。从这个意义上说,从安全的角度来看,使用UDP协议的syslog数据通常是愚蠢的做法,当前可以使用TCP/SSL的系统记录,而且该方式已得到极大改善。
表1-3展示否认的目标、解决否认的缓解策略以及如何实施这些缓解方法。
https://yqfile.alicdn.com/643a1969511fe1d9c6d32a40cc1d49ecbf2a3c06.png
" >
没有日志意味着你什么都不能证明:这个不言自明。例如,当一个客户来投诉说他们从来没接到订单,该怎么解决?保持做审计记录,这样当有人试图否认的时候就可以调查到底怎么回事了。
记录遭受攻击:攻击者会想方设法让你的审计记录变得毫无帮助,比如填满你的审计记录以致难寻攻击,或者强迫你的日志“转存”(roll over)。他们还会设法引发大量警报,这样就会淹没真正的攻击。显然,将日志发送到网络上会让它们暴露于其他威胁之中,这也是你需要解决的。
日志作为攻击的渠道:设计上,你从不可控的来源收集数据,然后将这数据发送到有安全权限的人和系统。这样的攻击样本可能会发送邮件给“