缓冲区溢出攻击的预防技术是什么?

9

如何预防缓冲区溢出攻击?我听说过Stackguard,但是仅仅应用Stackguard技术是否完全解决了这个问题?

作为一名经验丰富的程序员,你认为为何为缓冲区溢出攻击提供足够的防御措施如此困难?

编辑:感谢所有回答并保持安全标签活跃 :)


2
悲哀的事实是,半吊子的解决方案能够获得更多的利润,因为明年你可以销售一个稍微好一点的解决方案并赚更多的钱。有些解决方案并不能神奇地解决问题,但确实可以帮助程序员确保每一个可能的缺陷都得到了保护。http://www.google.com/search?q=taint+type+system - Ben Voigt
6个回答

5
有很多事情可以做。 没有特定的顺序...
首先,如果你的语言选择在允许直接内存访问和不允许之间平均分配(或接近平均分配),请选择不允许的一种。也就是说,使用Perl、Python、Lisp、Java等而不是C/C++。这并不总是可行的选择,但它确实有助于防止自己踩到陷阱。
其次,在允许直接内存访问的语言中,如果有处理内存的类可用,例如std::string,请使用它们。更喜欢经过充分验证的类,而不是用户较少的类。更多的使用意味着常规使用中更容易发现简单的问题。
第三,使用编译器选项,例如ASLR和DEP。使用应用程序提供的任何与安全相关的编译器选项。这不会防止缓冲区溢出,但会有助于减轻任何溢出的影响。
第四,使用静态代码分析工具,例如Fortify、Qualys或Veracode的服务,以发现您没有编码的溢出。然后修复发现的问题。
第五,学习溢出是如何工作的,以及如何在代码中发现它们。所有同事都应该学习这个。创建一个组织范围的政策,要求人们接受有关溢出(和其他漏洞)工作方式的培训。
第六,将安全代码审查与常规代码审查分开进行。常规代码审查确保代码有效,通过功能测试,符合编码策略(缩进、命名约定等)。安全代码审查专门、明确、仅旨在查找安全问题。对您可以的所有代码进行安全代码审查。如果必须优先考虑,从任务关键的内容开始,可能会出现问题的内容(跨越信任边界的地方(了解数据流图和威胁模型并创建它们),使用解释器的地方,以及传递/存储/检索用户输入的地方,包括从数据库检索的数据)。
第七,如果您有钱,可以聘请像Neohapsis、VSR、Matasano等好的顾问来审查您的产品。他们会发现比溢出更多的问题,您的产品也会因此变得更好。
第八,确保您的QA团队知道溢出是如何工作的以及如何测试它们。QA应该有专门设计用于在所有输入中查找溢出的测试用例。
第九,进行模糊测试。在许多产品中,模糊测试可以找到惊人数量的溢出。
编辑后添加:我误读了问题。标题说“什么是技术”,但文本说“为什么很难”。
这很难,因为很容易犯错误。小错误,如偏移一个错误或数字转换,可能导致溢出。程序是复杂的生物,具有复杂的交互作用。在存在复杂性的地方就会出现问题。
或者,将问题转回给你:为什么编写无错误代码如此之难?

数一下你说“雇用专业服务”的次数,你就会发现这是真正的金钱。这就是为什么他们中没有人会提倡像类型系统中的污点检查这样的系统方法,因为全面的解决方案不会带来重复的咨询费用。 - Ben Voigt
1
我曾经说过要雇佣专家。我也曾经说过要在外部花钱。污点检查有所帮助,但不能防止问题的发生。它们只是提醒您检查输入是否已经验证;它们并不检查您的验证是否正确或适用。此外,当您创建软件时,您正在谈论真正的金钱。当您验证该软件的任何质量时,您正在谈论真正的金钱。当您的软件具有专业功能时,您需要真正的专业知识来确保它是正确的。当您处理安全性时,为什么应该有所不同呢? - atk
我只是在说,专家们有经济利益让你不学习工具来自行系统地管理安全。 - Ben Voigt
我从未遇到过一个安全专家不喜欢开发人员学习如何正确处理安全问题的想法。但在任何环境下,专家都是专家。如果有可用的资金(无论是作为顾问还是全职雇员,或者是志愿者参与开源项目),他们在指出非专家看不到的问题方面非常有用。专家也倾向于比非专家更加关注最前沿的趋势。 - atk

