定义接口
与其他 Web 应用程序相比,XML Web 服务器应用程序的一个主要优点就是很好地定义了传递到您的应用程序的整个 XML 架构。对于应用程序设计人员和开发人员来说,这意味着您已经知道 XML Web 服务所必须处理的数据具有有效的格式。如果接收的数据格式不正确,那么 Microsoft® SOAP Toolkit 2.0 或 .NET 框架之类的工具将过滤出该请求,这样您就不必为此担心了。
例如,您不必分析日期输入的语法是否有效。日期必须具有有效的 XSD 格式,否则该请求会被丢弃。您可能需要利用结构验证,因此不要隐藏字符串变量中的结构。利用 XML 的能力和灵活性可以全面描述发送和接收的数据。
不可见的服务器
黑客攻击您的系统时,首先寻找的是信息。此 Web 站点是驻留在 Windows 中还是驻留在其他系统中?是否正在运行 Active Server Pages?是否安装了 Index Server?是否安装了已知的易受攻击的组件?是否安装了已知的易受攻击的 CGI 应用程序?主机是否正在运行 Microsoft® SQL Server?我是否可以对此服务器进行分布式 COM (DCOM) 调用?
对于不希望受到攻击的站点,即使非常聪明的 Internet 用户也应该无法回答上述任何问题。黑客对您的系统了解得越少,对平台的了解也越少,就越难在您的服务器上找到问题。
例如,试想一下,如果黑客只知道 XML Web 服务的 URL 为“http://www.coldrooster.com/ssf/account.asp”,他们能了解什么呢。由于此 URL 的扩展名为 .ASP,他们可以假设这是一台运行了 Active Server Pages 的 Windows 计算机。根据黑客对 Internet Information Server 的默认配置的了解,他们已具有足够的信息对大量的未正确配置的弱点进行攻击。他们可对配置方法进行大量的、很可能有效的假设,并用这些假设来刺探计算机。
如果 URL 为“http://www.coldrooster.com/ssf/account/”,情况又会怎样呢?在这种情况下,黑客得不到任何服务器所用操作系统的信息,也无从假设系统的配置。将虚拟目录级的请求映射到某个特定的 ASP 页是一个非常小的配置选项,但能为服务器提供很多保护。
熟悉基本 HTTP 协议的用户可能注意到 HTTP 标头特别指明了正在使用的 Web 服务器类型。是的,这是另一种确定计算机上操作系统的更为复杂的方法,但是也可以编写 ISAPI 过滤器来删除或替换此标头。有关如何进行这种操作的信息,请参阅 Developing ISAPI Filters(英文),以及 IIS 程序员指南中的 SF_NOTIFY_SEND_RESPONSE(英文)通知。服务器上运行的基础系统越难辨认,黑客编写的用于在 Internet 上查找某种类型计算机的脚本失败的可能性就越大。
但是操作系统本身并不是唯一的弱点。您创建的 ASP 页在后端执行 SQL 查询并抛出异常时,会执行什么操作?您是否将异常信息返回给用户浏览器?这样不仅指出了 Web 服务器平台,还指出了数据库平台。除此之外,它还可以使用户了解您正在进行的特定 SQL 查询,并为他们提供信息,使其了解如何更改要输入到窗体中的内容以得到他们不应有权访问的信息。
出现其他 COM 异常情况怎么办?如果将异常信息传播给用户,黑客将会知道您的计算机上安装了哪些 COM 组件。如果此 COM 对象是第三方 DLL,则黑客可以得到它的一个副本,并竭尽全力搜索可能存在的所有弱点。这至少使黑客有机会了解服务器上可能存在的问题。
同样,黑客可能会利用触发 COM 异常这一事实来阻塞服务器。黑客意识到多数异常代码路径未经充分测试,且常常是资源泄露或变得更糟的起因。要避免出现这种情况,服务器上的代码应能捕获所有异常情况,并且应该只返回普遍性的错误。对于 XML Web 服务,您应返回几乎不带有平台信息的 SOAP 错误。您可能希望以某种方式将数据连同 ID 一起返回给用户以便将错误与审核日志中的记录进行比较,但是,请将错误详细信息放在审核日志中而不是放在返回的 SOAP 错误中。建议应用程序设计人员创建自己的应用程序的 SOAP 错误架构,同时提供一个非常短的选项列表,并且仅返回此列表上的错误。调用 XML Web 服务的客户端不必知道有关 SQL 查询异常的详细信息,他们只需要知道出现了 SOAP 服务器错误。
如果正在使用 Microsoft® SOAP Toolkit 2.0,可以在 COM 对象上实现
ISoapError 接口以返回您希望返回的确切的 SOAP 错误,而不是一般的工具包错误。一般的工具包错误可以提供大量的、有关错误出现时在服务器上所发生情况的信息。在开发阶段,工具包错误对于调试来说是很有用的,但是它们在产品服务器上不应出现。他们可以为黑客提供大量的、具有潜在破坏性的信息。
XML Web 服务的用户需要知道您的服务所发送和接收的 SOAP 消息的格式,以及您的服务的终点位置。这就足够了。任何其他信息都只会为潜在的黑客提供攻击手段以毁坏您的系统。要进行自我保护,应限制返回与平台有关的信息,并消除计算机上的多余内容,包括删除任何有助于他人识别您的系统的默认虚拟目录或脚本映射。
开发问题
对黑客来说,服务器的脆弱性与服务器上运行的代码质量是成反比的。它包括基础系统(操作系统、Web 服务器和正在使用的 SOAP 工具)的质量,以及为特定应用程序编写的代码的质量。还可能包括服务器上运行的所有其他代码,即使该代码不是应用程序的一部分。但是从开发人员的角度而言,我们希望考虑我们能控制的问题,以及能执行哪些特殊的操作以保证代码的高质量,避免增加 XML Web 服务和服务器上正在运行的其他所有应用程序的脆弱性。
缓冲区溢出
服务器上最可怕的攻击类型是远程用户可以执行恶意代码导致系统完全破坏的攻击。大多数此类攻击都是由于缓冲区溢出错误造成的。这种错误的典型示例是:在 C 代码中为某本地变量分配了固定长度,然后该代码将 HTTP 请求中的信息复制到该变量中。如果您认为请求中的数据不会比您设定的值大,而对您的服务器的恶意请求可以超过该值,并导致其发送的数据在写入到已分配的缓冲区时超出末端。对于本地变量,缓冲区存储在堆栈中,而堆栈中还存储了当前函数结束时要返回的代码地址。通过写入时超出本地变量缓冲区的末端,黑客可以覆盖返回地址并使函数返回到他想要的任何地址,包括 Windows
CreateProcess 函数的地址。要传递到
CreateProcess 函数的参数也会存储在堆栈上,如果黑客覆盖了存储这些参数的位置,则可以有效启动服务器上他们想要启动的任何应用程序。
要避免这类攻击,请不要对从请求中读取的数据做任何假设,然后确保缓冲区的处理代码中没有错误。对于 C/C++ 程序员,应对以下函数格外小心:
strcpy、
strcat、
memcpy、
gets、
sprintf、
scanf 以及所有这些函数的变体(如
lstrcpy、
wcscpy、
CopyMemory 等等)。请注意
strncpy 函数及其他“n”函数只是略好一些,因为在这些方案中长度变量常常是由程序决定的,而且仍有可能覆盖固定长度的缓冲区。“n”函数中的长度参数应根据输出缓冲区的大小而定,而非传入字符串的大小。如果要使用这些函数,请使用“n”版本并从堆中动态分配您的缓冲区以避免可能的堆栈溢出。另外,Microsoft® Visual Studio® .NET C 编译器支持新的 /GS 开关,该开关可使代码不会出现许多常见的缓冲区溢出问题。
利用 .NET 框架和管理代码,可以消除大多数潜在的缓冲区溢出问题。Microsoft 设计 .NET 框架时,意识到了垃圾回收的好处,以及如何消除由传统的缓冲区处理方式引起的问题,所以他们提供了管理代码的能力。必须注意管理代码和非管理代码间的交互问题。但是至少可以在您需要时适当保证应用程序的安全。
检查错误
检查所有调用函数的返回代码。如果正在调用 Win32 API,请确保调用已成功完成。如果正在分配内存,请确保未返回 NULL 值。如果正在进行 COM 调用,特别是正在使用 Microsoft® Visual Basic® 进行调用并且已指定“On Error Resume Next”语句,请确保未出现异常。同样,不要对这类调用的结果做任何假设。
如果正在调用 Win32 安全函数,应特别小心。例如,如果正在调用
ImpersonateLoggedOnUser,应检查返回代码是否存在错误,否则将难以为用户提供较高的安全环境。当您的 Web 应用程序配置为在 IIS 上以“进程内”方式运行时要格外注意这一点,因为代码可能以本地系统帐户运行,这在本地计算机上几乎没有限制。还应注意某些交叉的 COM 调用同样可能在具