我们知道,与传统的Web应用程序不同,Web 2.0应用程序一般都是建立在Ajax和交互式的Web服务之上的,这种技术转变给安全专业人员带来了新的安全挑战。
一、简介
本文为安全专业人员详细介绍了利用Firefox及其插件来剖析Web2.0应用程序的一些方法、工具和技巧。通过阅读本文,您可以了解:
◆Web 2.0 应用程序体系结构及其安全事项。
◆黑客所面临的挑战,如发现隐藏的调用、爬行问题以及Ajax逻辑的发现等。
◆利用Firebug工具寻找XHR调用。
◆利用Chickenfoot插件自动模拟浏览器事件。
◆利用Firebug调试器从安全角度对应用程序进行调试。
◆安全漏洞的系统性检测方法。
二、Web 2.0 应用程序概述
近来流行的Web 2.0指的是采用了SOAP、XML-RPC和REST等XML驱动的新一代的Web应用程序。通过使用Ajax和富 Internet 应用程序(Flash)组件,这些新型的Web应用程序能够为终端用户提供更强大和灵活的用户界面。
这种技术的更替对Web应用程序的总体结构以及客户和服务器之间通信机制产生了很大的影响,同时也带来了许多新的安全挑战。比如,一些新型的蠕虫就是利用客户端AJAX框架来窃取机密信息的。
图1 Web 2.0的体系结构示意图
如图 1 所示,在左边的浏览器进程可以分成下列层次:
◆表示层——HTML/CSS提供了应用程序在浏览器窗口中的总体外观。
◆逻辑处理层——运行在浏览器中的JavaScript使得应用程序可以执行业务逻辑和通信逻辑。AJAX驱动的组件位于最底层。
◆传输层——XMLHttpRequest(XHR)。这个对象使得客户和服务器之间可以通过HTTP(S)进行异步通信并交换XML。
如图 1所示,右边的服务器端组件通常位于防火墙之后的企业基本设施之中,这些组件包括已部署的Web服务以及传统的Web应用程序资源。运行在浏览器上的Ajax资源可以直接跟基于XML的Web 服务进行通信,并且无需刷新页面就能与其交换信息。所有这些通信,对最终用户来说都是透明的,换言之最终用户不会感觉到发生了任何重定向。实际上,“刷新”和“重定向”是第一代Web应用程序逻辑不可分割的一部分。在Web 2.0框架中,通过Ajax极大地减少了对于刷新和重定向的使用。
三、Web 2.0安全审计所面临的挑战
在这种异步的框架中,应用程序没有太多的“刷新”和“重定向”。其结果是,许多可以被攻击者利用的服务器端资源都隐藏起来了。安全专业人员在了解Web2.0应用程序时,需要注意下列三个重要方面:
1. 发现隐藏的调用——这里要强调的是浏览器中已加载的页面生成的XHR驱动的调用。它们使用JavaScript通过HTTP(S)对后端服务器进行调用。
2. 爬行问题——传统的网络爬虫应用程序会在两个方面遇到问题,一是重复浏览器的动作方面,二是在此过程中识别服务器端关键资源方面。如果资源是通过JavaScript利用一个XHR对象进行访问的,那么网络爬虫很可能根本就爬不到它。
3. 逻辑发现——现在,Web应用程序是通过JavaScript进行加载的,所以逻辑和一个特定的事件是密不可分的。每个HTML页面都可能从服务器装载三个或者四个JavaScript资源。 这些文件中的每一个都有许多函数,但是一个事件可能仅仅用到了其中的很小一部分来执行其逻辑。
在审计Web应用程序时,我们需要探索并找到克服这些障碍的方法。对于本文来说,我们将使用Firefox作为我们的浏览器,并设法利用它的插件来应对上述挑战。
四、发现隐藏的调用
Web2.0应用程序可以从服务器装载单个页面,也可在构建最终页面时又多次调用XHR对象。这些调用可以从服务器那里异步请求内容或者JavaScript代码。在这种情况下,我们面临的挑战就是确定所有的XHR调用和从服务器获取的资源。这些信息对于发现所有可能的资源和相应的安全漏洞很有帮助。下面通过一个简单的示例进行说明。
假设我们可以访问一个简单的新闻门户站点来获得当天的商业新闻,该站点位于:
http://example.com/news.aspx
浏览器中的页面截图将类似于图2所示:
图2 一个简单新闻门户页面
对于Web 2.0 应用程序,它们是使用XHR对象对服务器进行Ajax调用。我们可以利用一个工具来找出这些调用,这个工具就是著名的Firebug——它是Firefox浏览器的一个插件,可以用来发现XHR对象调用。
在利用此插件浏览一个页面之前,要确保选中了拦截XHR调用的选项,具体如下图所示:
图3 设置Firebug使其拦截XMLHttpRequest调用
启用拦截XMLHttpRequest调用的选项后,我们就可以浏览前面的页面了,这时就能发现该页面发给服务器的所有XHR对象调用了,具体如图4所示。
图 4 捕获Ajax调用
上面我们可以清楚地看到浏览器利用XHR发送的多个请求。它从服务器加载了AJAX 框架Dojo,并调用了在服务器上的一个资源来取得新闻文章。
http://example.com/ getnews.aspx?date=09262006
如果我们仔细观察此代码的话,我们就会在JavaScript代码中发现以下函数:
function getNews()
{var http; http = new XMLHttpRequest(); http.open("GET", "
getnews.aspx?date=09262006", true); http.onreadystatechange = function()
{ if (http.readyState == 4) {
var response = http.responseText;
document.getElementById("result").innerHTML = response;
} } http.send(null);
}
上面的代码对后端Web服务器进行了一个异步调用,并请求资源 getnews.aspx?Date=09262006。这个页面的内容被放置在生产的HTML页面中标识符为“result”的位置上。这明显是利用XHR对象进行的Ajax调用。
通过这种形式的分析,我们能找出有弱点的内部URL、查询和POST请求。比如,对于上面的例子,参数“date”就容易受到SQL注入攻击。
五、爬行问题和浏览器模拟问题
当进行Web应用程序审计的时候,经常要用到一个重要侦察工具,即web爬虫。web爬虫抓取所有页面并收集所有的HREF(链接)。但是如果这些HREF指向一个利用XHR对象进行Ajax调用的JavaScript函数的话,情况会怎样?很糟糕,Web爬虫可能遗漏这些信息。
在许多情形下,模拟这个环境将变得非常困难。比如,下面是一组简单的链接:
go1
go2
go3
单击链接go1的时候,就会执行getMe()函数,这个函数的代码如下所示。 需要注意的是,这个函数也可以放在一个单独的文件中。
function getMe()
{
var http;
http = new XMLHttpRequest();
http.open("GET", "hi.html", true);
http.onreadystatechange = function()
{
if (http.readyState == 4) {
var response = http.responseText;
document.getElementById("result").innerHTML = response;
}
} http.send(null);
}
上述代码对在服务器上的资源hi.html进行了一个简单的Ajax调用。
那么,我们能够自动模拟这个单击吗?答案是肯定的。一个方法就是使用Firefox插件Chickenfoot,这个插件提供了基于JavaScript的应用程序接口,从而为浏览器提供了一个可编程接口。
通过此Chickenfoot插件,您可以编写简单的JavaScript代码来自动发出浏览器动作。使用该方法,就可以轻松完成爬行web页面之类的简单任务的自动化。举例来说,以下简单脚本将利用onclick事件来“单击”所有的锚。与传统的web爬虫相比,这个插件的优点是所有这些onclick事件都是由后端基于XHR的Ajax调用发出的;而这些Ajax调用是会被网络爬虫所遗漏的,因为网络爬虫会试图解析JavaScript并且收集可能的链接,却无法替换实际的onclick事件。
l=find("link")
for(i=0;ia = document.links[i];test = a.onclick;if(!(test== null)){ var e = document.createEvent("MouseEvents"); e.initMouseEvent("click",true,true,document.defaultView,1,0,0,0, 0,false,false,false,false,0,null); a.dispatchEvent(e); }}
您可以将这个脚本装载到Chickenfoot控制台中,并运行它,如图5所示。
图5 利用Chickenfoot模拟Ajax调用onClick
这样,我们就可以创建JavaScript并从Firefox浏览器内部来审计基于AJAX的应用程序的安全性了。对于Chickenfoot插件,还有其它几个API调用,其中一个比较有用的就是构建爬虫例程的fetch命令。
六、逻辑发现与应用程序解析
为了剖析客户端基于AJAX的应用程序,需要仔细遍历每一事件以确定其处理逻辑。确定整个逻辑的一种方法就是逐行阅读所有代码。但是通常每个事件调用仅涉及文件中的少数几个函数。因此,我们需要一种技术来步入调试运行在浏览器中的有关代码。
这时,有些强大的JavaScript调试器可以达到这一目的,Firebug便是其中之一。另一个调试器是venkman。在下面的例子中,我们将使用Firebug。
这里给出一个处理登录过程的简单的示例:login.html页面将从最终用户那里接收用户名和口令,如图6所示。使用Firebug的检查功能可以确定此表单的属性。
图6 借助 Firebug审查表单属性
检查表单属性之后,就会看到一个对auth函数的调用。我们现在可以通过Firebug的调试器功能把内部逻辑跟特定的事件隔离开来了,如图7所示。
图7 使用Firebug进行调试
这个页面的所有JavaScript依赖项都可以查看到。然后,调用ajaxlib.js和validation.js脚本。这两个脚本可能具有若干函数,我们可以通过登录过程用到的一些函数来进行推测。 我们可以使用断点来步入调试整个应用程序。设置一个断点后,我们可以输入证书信息,单击“Submit”按钮,并控制执行过程。在我们的例子中,在函数auth内设置了一个断点,如图8所示。
图8 利用断点控制执行过程
现在,我们就可以通过单击“step in”按钮来进行步入调试了,如图8所示。JavaScript的控制权转移至另一个位于validation.js文件中的函数userval,如图9所示。
图9 移动到 vali页面dation.js脚本
上图显示了用于验证用户名字段的正则表达式模式。一旦完成此验证任务,控制权会传递给另一个函数callGetMethod,如图10所示。
图10 进行Ajax调用
最后,运行序列结束时,我们能监视到XHR对象对后端Web服务的调用,如图11所示。
图11 Firebug控制台中的Web服务调用
这样我们就确定出用于此后端Web服务的资源位置,如下所示:
http://example.com/2/auth/ws/login.asmx/getSecurityToken?username=amish&password=amish
很明显,上面的资源是一些运行在.NET framework之下的Web服务。经过上面一番剖析之后,我们发现了一个可以轻松地绕过的用户验证例程。对于此Web应用程序来说,这是一个潜在的安全威胁。
经过以上测试可以发现,利用一个WSDL文件并对此服务进行蛮力攻击就可以访问该web服务及其终端。此外,我们还可以利用wsChess之类的工具来发动各种形式的注射式攻击(SQL或者XPATH注射)。
对本例而言,此应用程序容易受到XPath注射的攻击,不过针对这种攻击的讨论超出了本文的范围。以上可以看出,这种逐步的方法有助于识别一些客户端攻击,例如XSS、DOM操纵攻击、客户端安全措施旁路、执行恶意Ajax代码,等等。
七、结束语
面向服务的体系结构(SOA)、Ajax、富 Internet 应用程序(RIA)和Web 服务已经成为了新一代Web应用程序的关键部件。为了跟上这些技术的步伐并应对下一代应用程序安全性挑战,我们需要设计和开发不同的方法和工具。审计应用程序的有效方法之一就是有效地利用浏览器。
在本文中,我们介绍了三种针对Web2.0应用程序的审计方法,通过这些方法,我们可以寻找并隔离一些有关Ajax的安全漏洞。浏览器自动脚本不仅可以加速我们的分析过程,而且还能帮助我们发现有弱点的服务器端资源。
下一代应用程序广泛使用了JavaScript。得心应手的调试工具是我们的穿着明亮盔甲的骑士。当您打算使用Firefox对Web 2.0进行安全审计时,本文中介绍的技术将是一个不错的起点。