65.9K
CodeProject 正在变化。 阅读更多。
Home

应用程序错误处理:如何避免“千刀万剐”

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.90/5 (7投票s)

2006年8月31日

CPOL

9分钟阅读

viewsIcon

22768

了解创建错误消息时应遵循的最佳实践,包括应考虑的重要指南。

引言

当应用程序因用户输入或内部功能而发生错误时,我们作为尽职尽责的开发人员,希望呈现一条错误消息,以帮助最终用户纠正问题。然而,在错误处理方法上“过度帮助”也是可能的。通过向用户提供过于详细的应用程序错误消息,实际上可能会让您的网站暴露给黑客。黑客花费大部分时间对网站进行侦察,缓慢地收集多条信息,以确定网站的漏洞。有时,应用程序错误消息中看似无害的一条信息,可能正是攻击者发起毁灭性攻击所需的最后一块拼图。

用户输入错误

在应用程序错误消息中提供过多信息的典型例子是登录屏幕上的身份验证失败消息。乍一看,使用一种错误处理方法,该方法显示一条明确的消息,表明输入的用户名未找到,而不是密码不正确,这似乎很有帮助。事实上,这确实有帮助——但对攻击者比对合法用户更有帮助。

想象一下,一名攻击者正试图闯入一个 Web 应用程序。他不知道该网站上任何现有的用户名或密码,因此他尝试进行“暴力破解”或“字典攻击”。将常见的用户名列表(如 admin、user 和 guest)与常见的密码列表(如 password、admin 和 Elvis)配对。尝试所有可能的组合,看看是否有任何组合有效。如果使用大小显著的列表,例如实际的电子词典,则可能的组合数量可能达到数十亿。即使使用自动化工具进行请求,也可能需要数周或数月才能找到匹配项。

然而,如果网站的错误处理过程提供区分无效用户名和无效密码的明确消息,那么攻击者的工作就大大简化了。一旦他遇到显示“密码无效”应用程序错误消息的用户名/密码组合,他就可以停止检查列表中的其他用户名。他现在知道猜测的用户名存在于系统中,并且可以专注于破解该帐户。如果他的潜在用户和密码列表都包含 5000 个项目,那么他的任务现在就从进行 2500 万次请求减少到更易于管理的 5000 次请求。在几小时内就可以完成 5000 次请求,而不是几周,这意味着攻击者在网站管理员注意到异常行为之前,更有可能获得对网站的访问权限。

用户错误最佳实践

在这种情况下,开发人员在处理错误时最好的做法是创建一个通用的应用程序错误消息,无论用户名是否未找到还是密码不正确,都显示此消息。一个好的例子是:“用户名或密码无效”。这条错误处理消息足够有用,可以告知合法用户他需要重新输入登录凭据,同时不提供任何可能帮助攻击者进行暴力破解攻击的额外信息。

内部错误

正如我们所见,在制定面向用户的错误处理程序时,不要提供过多细节非常重要。当应用程序本身发生错误时,更重要的是隐藏细节。发生这种情况的原因有很多:可能缺少必需的数据库或 Web 服务;组件许可证可能已过期;甚至可能是代码中的一个 bug。无论原因是什么,绝不能向用户透露应用程序错误的具体细节。

攻击者靠细节为生。允许显示详细的组件错误(例如数据库错误)可能会使攻击者能够确定使用的数据库类型、其版本、数据库运行的操作系统、使用的 Web 服务器,甚至可能是 Web 应用程序的源代码。所有这些数据都是攻击者可以用来攻击网站的弹药。例如,如果错误处理方法允许攻击者发现使用的数据库是 Microsoft SQL Server 2000,他接下来的第一件事就是搜索互联网上 Microsoft SQL Server 2000 中已知的安全漏洞。一些应用程序错误消息甚至会显示受影响文件的完整或部分路径,或表中受影响行或列的名称,试图帮助用户追踪问题的根源。这种形式的应用程序错误处理将为攻击者提供更多可用于恶意目的的信息。

