本书是针对软件专业人士编写的技术指南,适合那些希望更好地理解软件安全原则、学习如何实践软件安全设计和实施的专业人员阅读。我有幸对本书介绍的很多主题进行了自己的创新,此外,我也见证了这个领域大量技术的发展与落地。本书是根据我自己的从业经验创作的,其中包含了很多实用性很强的观点,读者可以把这些观点付诸实践,让自己正在编写的软件更加安全。
本书有两大核心主题:一是鼓励软件从业者在软件开发过程的早期就关注软件的安全性;二是让整个团队都参与到安全流程当中,并且对软件安全承担起自己的那一份职责。这两方面必然存在很大的改进空间,本书则展示了如何实现这些目标。
在我的职业生涯中,我有得天独厚的机会可以一直奋斗在软件领域的一线。如今,我希望与尽可能多的人分享我的学习成果。二十多年以前,我是微软公司某团队的成员,这个团队首次把威胁建模大规模应用于大型软件公司。后来我在谷歌公司参与了同一项基本实践的演化,同时也体验到了一种应对挑战的全新方式。本书第二部分参考了我所完成的百余项设计评审。过去的经历为我提供了一个极佳的视角来对这些要点重新进行解释。
设计、搭建和操作软件系统是一项存在固有风险的工作。我们的每一次选择、前进的每一步,都会在不经意间升高或者降低系统中引入安全漏洞的风险。本书涵盖了我最熟悉的内容,这些内容来源于我个人的经验。安全意识是我希望传达的首要原则,我也同时展示了如何把安全融入整个开发过程当中。在本书中,我提供了很多设计和代码示例,它们在很大程度上不会依赖某项特定的技术,这是为了让它们的应用尽可能广泛。本书包含大量的故事、类比和示例,这是为了增加阅读的趣味性,同时尽可能有效地表达抽象的概念。
安全意识对有些人来说很容易理解,对另一些人来说则比较难。鉴于此,我着重强调培养这种直觉的方法,帮助读者用全新的方式思考,这类方法可以简化我们工作中的软件安全任务。我应该补充一点,根据我的个人经验,即使对那些比较容易培养安全意识的人来说,他们也一定可以从中获益良多。
本书虽然简洁,但是涵盖了很多方面的问题。在撰写本书的过程中,我已经意识到简洁对这本书的成功至关重要。软件安全领域在广度和深度上都令人生畏,所以我才希望本书尽可能简短,从而让它能够被更多人理解。我的目标是让读者用一种全新的方式来思考安全问题,并且应用在自己的日常工作当中。
本书适合在软件设计、开发等领域已经有所专长的人阅读,包括架构师、UX/UI设计师、程序管理员、软件工程师、编程人员、测试人员和管理人员。技术从业者在理解本书中的概念时应该不会遇到什么障碍——只要他们理解了软件行业的一些基本概念,以及软件架构的基本方法。如今,软件的使用已经非常广泛,类型也相当丰富,我不能说所有软件均依赖安全性,但绝大多数软件确实如此,尤其是那些需要连接到互联网或者需要与人互动的软件。
在撰写本书的过程中,我意识到应该把潜在的读者分为三类。
安全行业的新人——尤其是那些一听到安全就皱眉头的人,他们是我写作时思考的主要受众,因为让所有软件从业者都对安全有所理解是非常重要的,这样大家才能全部参与到提升软件安全性的工作当中。为了让未来的软件更加安全,我们需要所有人的参与,我也希望本书能够帮助那些刚刚开始学习安全技术的人迅速踏上正途。
具备安全基础的读者——是指那些对安全抱有一定的兴趣,但知识层面仍然有待提升的人,他们希望加深自己的理解,学习更多实用技能,从而应用到他们的工作当中。希望本书能够弥补他们的知识空白,提供各种方式让他们可以学以致用。
安全专家——他们或许熟悉本书中的大部分内容,但我相信本书一定会提供一些新的视角,可以给他们提供很多新的内容。具体来说,本书会探讨一系列重要内容,包括安全设计、安全审查和一些很少见诸文字的“软技能”。
本书第三部分会介绍漏洞实施与缓解的方法,包括一些用C或Python语言编写的代码的简短摘录。有些例子假定读者已经熟悉了内存分配的概念,也理解了整数和浮点类型,以及二进制运算。在为数不多的地方,我使用了数学公式,但是复杂度不会超过模和指数运算。如果读者认为这些代码和数学知识的技术性太强,可以跳过这些章节,完全不需要担心因此而无法把握本书叙事的主线。
本书共有13章,分为三大部分,其中包含了概念、设计和实施,以及最终的结论。
本书第1~5章介绍了基础概念。第1章是对信息安全和隐私基础所做的概述。第2章则介绍了威胁建模,以保护资产为背景,对攻击面和信任边界的核心概念进行了具体说明。接下来的三章介绍了一些可供读者使用以实现软件安全的重要工具。第3章探讨了对可识别威胁进行防御性缓解的通用策略。第4章介绍了一些有效的安全设计模式,同时着重说明了一些应该避免的反模式。第5章用工具箱的方式解释了如何使用标准的加密库来缓解常见的风险,同时本章并没有探讨底层的数学原理(这些知识在实践当中很少用到)。
这一部分也许代表了本书对潜在读者最独特也是最重要的贡献。第6章和第7章介绍了如何使软件设计变得安全,以及可以应用哪些技术来实现安全性,它们分别从设计者和审查员的角度分析了问题。在这个过程中,解释了为什么一开始就将安全性融入软件设计是很重要的。
这两章借鉴了本书第一部分介绍的思想,提供了如何将它们结合起来构建安全设计的具体方法。审查方法直接来自作者的行业经验,其中包括了能够适应你的工作方式的分步过程。你可以在阅读这些章节时浏览附录A中的设计文档示例,以此当作将这些想法付诸实践的示例。
第8~13章涵盖了实施阶段的安全性,涉及部署、运维直至生命周期结束。在你有了一个安全的设计后,这一部分将会阐释如何在不引入额外漏洞的情况下进行软件开发。这些章节中包含了代码片段,用来说明漏洞是如何潜入代码中的,以及如何避免出现漏洞。第8章介绍了程序员面临的安全挑战,以及代码中真正的漏洞是什么样的。第9章涵盖了计算机在计算上的弱点,并说明了针对动态内存分配的C风格显式管理是如何对安全性造成破坏的。第10章和第11章涵盖了许多众所周知,但还没有消失的常见错误(比如注入攻击、路径遍历、XSS和CSRF漏洞)。第12章介绍了那些在很大程度上还没有得到充分利用的测试实践,目的是保证我们的代码都是安全的。第13章介绍了安全实施的指导方针,包括一些一般性的最佳实践,同时也对常见的陷阱提出了警示。
本书这一部分摘录的代码一般都会展示需要加以避免的漏洞,同时也会给出修补之后的版本来展示如何让代码更加安全(在书中这两类代码分别标记为“易受攻击的代码”和“修复后的代码”)。书中提供的代码不是为了让读者进行复制,然后运用到生产软件当中的。即使是修复后的代码仍然会因为其他原因而在不同背景下存在漏洞,所以读者不应该把本书提供的任何代码视为绝对安全的代码并加以应用。
后记对本书的内容做了总结,同时对我希望能够产生积极影响的一些方法进行了介绍。在这里,我对本书中的几大重点进行了总结,也对未来进行了展望,并提供了有助于提升软件安全性的一些预测——其中,首要的一点是本书如何为提升未来软件的安全性做出贡献。
附录A是一份设计文档示例,展示了在实践中安全设计文档大致应该如何编写。
附录B是本书中出现的所有软件安全术语的列表。
附录C包含了一些开放式的练习题,以供需要的读者进一步探索。
附录D是一系列重要概念和流程的备忘单。
此外,本书中提到的参考文献汇编可以从异步社区下载获得。
在开始介绍正式内容之前,出于对本书中介绍的安全知识负责的考虑,我想先提出一些警告。为了解释清楚如何让软件更加安全,我需要介绍各类漏洞如何发挥作用,以及攻击者如何对这些漏洞加以利用。从攻击和防御两个方向实践是磨练技能的理想方式,但我们在使用这些知识的时候也需要谨慎。
永远不要在生产系统上试探安全性。比如,在读到有关跨站脚本(XSS)的内容时,读者或许想要试着用经过修改的URL来浏览自己最喜欢的网站,看看会发生什么。千万不要这么干!即使我们的动机是善意的,这种做法从站点管理员角度看仍然和真正的攻击别无二致。读者必须考虑到别人可能会把这类行为解读成威胁。而且与此同时,这种行为在有些国家和地区可能存在法律问题。我们要运用常识,包括思考别人会如何解读我们的行为、我们行为出现差错以及我们的行为跨越红线的后果。因此,如果我们希望尝试一下XSS,可以用伪造的数据来建立自己的Web服务器,然后用这个服务器来练手。
另外,虽然我根据自己在软件领域的多年经验尽可能为读者提供了最好的建议,但没有任何指导方针是无懈可击的,也没有任何指导方针适用于所有环境。本书提到的解决方案绝不是什么“仙丹”,它们只是我提供的建议,或者读者应该掌握的一些常见方法。在对安全决策进行评估的时候,读者应该依靠自己的判断力。没有一本书可以替读者做出判断,但本书可以协助读者找出正确的做法。