【发布时间】:2011-02-03 15:45:27
【问题描述】:
当您的系统或浏览器或任何程序更新时,您总是会在更新日志中看到它们修复了一个错误,该错误使攻击者可以使用伪造的网站在您的计算机上执行任何代码,或者使用精心伪造的数据包攻击您的计算机等...
因为您经常阅读它,这意味着任何程序都可能有类似的漏洞......是什么原因造成的?如何设计我们的程序以防止出现类似问题?
【问题讨论】:
标签: security execution platform-independent
当您的系统或浏览器或任何程序更新时,您总是会在更新日志中看到它们修复了一个错误,该错误使攻击者可以使用伪造的网站在您的计算机上执行任何代码,或者使用精心伪造的数据包攻击您的计算机等...
因为您经常阅读它,这意味着任何程序都可能有类似的漏洞......是什么原因造成的?如何设计我们的程序以防止出现类似问题?
【问题讨论】:
标签: security execution platform-independent
错误如何创造利用机会的一个示例:
假设您的程序中有一个子例程,它修改字符数组中的数据。假设它还包含一个错误,即当数组为特定大小或数组包含特定字符时,子例程会无意中写入字符数组的末尾。
这本身似乎不是一个很大的机会,但取决于执行如何到达子例程以及如何实现和编译的其他工件,它可以用作执行任意代码的跳板。
在传统编程(C、C++)中,字符数组(缓冲区)通常存储在程序堆栈中。堆栈对于小的临时数据来说是非常快速和容易的内存分配。
另外一个存储在栈上的是函数调用返回地址——这个函数退出时返回的代码地址。
现在你已经拥有了制造灾难所需的所有部分:如果你可以将正确的数据传递给这个子例程以使其覆盖堆栈,并覆盖它足以覆盖同样在堆栈上不远处的函数返回地址来自数据缓冲区,那么您有可能改变函数退出时程序执行将返回的位置。它可以“返回”(实际上是跳转)到 Halt() 或 Format() 或 PhoneHome(),而不是返回给调用者。此时可以访问当前进程引用的任何库或 DLL 中的任何函数。
这只是任意执行漏洞的一个示例。有几十种这样的模式。
阻止此特定漏洞利用的最简单方法是确保您的代码遵守数据缓冲区的边界。对于大多数编译器,这意味着打开范围检查或类似的运行时检查。在访问数组中的内存位置之前,编译器会发出代码来验证数组索引值是否在范围内。
【讨论】:
第一条也是最重要的规则是“不信任任何人”。
关键是“防御性编程”。始终检查您的函数可以接收其参数的最恶意、最畸形的方式,然后围绕它进行计划。永远不要认为仅仅因为你在另一端编写了代码,你就可以相信它对它所传递给你的内容的描述。这对于最终用户手中的任何代码来说都是双重的。 客户在敌人手中。
彻底采用这种思维方式,您就能更好地抵御攻击。但是您仍然会犯错误 - 每个人都会犯错误 - 并且需要对错误做出回应并为您的客户制定更新流程。
【讨论】:
有一本书The Shellcoder's Handbook: Discovering and Exploiting Security Holes,ISBN 978-0470080238,详细介绍了各种类型的利用(堆栈溢出、堆溢出、sql 注入等)。
【讨论】:
这个问题有很好的“google”来源,但简而言之,您需要确保所有调用(函数调用、方法调用等)安全。安全意味着他们将传入的数据截断到合适的大小,不要“评估”它,等等。
可能的攻击次数非常多。您可能需要阅读 Bugtraq 以了解最新情况。
希望这会有所帮助!
【讨论】: