如何在我们的程序中防止任意代码执行漏洞?

时间:2010-04-02 06:48:16

标签: security execution platform-independent

当您的系统或浏览器或任何程序更新时,您总是在更新日志中读取它们修复了一个错误,该错误可能导致攻击者可以使用伪造网站执行您计算机中的任何代码,或者使用经过仔细伪造的数据包攻击您的计算机等...

因为你经常阅读它意味着任何程序都有类似的漏洞......是什么原因造成的?如何设计我们的程序以防止出现类似问题?

4 个答案:

答案 0 :(得分:4)

错误如何为漏洞利用创造机会的一个例子:

假设您在程序中有一个子程序来修改字符数组中的数据。假设它还包含一个错误,当数组是特定大小或数组包含特定字符时,子程序无意中写入字符数组的末尾。

这本身似乎不是一个机会,但取决于执行如何到达子程序以及如何实现和编译的其他工件,它可以用作执行任意代码的跳板。

在传统编程(C,C ++)中,字符数组(缓冲区)通常存储在程序堆栈中。对于小型临时数据,堆栈非常快速且容易分配内存。

存储在堆栈中的另一件事是函数调用返回地址 - 当此函数退出时返回的代码地址。

现在你已经拥有了创建灾难所需的所有部分:如果你可以将正确的数据传递给这个子程序,使其覆盖堆栈,并覆盖它足以覆盖堆栈上不同的函数返回地址从数据缓冲区开始,您就有可能改变函数退出时程序执行将返回的位置。可以使其返回到调用者,而不是“返回”(实际上是跳转)到Halt()或Format()或PhoneHome()。此时可以访问当前进程引用的任何库或DLL中的任何函数。

这只是任意执行漏洞利用的一个例子。有几十种这样的模式。

阻止这种特殊攻击的最简单方法是确保您的代码尊重数据缓冲区的边界。对于大多数编译器,这意味着打开范围检查或类似的运行时检查。在访问数组中的内存位置之前,编译器将发出代码以验证数组索引值是否在范围内。

答案 1 :(得分:1)

第一个也是最重要的规则是“不相信任何人。”

  • 不要相信用户对其数据的描述(记录计数,数组长度等)。
  • 在没有仔细检查并使其无害(逃避不可打印的字符,验证与结构边界和类型的一致性等)的情况下,不要反刍客户给你的任何东西。
  • 始终假设当您获得信息时,它将被破坏。字符串不会被终止。数组的大小不合适。结构将缺失。数据包将超大或不完整。

关键是“防御性编程”。始终检查您的功能可以接收其参数的最恶意,最不正确的方式,然后围绕它进行规划。永远不要以为只是因为你在另一端编写了代码,你可以信任它对你所处理的内容的描述。对于最终用户手中的任何代码而言,这都是双倍的。 客户掌握在敌人手中。

彻底采用这种心态,你将为抵抗攻击做好准备。但是你仍然会犯错误 - 每个人都这样做 - 并且需要回应它们并为你的客户制定更新流程。

答案 2 :(得分:1)

有一本书The Shellcoder's Handbook: Discovering and Exploiting Security Holes,ISBN 978-0470080238,详细介绍了各种类型的开发(堆栈溢出,堆溢出,sql注入等)。

答案 3 :(得分:0)

此问题有很好的“谷歌”来源,但简而言之,您需要安全地进行所有调用(函数调用,方法调用等)。安全意味着他们将传入的数据截断到正确的大小,不要“评估”它,等等。

可能的攻击次数非常多。您可能需要阅读Bugtraq以了解最新信息。

希望这有帮助!