下载本文的PDF版本 PDF

安全比你想象的更难

不仅仅是缓冲区溢出。

John Viega 和 Matt Messier,安全软件

许多开发者认为缓冲区溢出是对软件最大的安全威胁,并相信有一个简单的两步过程来保护软件安全:从 C 或 C++ 切换到 Java,然后开始使用 SSL(安全套接层)来保护数据通信。但事实证明,这种幼稚的策略是不够的。在本文中,我们将探讨为什么软件安全比人们预期的更难,重点关注 SSL 的例子。

我们是如何走到这一步的

尽管像 Java 这样的语言让程序员比 C 语言更少有机会搬起石头砸自己的脚,但仍然有很多机会伤到脚趾。在一项基于商业代码安全审查的非正式研究中,我们发现 C 代码的漏洞往往比 Java 代码多 5 到 10 倍。考虑到我们在 C 代码中发现的漏洞数量,这对 Java 来说仍然不算什么好消息。

软件安全问题是如此严重,以至于微软在 2002 年初花费了两个月的时间,让所有开发者专注于这个主题(“可信计算”计划的主要组成部分)。不允许开发新功能,只能改进安全性。开发者接受了广泛的培训,高管们承诺,宁愿推迟产品发布,也不愿发布存在安全问题的产品。这不仅仅是一次性的推动。微软承认,其持续推动改进软件安全性导致了交付期限的延误。

尽管微软为此投入了大量资金,但巨大的回报仍然遥遥无期。虽然自推动以来,微软产品中发现的安全漏洞数量有所减少,但远未停止,并且在一段时间内也不会停止。

无论微软的投资是多少,这都是非常昂贵的。尽管该公司肯定希望通过从最差到最好来扭转公众对其安全实践的看法,但令人难以置信的是,尽管微软进行了如此巨大的投资,但 20 年后的微软产品中仍然不会存在安全风险。

这根本不可能。安全是关于风险管理,而有些风险永远不会完全消失。例如,所有加密方案都有理论上的局限性,并且始终存在政府或其他人破解它的风险。不过,这个例子有点深奥。在实践中,一些备受瞩目的风险(例如缓冲区溢出)有相当直接的解决方案,但最容易实施的攻击类型——特别是社会工程学和内部人员攻击——则不然。

这些风险令人担忧,但即使是具有安全意识的开发团队也忽视了这个问题。据 Gartner 称,70% 的 IT 系统攻击来自内部人员。然而,大多数开发组织并没有意识到这一点,也许是因为大多数 IT 组织都采取“这种事不会发生在我们这里”的态度。大多数人奉行“我们信任我们的人”的信条,但即使这是真的,也可能不仅仅是您的人员才是内部人员:承包商、朋友和清洁工也存在风险。

人员问题

社会工程学同样难以防范。当帮助台整天处理合法忘记密码并需要重置密码的用户时,要筛选出听起来很有说服力的人有多困难?即使要求提供母亲的娘家姓或社会安全号码的后四位数字也不是很有效。优秀的社会工程师通常可以成功地冒充权威人物、维修工人或任何达到其目标所必需的角色。凯文·米特尼克的著名黑客事迹在很大程度上是社会工程学的壮举。如果您不认为社会工程学是一个严重的风险,那么我们建议您阅读他的著作《欺骗的艺术:控制安全的人为因素》(John Wiley and Sons,2002 年)。

在密码系统的情况下,为了安全起见,最好完全放弃它们。但是,我们可能会在一段时间内仍然受困于它们,因为其他解决方案(例如生物识别技术和智能卡)要么成本太高,要么对用户来说太不方便。

即使这些问题有直接的解决方案,该行业仍然有很长的路要走。对于普通开发者来说,要真正理解所有可能的风险,尤其是在大多数开发组织更重视新功能而不是安全性时,可能会出错的事情太多了。深入了解软件的每一个重大风险并非易事,尤其考虑到在密码学等复杂领域中可能出错的一些微妙之处。

归根结底,开发者不应该了解太多关于安全性的知识。风险分析应该留给专家。应该为普通开发者提供抽象,让他们可以轻松构建优秀的应用程序,而无需详细了解安全风险。他们只需要了解如何使用抽象,至少尽可能多地了解。到目前为止,安全行业在这方面做得还不够好。

无脑安全

