正在阅读:利用 ASP.NET 的内置功能抵御 Web 攻击利用 ASP.NET 的内置功能抵御 Web 攻击

2005-06-25 10:11 出处: 作者:Dino Esposito&Wintellect 责任编辑:moningfeng


三、ViewStateUserKey
  从 ASP.NET 1.1 开始引入,ViewStateUserKey 是 Page 类的一个字符串属性,只有很少数开发人员真正熟悉该属性。为什么呢?让我们看看文档中是怎么说的。

  在与当前页相关联的视图状态变量中将一个标识符分配给单个用户

  除了有些累赘,这个句子的意思相当清楚;但是,您能老老实实地告诉我,它说明了该属性原本的用途吗?要理解 ViewStateUserKey 的角色,您需要继续往下读,直到 Remarks 部分。

  该属性有助于防止一次单击攻击,因为它提供了附加的输入以创建防止视图状态被篡改的哈希值。换句话说,ViewStateUserKey 使得黑客使用客户端视图状态的内容来准备针对站点的恶意张贴困难了许多。可以为该属性分配任何非空的字符串,但最好是会话 ID 或用户的 ID。为了更好地理解这个属性的重要性,下面我们简短介绍一下一次单击攻击的基本知识。

  一次单击攻击包括将恶意的 HTTP 表单张贴到已知的、易受攻击的 Web 站点。之所以称为“一次单击”,是因为它通常是以受害者不经意的单击通过电子邮件发送的或者在拥挤的论坛中浏览时发现的诱惑性链接而开始的。通过点击该链接,用户无意中触发了一个远程进程,最终导致将恶意的<form>提交到一个站点。大家都坦白些吧:您真能告诉我,您从未因为好奇而单击过 Click here to win $1,000,000 这样的链接吗?显然,并没有什么糟糕的事情发生在您身上。让我们假定的确是这样的;您能说 Web 社区中的所有其他人都幸免于难了吗?谁知道呢。

  要想成功,一次单击攻击需要特定的背景条件:

  1.攻击者必须充分了解该有漏洞的站点。这是可能的,因为攻击者可以“勤奋地”研究该文件,或者他/她是一位愤怒的内部人员(例如,被解雇而又不诚实的雇员)。因此,这种攻击的后果可能是极其严重的。

  2.站点必须是使用 Cookie(如果是持续性 Cookie,效果更好)来实现单次登录,而攻击者曾经收到过有效的身份验证 cookie。

  3.该站点的某些用户进行了敏感的事务。

  4.攻击者必须能够访问目标页。

  前已提及,攻击包括将恶意的 HTTP 表单提交到等待表单的页。可以推知,该页将使用张贴来的数据执行某些敏感操作。可想而知,攻击者清楚地了解如何使用各个域,并可以想出一些虚假的值来达到他的目的。这通常是目标特定的攻击,而且由于它所建立的三角关系,很难追本溯源 — 即黑客诱使受害者单击该黑客站点上的一个链接,而这又会导致恶意代码被张贴到第三个站点。(请参阅图 1。)



图 1. 一次单击攻击


  为什么是不抱怀疑的受害者?这是因为,这种情况下,服务器日志中所显示的发出恶意请求的 IP 地址,是该受害者的 IP 地址。如前所述,这种工具并不像“经典”的 XSS 一样常见(和易于发起);但是,它的性质决定了它的后果可能是灾难性。如何应对它?下面,我们审视一下这种攻击在 ASP.NET 环境下的工作机理。

  除非操作编码在 Page_Load 事件中,否则 ASP.NET 页根本不可能在回发事件之外执行敏感代码。要使回发事件发生,视图状态域是必需的。请牢记,ASP.NET 会检查请求的回发状态,并根据是否存在 _VIEWSTATE 输入域,相应地设置 IsPostBack。因此,无论谁要向 ASP.NET 页发送虚假请求,都必须提供一个有效的视图状态域。

  一次单击攻击要想得手,黑客必须能够访问该页。此时,有远见的黑客会在本地保存该页。这样,他/她就可以访问 _VIEWSTATE 域并使用该域,用旧的视图状态和其他域中的恶意值创建请求。问题是,这能行吗?

  为什么不能?如果攻击者可以提供有效的身份验证 cookie,黑客就可以进入,请求将被照常处理。服务器上根本不会检查视图状态内容(当 EnableViewStataMac 为 off 时),或者只会检查是否被篡改过。默认情况下,试图状态中没有机制可以将该内容与特定的用户关联起来。攻击者可以轻松地重用所获取的视图状态,冒充另一个用户合法地访问该页,以生成虚假请求。这正是 ViewStateUserKey 介入的地方。

  如果选择准确,该属性可以将用户特定的信息添加到视图状态。处理请求时,ASP.NET 会从视图状态中提取秘钥,并将其与正在运行的页的 ViewStateUserKey 进行比较。如果两者匹配,请求将被认为是合法的;否则将引发异常。对于该属性,什么值是有效的?

  为所有用户将 ViewStateUserKey 设置为常量字符串,相当于将它保留为空。您必须将它设置为对各个用户都不同的值 — 用户 ID,会话 ID 更好些。由于一些技术和社会原因,会话 ID 更为合适,因为会话 ID 不可预测,会超时失效,并且对于每个用户都是不同的。

  以下是一些在您的所有页中都必不可少的代码:

void Page_Init (object sender, EventArgs e) {
ViewStateUserKey = Session.SessionID;
:
}



  为了避免重复编写这些代码,您可以将它们固定在从 Page 派生的类的 OnInit 虚拟方法中。(请注意,您必须在 Page.Init 事件中设置此属性。)

protected override OnInit(EventArgs e) {
base.OnInit(e);
ViewStateUserKey = Session.SessionID;
}



  总体说来,使用基 page 类始终都不失为一件好事,我在 Build Your ASP.NET Pages on a Richer Bedrock 一文中已经进行了说明。如果您要了解更多有关一次单击攻击者的伎俩的信息,可以在 aspnetpro.com 找到一篇非常好的文章。

键盘也能翻页,试试“← →”键

关注我们

最新资讯离线随时看 聊天吐槽赢奖品