2

没有安全的万灵药:您必须仔细设计、仔细编码、进行代码审查、测试,并安排及时解决漏洞。

幸运的是,缓冲区溢出已经是一个解决了很长时间的问题。大多数编程语言都有数组界限检查,并且不允许程序随意创建指针。只需不使用少数几个允许缓冲区溢出的语言,如C和C++即可。

当然,这适用于整个软件堆栈,从嵌入式固件¹到您的应用程序。

¹ 对于那些不熟悉涉及技术的人,此漏洞可以允许网络上的攻击者唤醒并控制关闭的计算机。(典型的防火墙配置会阻止有问题的数据包。)


2

缓冲区溢出漏洞是可以预防的。如果程序员是完美的,就不会有未经检查的缓冲区,因此也不会有缓冲区溢出漏洞。然而,程序员并不完美,未经检查的缓冲区仍然大量存在。


1
我会说,“未经检查的缓冲区供应继续溢出”。 - Ira Baxter

2

只需要一项技术: 不要相信来自外部来源的数据。


1
我同意你的帖子,但这并不足够。好的开发人员并不完全理解全部含义。过程和工具是必要的,以验证正确的实现。我可以告诉你,“总是编写正确的代码”,但这并不能教你如何编写正确的代码或发现它是否不正确。污点标记指示未经验证的内容,而不是指示(不)正确的验证。我同意,DEP和ASLR使其更加困难,但这就是安全性 - 使事情变得更加困难,以至于它们要么不可行,要么不值得努力/支出。 - atk
1
我本应该说,“好的开发者并不总是理解...”。你可能认为这很容易,但我见过很多其它方面非常优秀的开发者根本没有领悟。将“好”的定义限制在某些范围内或许可以支撑你的论点,但这并不能解决实际世界中的问题:好的开发者也会犯错,而强类型虽然有助于缩小攻击面,但并不能消除漏洞。除了BSD之外,我不知道还有哪个复杂的、面向消费者或商业的产品被证明是正确的——即便是BSD在被证明正确之后仍然有漏洞。 - atk
1
现在,需要确保每次正确处理边缘情况的任务留给了自动化静态分析,这就是它的好处所在。类型系统中的污点支持是一种形式的正式静态分析,在误报方面具有非常好的性能,而误报问题只有在对经过严格审查的大型现有代码库进行改装时才可能成为问题。 - Ben Voigt
1
我从未认为污点支持是一个坏主意。我主张把所有的鸡蛋放在一个篮子里是不明智的。安全程序应该遵循深度防御的概念,就像应用程序安全或现实世界中的安全一样。 - atk
我完全同意这一点。只有在资源有限的情况下(而且它们总是有限),才需要进行一些成本效益分析。ASLR是完全自动化的,因此成本非常低。但接下来呢?有一些建议进行模糊测试和单元测试溢出,但我认为污点是发现需要进行溢出检查的更好方法,而不是任何可行数量的模糊测试。 - Ben Voigt
显示剩余7条评论

1

在代码进入生产之前,您可以运行分析器来帮助您找到问题。我们的内存安全检查器将通过仪器化您的代码以在错误发生时监视错误,从而在C代码中找到缓冲区溢出、错误指针故障、数组访问错误和内存管理错误。如果您希望C程序对此类错误不受影响,您可以简单地使用内存安全分析器的结果作为您的代码的生产版本。


0

在现代开发中,三大要素是:

ASLR

Canary

NX Bit

现代版本的GCC默认应用Canaries。并非所有的ASLR都是相同的,Windows 7、Linux和*BSD拥有最好的ASLR。OSX的ASLR实现远不如其他系统,很容易被绕过。一些最先进的缓冲区溢出攻击使用奇特的方法来绕过ASLR。NX Bit是最容易绕过的方法,return-to-libc风格的攻击使其对于攻击者来说不再是问题。


把一个瑞士奶酪形状的钢板放在窗户上可以阻挡很多来袭的火力,但并不能保证没有子弹穿过。 - Ben Voigt
1
我想我应该更清楚。这些技术现在已经完全自动化并且几乎免费,所以请务必使用它们。但是当安全性至关重要时,请不要信任它们。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接