SSL 是安全领域可以做得更好的一个很好的例子。大多数开发者认为 SSL 是标准网络套接字的直接替代品——也就是说,只需用启用 SSL 的调用替换标准 API(应用程序编程接口)调用,神奇地,就有了安全性。一些开发者可能意识到客户端-服务器应用程序服务器端的系统管理员必须做一些事情才能使这一切正常工作,但这对于开发者来说仍然往往是透明的。

也许应该如此简单,但事实并非如此。SSL 旨在提供经过身份验证的加密通信通道,攻击者无法在传输过程中篡改数据,而不会在接收端被检测到。完整性和加密是容易的部分。困难的部分在于建立 SSL 连接,尤其是在执行身份验证时。在大多数客户端-服务器案例中,客户端希望确定它正在与正确的服务器对话,而服务器希望确定它知道连接另一端的用户是谁——也就是说,双方真正需要的是相互身份验证。大多数人期望 SSL 对客户端验证服务器,然后,一旦建立加密数据通道,就在其上实现(通常是弱)身份验证机制,以便服务器可以建立客户端的身份。

不幸的是,人们每天使用的 SSL 库默认情况下不会进行充分的服务器验证。在大多数情况下,SSL 使用基于证书的验证方案进行服务器身份验证(其他选项,例如仅密码协议,是可能的,但只有实验库实现了这些)。在这样的方案中,要验证的一方(通常是服务器)向另一方(客户端)出示其证书,该证书是信息捆绑包,其中包括公钥、身份信息、表示有效期和作为证书有效性背书的一个或多个数字签名。数字签名通常由 CA(证书颁发机构)例如 VeriSign 放置在那里,VeriSign 负责确保它只背书那些真正属于预期所有者的证书。

考虑客户端

这里的想法是客户端可以检查签名。如果签名有效并且是由受信任的机构放置在那里的,那么客户端就可以确信证书的内容是相当准确的。当然,证书颁发机构是因效率而获得奖励的企业,因此它们有时会颁发虚假证书也就不足为奇了。例如,几年前,VeriSign 签署了两份声称来自微软的证书,但实际上肯定不是。

但是,让我们先假设证书颁发机构永远不会犯错。我们还假设我们关心与之开展业务的公司擅长保护与该证书关联的私钥,因为窃取私钥会导致攻击者能够冒充该证书绑定的服务器。

客户端仍然需要做几件事来确保证书是正确的证书。如果您想与 amazon.com 通话,仅检查 VeriSign 的签名是不够的。如果您获得 VeriSign 为 Barnes and Noble 或 attacker.org 签名的证书怎么办?

在大多数情况下,客户端应至少执行以下操作

• 检查证书是否由已知的 CA 签名。

• 检查证书是否是最新的(特别是,它是否已过期)。

• 检查证书是否绑定到客户端想要与之通信的实体。

第一项和第三项至关重要。如果证书不是由受信任方签名的,那么任何人都可以签名。如果证书声称属于 Microsoft,但由 attacker.org 签名,您应该信任它吗?可能不应该。要正确地做到这一点,您需要一组来自证书颁发机构的受信任凭据,称为根证书。如今,Windows 和 OS X 等商业操作系统以及大多数第三方 SSL 库(包括流行的 OpenSSL)都附带了一组根证书。

验证

验证证书中的数据并非易事。通常,证书将绑定到域名。在某些情况下,域名将指向单个机器。在其他情况下,证书旨在从该域中的任何机器都有效。

无论出于何种原因,主要的 SSL 库默认情况下都不会为开发者执行任何此类验证。事实上,实现前面提到的所有三个简单策略往往非常复杂。

如果您想考虑到有效证书可能会被盗用的事实,情况会变得更糟。您要么需要下载并检查每个证书颁发机构发布的 CRL(证书吊销列表),要么检查指定的 OCSP(在线证书状态协议)服务器。标准加密库没有努力使执行这些任务中的任何一个变得容易。它们不保留有关任何这些资源的信息。更糟糕的是,大多数 CA 无论如何都不会公开这些资源。如果您碰巧找到了它们,实现往往也很复杂。很少有库完全支持 OCSP。

