找出并保护程序的入口
本文论述了数据进入您的程序的各种途径,重点是如何适当地对它们进行处理;您甚至可能还没有了解它们全部!本文首先论述了如何设计程序来限制数据可以进入您的程序的途径,以及您的设计会如何影响哪些可以成为输入。然后论述了各种不同的输入通道以及如何使用这些通道,包括环境变量、文件、文件描述符、命令行、图形用户界面(GUI)、网络数据以及其他的输入。
早在 2001 年,许多大公司安装了应用程序“SAP R/3 Web Application Server demo”,却没有发现它有一个致命的漏洞。这个应用程序中有一个名为 saposcol 的程序,没有能保护自己免受恶意输入值的攻击。攻击者可以通过设置 PATH 环境变量来改变 saposcol 寻找其他程序的位置,然后为 saposcol 创建一个恶意的“扩展”程序来运行。由于 saposcol 具有 setuid root 权限,这就意味着因为这一个编程上的失误,本地用户可以(作为 root)很快地获得整个计算机系统的控制权(参阅 参考资料 中的链接,以深入了解这一点及本文中提到的其他相关内容)。
本专栏的前一期文章 指出了一些常见的输入数据类型以及检查它们的方法。但是如果您不知道所有的数据自何处而来,那么,只是知道如何检查数据类型是不够的。本文讨论了数据进入您的程序的各种不同途径 —— 有一些并不是显而易见的 —— 并着重讨论了如何适当地去处理它们。
如果您不控制,攻击者就会来控制
安全的程序中第一道防线是检查每一个不可信的输入。但是这是什么意思呢?可以归结为以下三点:
1. 限制程序暴露的部分。如果您的程序分为若干块 —— 这通常是一个好主意 —— 那么尽量设计得让攻击者根本不能与大多数块通信。这包括不能让他们利用各块之间的通信路径。如果攻击者不能查看、修改或者插入他们自己的数据到那些通信路径中(包括作为块间的中间人潜入),那是最好了。如果那不可能 —— 比如当块之间使用网络通信时 —— 那么使用加密等机制来防范攻击者。后续的文章将更深入地讨论这一问题。
2. 限制暴露部分所允许的输入类型。有时您可以修改设计以使只有少数的输入可以接受 —— 如果可以,那么就这样做吧。
3. 严格检查不可信的输入。真正“安全”的程序应该没有任何输入,但那种程序是没有用处的。因而,您需要对来自于不可信源的输入路径的数据进行严格的检查。 前一期文章 论述了如何检查各种不同类型的数据;本文将帮助您确定这些数据的来源。这并不是说您 只需检查进入您的程序的数据。通常明智的做法是检查多个位置的数据,但是您必须至少检查所有的数据一次,并且明智的做法是至少在数据第一次进入时进行一次检查。
程序的类型决定一切
您必须检查所有不可信的输入 —— 但是什么是不可信的输入呢?其中一些取决于您的程序要做什么。如果您的程序是数据的浏览器或者编辑器(比如文字处理器或者图像显示器),而这些数据有可能来自攻击者,所以那是不可信的输入。如果您的程序响应网络上的请求,那些请求可能正是来自攻击者 —— 所以网络连接是不可信的输入。
另一个重要的因素是您的程序是如何设计的。如果您的程序运行时身份是“root”或者其他一些特权用户,或者有对数据(比如数据库中的数据)的访问特权,那么从程序中没有特权的部分到那些有特权的部分的输入是不可信的。
尤其重要的情形是所有的“setuid”或者“setgid”的程序。只是运行一个 setuid/setgid 程序就会获得特权,这些程序特别难以保证安全。为什么呢?因为 setuid/setgid 程序有特别多的输入 —— 它们中很多输入多得惊人 —— 可以被攻击者控制。
共6页: 上一页 1 [2] [3] [4] [5] [6] 下一页