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

发布于 2024-08-27 15:26:04 字数 170 浏览 12 评论 0原文

当您的系统或浏览器或任何程序更新时,您总是会在更改日志中看到它们修复了一个错误,该错误使攻击者可以使用伪造的网站在您的计算机中执行任何代码,或者使用精心伪造的数据包攻击您的计算机等......

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

You always read in changelogs when your system or browser or any program updates that they fixed a bug that made possible that an attacker can execute any code in your computer with a forged website, or attacking your computer with carefully forged packets, etc...

Because you read it so often that means any program can have similar vulnerabilites... What causes this? how to design our programs to prevent similar issues?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深居我梦 2024-09-03 15:26:04

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

假设您的程序中有一个子例程,该子例程修改字符数组中的数据。假设它还包含一个错误,即当数组具有特定大小或数组包含特定字符时,子例程会无意中写入超出字符数组末尾的内容。

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

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

堆栈上存储的另一件事是函数调用返回地址 - 当该函数退出时返回到什么代码地址。

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

这只是任意执行利用的一个示例。这样的图案有几十种。

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

One example of how a bug can create an opportunity for exploit:

Let's say you have a subroutine in a program that modifies data in an array of characters. Let's say it also contains a bug that when the array is a particular size or the array contains particular characters, the subroutine inadvertantly writes past the end of the array of characters.

This by itself doesn't seem like much of an opportunity, but depending on how execution reaches the subroutine and other artifacts of how it is implemented and compiled, it could be used as a springboard to executing arbitrary code.

In traditional programming (C, C++), character arrays (buffers) are often stored on the program stack. The stack is very fast and easy memory allocation for smallish temporary data.

Another thing that is stored on the stack is the function call return address - what code address to return to when this function exits.

Now you have all the pieces needed to create disaster: If you can pass just the right data to this subroutine to make it overwrite the stack, and overwrite it enough to overwrite the function return address that is also on the stack not far from the data buffer, then you have the potential to alter where program execution will return to when the function exits. Instead of returning to the caller, it could be made to "return" (jump, really) to Halt() or Format() or PhoneHome(). Any function in any library or DLL referenced by the current process is accessible at this point.

This is just one example of an arbitrary execution exploit. There are dozens of such patterns.

The easiest way to thwart this particular exploit is to ensure that your code respects the bounds of your data buffers. For most compilers, this means turning on range checking or similar runtime checks. The compiler will emit code to validate that an array index value is in range before accessing the memory location in the array.

为你拒绝所有暧昧 2024-09-03 15:26:04

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

  • 不要相信用户对其数据的描述(记录计数、数组长度等)。
  • 在没有仔细检查并使其无害之前,不要反省客户给您的任何内容(转义不可打印的字符,验证与结构边界和类型的一致性等)。
  • 始终假设当您获得信息时,该信息将会被损坏。字符串不会被终止。数组的大小将会错误。结构将会缺失。数据包将过大或不完整。

关键是“防御性编程”。始终检查您的函数接收参数的最恶意、最畸形的方式,然后围绕它进行计划。永远不要假设仅仅因为您在另一端编写了代码,您就可以相信它对它所提供给您的内容的描述。对于最终用户手中的任何代码来说,情况更是如此。 客户落入敌人手中。

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

The first and most important rule is "trust no one."

  • Don't trust the user's description of their data (record counts, array lengths, etc).
  • Don't regurgitate anything the client gives you without having carefully examined it first and rendered it harmless (escaping unprintable characters, validating conformance with structure boundaries and types, etc).
  • Always assume that when you are being supplied with information, it will be corrupted. Strings will not be terminated. Arrays will be mis-sized. Structures will be missing pieces. Packets will be oversized or incomplete.

The key is "defensive programming". Always examine the most malicious, malformed way that your functions could receive their parameters and then plan around it. Never assume that just because you wrote the code on the other end, you can trust its description of what it's handing you. This goes doubly so for any code which is in the hands of an end-user. The client is in the hands of the enemy.

Adopt this mindset thoroughly and you'll be better prepared for withstanding attacks. But you'll still make mistakes -- everyone does -- and need to respond to them and have an update process in place for your customers.

梅窗月明清似水 2024-09-03 15:26:04

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

There is a book The Shellcoder's Handbook: Discovering and Exploiting Security Holes, ISBN 978-0470080238, that goes into great detail into the various types of exploitations (stack overflow, heap overflow, sql injection, etc).

尽揽少女心 2024-09-03 15:26:04

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

可能的攻击数量非常大。您可能需要阅读 Bugtraq 以掌握最新情况。

希望这有帮助!

There are good "google" sources for this problem, but in short, you need to make all your calls (function calls, method calls, etc) safe. Safe means they truncate incoming data to its right size, do not 'eval' it, and so on.

The number of possible attacks is very large. You may want to read Bugtraq to keep on top of things.

Hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文