许多网站试图防止信息泄露,同时还试图通过显示友好的应用程序错误消息并嵌入组件错误代码来为用户提供帮助。例如:“发生错误。请联系技术支持并参考错误代码 123-456-789”。然而,这种错误处理方法与之前的方法相比并没有好多少,原因也相同。攻击者将简单地搜索“123-456-789”。很可能应用程序错误代码的文档存在于互联网上的某个地方,如果存在,攻击者就会找到并使用它。

自定义错误代码

一些 Web 应用程序创建自己的内部错误代码,作为错误处理过程的一部分显示给用户。例如,如果数据库层发生任何应用程序错误,它们会显示一条消息,如“请联系技术支持并参考错误代码 01”。如果许可组件发生任何应用程序错误,消息会更改为“参考错误代码 02”。这种错误处理方法确实比以前的方法提供了一定程度的安全性,因为内部代码的含义不会在互联网搜索中找到。不幸的是,这种形式的错误处理仍然不安全。

在这种情况下,安全缺陷在于应用程序错误的独特性,而不是其内容。就像前面讨论的错误处理方法一样,攻击者利用了无效用户响应和无效密码响应之间的差异;一个聪明的攻击者会注意到他的一些攻击返回错误代码“01”,而另一些攻击返回错误代码“02”。虽然这种错误处理方法没有提供太多信息,但可能足以帮助他发起成功的攻击。此外,这也不是合法用户真正需要的信息。

千刀万剐

即使通过错误处理发生少量数据泄露,也可能极其危险。很少有单个错误消息包含攻击者能够利用系统所需的所有信息。与其说是一次致命的“银弹”,不如说是一种更常见的攻击,即“千刀万剐”。正是由于不当的应用程序错误处理提供的许多微小个体信息累积起来,才使攻击者获得足够的知识来成功利用系统的安全漏洞。

内部错误最佳实践

当然,一个解决方案是显示一个非常通用的“发生错误”消息,以应对系统中可能发生的任何问题。应用程序错误消息没有任何细节,也没有独特性。攻击者无法利用任何信息。虽然这种错误处理方法非常安全,但对开发人员或技术支持人员来说帮助不大。如果用户遇到应用程序错误,他将无法向应用程序所有者提供任何有用的信息来帮助重现或调试问题。

提供安全性和功能性最佳组合的错误处理方法是问题跟踪技术。每当发生应用程序错误时,都会详细记录错误状况。此日志被分配一个唯一的 issue ID,并安全地存储在服务器上的某个位置,例如无法通过 Web 浏览器访问的数据库或目录。返回给用户的错误消息包含 issue ID。用户可以向技术支持报告 issue ID,技术支持可以从服务器的安全位置引用详细日志。这种错误处理方法为应用程序所有者提供了详细信息,同时将其从用户和任何潜在攻击者手中隐藏起来。

问题跟踪也满足了错误不因应用程序错误类型而异的条件。每个错误处理消息都是唯一的,因为每个错误都会有一个唯一的跟踪 ID。然而,由于无法从响应中辨别出任何模式,因此此技术与为任何错误情况提供完全相同的错误消息一样安全。为了在错误处理期间提供额外的安全措施,请使用完全随机的数字或全局唯一标识符 (GUID) 作为问题跟踪 ID,而不是顺序编号。这将阻止攻击者通过联系技术支持并提供容易猜测的跟踪号码来发起“社会工程”攻击。

结论:一个简单的解决方案

在应用程序错误发生时,确定向用户提供正确反馈量可能很困难。如果开发人员试图在错误处理方法上尽可能提供帮助,这可能会适得其反,因为对用户有用的信息也可能帮助攻击者攻击系统。另一方面,如果开发人员过于含糊,那么修复应用程序错误就会困难得多,因为用户将没有任何数据可以提供给开发人员或技术支持团队。

作为一个简单的解决方案,在创建应用程序错误消息时,请遵循以下指南:

  • 当应用程序错误仅由无效用户输入引起时,例如密码无效,则应用程序应显示通用且非独特的错误消息。
  • 当错误发生在应用程序代码中时,例如数据库错误,则应用程序应提供包含跟踪号的通用消息。跟踪号随后可供技术支持人员用于帮助解决问题。

遵循这些指南,您可以挫败攻击者试图通过其错误处理消息来获取您的应用程序信息的企图。

© . All rights reserved.