所有这一切都特别令人沮丧,因为大多数关于安全编程的书籍都没有解释这些问题。它们只是简单地说,“使用 SSL”,这就是它们关于密码学的大部分讨论。使用 OpenSSL 的人可以查看我们的书《C 和 C++ 安全编程食谱》(O'Reilly,2003 年),其中包含实现这些策略的代码,但到目前为止,使用其他平台的人运气不佳。

这个问题完全没有必要。当用户请求打开客户端套接字时,SSL 库可以轻松地对服务器证书执行所有合理的检查,包括检查证书是否绑定到用户提供的域。如果这种验证对于某些场景来说过于严格,那么应该有一种方法可以绕过它。然而,绝对没有理由说明为什么这不能成为默认行为。

陷入中间

结果是,大多数使用 SSL 的应用程序都容易受到中间人攻击。当客户端和服务器认为它们正在直接相互对话时,实际上它们正在与恶意代理对话时,就会发生这种情况。如果用户不进行任何检查,攻击者可以出示任何证书,以使用户与攻击者而不是服务器对话。如果用户正在检查 CA 背书,但不检查实体信息,那么攻击者可以使用 CA 背书的任何证书,客户端将简单地接受它。而且,如果用户检查实体信息,但不查找 CA 背书,那么攻击者可以构建自己的具有正确实体信息的证书,并将其出示给客户端。

这个问题很普遍。不仅仅是开发库在这方面犯错。行业中的许多其他人也犯了错。我们将用一家真实的公司(我们称之为“X 公司”以保持其匿名性)来说明,该公司管理金融交易,并为供应商提供使用 SSL 的安全解决方案。基本思路是,供应商与客户进行交易,通常在不安全的环境中,然后,在最终确定交易之前,通过 SSL 连接到 X 公司的服务器,并检查供应商和 X 公司是否就交易达成一致。供应商提供所有信息;然后 X 公司响应,指示交易是否有效。

问题是,X 公司没有向商家展示如何建立到其服务器的安全 SSL 连接——而是通过一些糟糕的文档和示例代码,它向供应商展示了如何建立不安全的 SSL 连接。事实上,在得知问题两年多后,X 公司仍然分发完全不进行任何证书验证的示例代码。遵循此配方的供应商可能会面临中间人攻击的风险。

有些人会认为中间人攻击只是一个理论问题。X 公司的论点是,由于互联网骨干网几乎没有给攻击者立足的机会,因此这些漏洞“极不可能发生”。假设没有人可以利用互联网的路由器基础设施(即使 Cisco 的 IOS 软件是用一种容易出现缓冲区溢出的语言编写的,并且以前也发现过 IOS 中的漏洞),人们可以从与两个端点之一位于同一底层介质上的机器上发起中间人攻击。也就是说,与其中一个端点位于同一本地子网上的任何机器都可以用来发起此类攻击。

这种攻击很容易实现。有一些工具可以自动化拦截过程,例如 dsniff (http://naughty.monkey.org/~dugsong/dsniff/)。攻击者欺骗商家通常只需要在商家的网络上获得立足点。有时,攻击商家的 ISP 也会奏效。

许多组织认为他们的运营安全流程解决了这个问题。特别是,有些人认为交换机可以阻止这种拦截问题。不幸的是,一种称为 ARP(地址解析协议)欺骗(攻击者伪造低级网络地址)的技术使得在交换环境中进行拦截成为可能。一般来说,您应该始终假设攻击者完全控制了网络。

是的,中间人攻击是真实存在的,并且有人发起它们。我们已经看到证据表明,有人至少以 X 公司的一家供应商为目标,但是,由于 X 公司的大部分交易都是明文进行的,因此商家不太可能受到这种特定攻击的攻击。坏人倾向于首先攻击最薄弱的环节。

我们能做什么?

事实仍然是,作为一个行业,我们在理解和减轻软件风险方面显然做得不够好。供应商在很大程度上未能为开发者提供正确的抽象,以及确保有效使用这些抽象的正确心智模型。开发者最终不应该了解太多关于证书验证、SQL 注入攻击、缓冲区溢出、粉碎攻击等等的知识,如果有什么需要了解的话。他们应该被良好的抽象概念迎头痛击,以及正确使用这些抽象概念并确定他们需要了解的超出这些抽象概念的安全性的最少量知识。

然而,由于现实世界对开发组织还不是很友好,因此他们需要对安全性更加勤奋。由于世界在教育人们了解风险方面做得不够好,组织应该尽可能多地发展这方面的专业知识。即使行业提供了出色的 API,使我们不必过于努力地保护自己免受中间人攻击、缓冲区溢出、SQL 注入攻击、整数溢出、跨站点脚本攻击、会话固定攻击等等的侵害,我们也永远不应停止思考可能出错的事情。

不太可能存在绝对的解决方案来保护我们免受软件面临的所有威胁,尤其是在考虑到内部人员风险和社会工程学时,但教育、意识和勤奋可以帮助我们实现目标。例如,金融机构花费大量资源进行深入研究的预先风险分析,这样做会产生可证明的结果。包括微软在内的许多开发组织开始使用轻量级的威胁建模和风险分析技术,例如攻击树。

攻击树、避免常见错误的秘诀以及其他最佳实践等技术现在已在《构建安全软件》(John Viega 和 Gary McGraw,Addison Wesley Professional,2001 年)、《编写安全代码》(Michael Howard 和 David LeBlanc,第二版,Microsoft Press,2002 年)和《C 和 C++ 安全编程食谱》(John Viega 和 Matt Messier,O'Reilly,2003 年)等书籍中得到了很好的记录。我们建议花时间研究这些资源,而不是传统的忽视问题的方法!

喜欢还是讨厌?请告诉我们

[email protected]www.acmqueue.com/forums

JOHN VIEGA 是 Secure Software (www.securesoftware.com) 的首席技术官,也是三本关于软件安全书籍的合著者,包括《构建安全软件》(Addison-Wesley,2001 年)和《C 和 C++ 安全编程食谱》(O'Reilly,2003 年)。

MATT MESSIER 是 Secure Software 的工程总监,也是《C 和 C++ 安全编程食谱》(O'Reilly,2003 年)和《OpenSSL 网络安全》(O'Reilly,2002 年)的合著者。

©2004 1542-7730/04/0700 $5.00

acmqueue

最初发表于 Queue 第 2 卷,第 5 期——
数字图书馆 中评论本文





更多相关文章

Jinnan Guo, Peter Pietzuch, Andrew Paverd, Kapil Vaswani - 使用机密联邦学习的可信 AI
安全性、隐私性、问责制、透明度和公平性原则是现代人工智能法规的基石。经典的 FL 在设计时非常强调安全性和隐私性,但以牺牲透明度和问责制为代价。CFL 通过将 FL 与 TEE 和承诺相结合,弥补了这一差距。此外,CFL 还带来了其他理想的安全属性,例如基于代码的访问控制、模型机密性和推理期间的模型保护。机密计算的最新进展,例如机密容器和机密 GPU,意味着现有的 FL 框架可以无缝扩展以支持低开销的 CFL。


Raluca Ada Popa - 机密计算还是密码计算?
通过 MPC/同态加密与硬件 enclave 进行安全计算,在部署、安全性和性能方面存在权衡。关于性能,您考虑的工作负载非常重要。对于简单的求和、低阶多项式或简单的机器学习任务等简单工作负载,这两种方法都可以在实践中使用,但对于复杂的计算(例如复杂的 SQL 分析或训练大型机器学习模型),目前只有硬件 enclave 方法在许多实际部署场景中足够实用。


Matthew A. Johnson, Stavros Volos, Ken Gordon, Sean T. Allen, Christoph M. Wintersteiger, Sylvan Clebsch, John Starks, Manuel Costa - 机密容器组
此处介绍的实验表明,Parma(在 Azure 容器实例上驱动机密容器的架构)增加的额外性能开销不到底层 TEE 增加的额外性能开销的百分之一。重要的是,Parma 确保了容器组所有可达状态的安全性不变性,根植于证明报告中。这允许外部第三方与容器安全地通信,从而实现广泛的容器化工作流程,这些工作流程需要对安全数据的机密访问。公司获得了在云中运行最机密的工作流程的优势,而无需在其安全要求上妥协。


Charles Garcia-Tobin, Mark Knight - 使用 Arm CCA 提升安全性
机密计算通过将监管系统从 TCB 中移除,从而减小 TCB 的大小、攻击面和安全架构师必须考虑的攻击向量,从而具有提高通用计算平台安全性的巨大潜力。机密计算需要在平台硬件和软件方面进行创新,但这些创新有可能增强对计算的信任,尤其是在由第三方拥有或控制的设备上。机密计算的早期消费者将需要自行决定他们选择信任的平台。





© 保留所有权利。

© . All rights reserved.