很久以前,Jerry Saltzer和Michael Schroeder发表了一篇论文,题为“计算机系统中的信息保护”,该论文的第三部分提供了信息安全的一些基本设计原则。人们都说,他们给安全界带来启发式的影响,其实不仅如此,在近40年后的今天,他们早在1975年提出的原则仍然实用。
在新年开始之际,笔者建议你在设计新系统时采用这13个原则。虽然13并不认为是吉利的数字,但笔者相信,当你将这些原则在企业中付诸实践时,将会给你带来好运气。
13条安全设计原则
1)保护最薄弱环节–-Spaf(即备受推崇的普渡大学安全专家Gene Spafford)通过一个有趣的故事来说明这个原则。试想一下,你需要负责把睡在公园长椅上的无家可归的人(我们称他为Linux)的财产运送给另一个无家可归的女人(我们称她为Android),你租用了一辆装甲卡车来运送,运输公司的名称是“Applied Crypto, Inc.”。现在,假设你是准备窃取财产的攻击者,你是会攻击Applied Crypto卡车、无家可归的人Linux还是无家可归的女人Android?很容易做出选择吧?(提示:答案是,“除了卡车以外”)
笔者及其合著者John Viega在2001年撰写的《构建安全软件》一书中写道,“安全从业者经常指出,安全就像一根链条,链条的强弱取决于其最薄弱的环节,同样的道理,软件安全系统的安全性也取决于其最薄弱的组件。”攻击者往往会寻找系统中最薄弱的地方,而最薄弱的地方很少会是某个安全功能或特性。当涉及到安全设计时,一定要考虑你的系统中最薄弱的环节,确保它是足够安全的。
2)深度防御–笔者和Kenneth van Wyk喜欢将这个称为“腰带和吊袜带”的方法。在安全领域,冗余和分层通常是好事。不要指望你的防火墙来阻止所有恶意流量;同时还应该使用入侵检测系统。如果你正在设计一个应用,通过安全冗余和防御层来防止单点故障。《构建安全软件》中提到:“深度防御背后的概念是管理不同防御策略的风险,这样的话,即使某个防御层无法提供足够的安全性,另一个防御层将有可能防止数据泄露。”这是信息安全专家普遍认同的概念,理由很简单:它有用。
3)保证失效后的安全性—请确保你设计的系统不会在失效后保持“开放”。关于这个原则,笔者最喜欢的故事是命运多舛的Microsoft Bob产品(Bob是Clippy回形针的前身),据传说,如果你三次尝试输入用户名和密码失败后,Bob将会询问你是否要选择使用一个新密码,感谢Bob(攻击者说)!很显然,在这种情况下,更好的默认设置应该是拒绝访问。
《构建安全软件》中提到:“任何足够复杂的系统都会失效,失效是不可避免的,企业应该提前做好准备。可以避免的是与失效相关的安全问题。但问题是,当很多系统以任何方式失效时,它们都会表现出不安全行为。”
4)最小特权—当你需要为用户或进程授予权限来完成一些操作,尽可能授予最小的权限。想想你的Outlook联系人列表,如果你需要别人访问你的联系人列表来查看一些数据,授予他们读者权限,但不要授予编辑权限。这有一个更专业的例子:系统的大多数用户的日常工作并不需要根级权限,所以不要授予他们根级权限。底线是,避免无意的、不必要的或不正确的权限使用,以“吝啬”的方式来授予权限。
5)独立权限—笔者曾经看到一个系统将其认证前端划分成大量角色,这些角色对系统有不同程度的访问。问题是,当任何角色的用户需要执行后端数据库操作时,该软件会临时授予每个用户管理员权限。这样做并不好,即使是最底层的实习生也可以侵入数据库。要知道,如果攻击者可以骗取一个权限,而无法得到第二个权限时,他将无法成功发起攻击。所以保持权限的分离。
6)经济机制—复杂性是安全工程的敌人,却是攻击者的朋友。无论是从设计的角度来看,还是从部署的角度来看,在复杂的系统中,很容易将事情“搞砸”。具有讽刺意味的是:想看看复杂的东西吗?只要看一看现代企业软件的任何一部分。
尽可能保持事物简单。《构建安全软件》中提到,“KISS的口头禅众所周知:‘保持简单,保持愚蠢!(Keep It Simple, Stupid!)’这个说法同样适用于安全领域及其他任何领域。复杂性增加了问题的风险,避免复杂性,就是避免问题。”
7)不要共享机制—你是否应该将面向内部的业务应用放在公共云中?根据这条原则,最好不要。你可以将你的身份验证系统限制为你信任的员工,为什么让你的系统处理随机互联网流量呢?
还有一个专业的例子:如果你有多个用户使用相同的组件,让你的系统为每个用户创建不同的实例。不共享用户之间的对象和访问机制,可以减少安全故障的可能。
8)不要轻易信任—假设你的系统运行的环境处于不利条件,不要让所有人都能调用你的API,当然也不要让所有人能够访问你的机密信息。如果你依赖于云组件,你需要对其进行检查,以确保它没有被欺骗或者受到感染。预防命令注入、跨站脚本等攻击。在《构建安全软件》中,“最后一点要记住的是,信任是可传递的,当你给出信任时,你往往会将这种信任扩展到你信任的实体所信任的对象上。”
9)假设你的机密信息并不安全—安全不能“含糊其辞”,特别是当涉及存储在你的代码中的秘密信息时。假设攻击者能够找出关于你的系统尽可能多的信息,甚至可能超过超级用户。攻击者的工具包有反编译器、反汇编器以及很多分析工具。假设他们瞄准了你的系统,他们怎么查看二进制码中的加密密钥?函数扫描会让加密密钥呼之欲出,毕竟二进制只是一种语言。
10)彻底检查--企业应该对每次访问和每个对象进行检查。请确保你的访问控制系统是全面的,适应当今这个多线程世界的。不管你做什么,如果更改系统权限,请确保对访问进行了系统化的重复检查。不要缓存授权或使用权的结果。在充满大规模分布式系统和多处理器计算机的世界,这条原则非常重要。
11)使安全可用—如果你的安全机制太繁琐,你的用户会想尽办法规避或避免它们。请确保你的安全系统足够安全,但也不要“过头”。如果你深深地影响了可用性,没有人会使用你的东西,不管它多么安全。虽然它非常安全,但同时也非常没用。Spaf经常会笑话据称是世界上最安全的系统,即系统硬盘消磁,被埋在填满混泥土的30英尺的围绕法拉第电网的洞里。这样的系统肯定很难使用。
12)保护隐私--大家都在谈论保护隐私,但大多数人实际上没有做任何相关事情。你可以帮助解决这个问题。当你设计一个系统时,考虑一下最终用户的隐私。你收集个人识别信息(PII)只是因为市场部有人要求这样做吗?这样做好吗?你是将PII存储在可能受到破坏的地方吗?难道不应该对这些信息进行加密吗?信息安全从业人员并不需要提供对这些隐私问题的答案(这是首席信息官的工作),但如果没有其他人提出这类问题,你需要提出。
13)使用你的资源—正如笔者14岁时在童军领导培养课程中学到的那样,“使用你的资源”这条原则具有令人难以置信的广泛应用范围。如果你不确定你的系统设计是否安全,请寻求帮助。架构风险分析很难,但有些人已经做了几十年。如果你做不到的话,最好不要尝试单独操作。不要羞于寻求帮助,这件事情非常复杂。
借用别人的好点子
笔者永远都不会忘记在硅谷的HSARPA会议演示软件安全幻灯片的那天。这个幻灯片是基于笔者的《构建安全软件》一书中的内容,该书有一章是围绕这些安全原则。其中一张幻灯片是Saltzer和Schroeder的图谱,你猜谁正好坐在观众席中?正是Michael Schroeder本人,他赞扬了这个幻灯片,这个世界确实很小。Saltzer和Schroeder在1975年是正确的,当我们在撰写《构建安全软件》的今天仍然是正确的。将他们的原则应用到2013年的安全工作中,不要害怕使用别人想出的好想法。