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

Security 如何防止程序中的任意代码执行漏洞?,security,execution,platform-independent,Security,Execution,Platform Independent,当您的系统、浏览器或任何程序更新时,您总是会在变更日志中阅读它们修复了一个漏洞,使得攻击者可以使用伪造的网站在您的计算机中执行任何代码,或者使用精心伪造的数据包攻击您的计算机,等等 因为您经常阅读它,这意味着任何程序都可能有类似的漏洞。。。这是什么原因?如何设计我们的程序来防止类似的问题?这个问题有很好的“谷歌”来源,但简而言之,您需要确保所有调用(函数调用、方法调用等)的安全。安全意味着他们将传入的数据截断到正确的大小,不“评估”它,等等 可能的攻击数量非常多。你可能想通过阅读来掌握情况 希望

当您的系统、浏览器或任何程序更新时,您总是会在变更日志中阅读它们修复了一个漏洞,使得攻击者可以使用伪造的网站在您的计算机中执行任何代码,或者使用精心伪造的数据包攻击您的计算机,等等

因为您经常阅读它,这意味着任何程序都可能有类似的漏洞。。。这是什么原因?如何设计我们的程序来防止类似的问题?

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

可能的攻击数量非常多。你可能想通过阅读来掌握情况


希望这有帮助

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

  • 不要相信用户对其数据的描述(记录计数、数组长度等)
  • 在没有仔细检查并使其无害(转义不可打印的字符、验证与结构边界和类型的一致性等)的情况下,不要重复客户端提供给您的任何内容
  • 始终假定,当您被提供信息时,它将被破坏。字符串将不会终止。阵列的大小将不正确。结构将是缺失的部分。数据包将过大或不完整
关键是“防御性编程”。始终检查函数接收其参数的最恶意、格式最错误的方式,然后制定相应的计划。不要以为仅仅因为你在另一端写了代码,你就可以相信它对你的描述。对于最终用户手中的任何代码来说,情况更是如此客户在敌人手中。


彻底采用这种心态,你将为抵御攻击做好更好的准备。但是你仍然会犯错误——每个人都会犯错误——并且需要对错误做出反应,并为客户制定一个更新流程。

一个bug如何创造利用机会的示例:

假设您在程序中有一个子例程,用于修改字符数组中的数据。假设它还包含一个bug,即当数组是特定大小或数组包含特定字符时,子例程会无意中写入超过字符数组末尾的内容

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

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

堆栈上存储的另一个内容是函数调用返回地址——当函数退出时返回的代码地址

现在,您已经具备了创建灾难所需的所有部分:如果您可以将正确的数据传递给此子例程,使其覆盖堆栈,并覆盖到足以覆盖堆栈上离数据缓冲区不远的函数返回地址,然后,您就有可能改变函数退出时程序执行返回的位置。可以让它“返回”(jump,really)到Halt()或Format()或PhoneHome(),而不是返回调用方。此时可以访问当前进程引用的任何库或DLL中的任何函数

这只是任意执行攻击的一个示例。这样的模式有几十种

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

有一本书ISBN 978-0470080238详细介绍了各种类型的利用漏洞(堆栈溢出、堆溢出、sql注入等)