警报函数劫持
在测试网站的跨站脚本(XSS)漏洞时,如果遇到包含大量输入字段或输入内容在全站重复显示的页面,我通常使用带有输入名称或其他唯一标识符的警报框。这样当警报弹出时,我就能知道来源并将输入与输出对应起来。
在最近的一次测试中,我遇到了一个问题。在一个页面上,出现了与用户名字段相关的警报,但该页面上至少有八个用户名副本。在传统的HTML页面上,我只需查看源代码就能找出是哪个触发了警报,但这是一个"现代"页面,HTML仅作为模板,所有内容都是通过一些非常晦涩的JavaScript加载到DOM中的。所有名称似乎都正确编码,并完整显示,注入的内容也可见,但显然某个地方出了问题。
我的第一反应是偷懒,告诉开发人员页面存在XSS,让他们自己去找出是哪个字段的问题。但我不喜欢这样做,我宁愿尽可能多地提供问题的信息。
在思考过程中,我想起了观看Natalie Silvanovich的《ECMA与Chakra》演讲。Natalie在演讲中谈到了各种高级JavaScript技术,但她提醒我的一件更基本的事情是:JavaScript中的所有内容都可以被重写,甚至是内置函数。那么,为什么不用自己的函数覆盖alert函数呢?这有什么用呢?如果将其与debugger函数结合使用,我可以在调用alert时让代码暂停,然后通过查看调用堆栈来确定位置。
该函数如下:
|
|
我添加了输出,以防debugger调用因某种原因失败,这样至少能在过程中捕获日志。
如果你想知道如何注入新的alert函数,这部分很简单:Burp和ZAP都允许你拦截页面响应和请求。在代理中启用响应拦截,在页面开头添加自定义函数,以便在其他任何内容运行之前注入,然后让自然发展。一旦XSS触发,alert函数被调用,debugger函数触发断点,通过检查调用堆栈,很容易看出八个实例中哪个是易受攻击的。
在Chrome中的效果如下。断点由debugger调用触发:
然后向上查看调用堆栈,看看alert是在哪里触发的:
如你所见,恶意用户名被写入ID为latest_3的元素中。
查看页面源代码,可以看到最新内容字段是易受攻击的。
通常我在Firefox中进行测试,但这次我测试了Burp内置的新Chrome浏览器。结果我很幸运,因为当我尝试在Firefox中为这篇文章截取一些截图时,我发现Firefox只能追溯到onerror调用,而不能一直追溯到将内容添加到页面的innerHTML。
这是debugger调用触发断点的地方:
调用堆栈的顶部是alert函数:
因此,这是一个相当酷的小技巧,可以为客户提供更多关于其漏洞的信息。如果你想尝试,请确保使用Chrome。
如果你想尝试一下看看它有多容易工作,我创建了Alert Lab,一个简单的单页面应用程序,其中有一个神秘的XSS警报,你可以使用这种技术来追踪。
在有人提出"你本可以更改用户名"之前,我无法这样做,为了这个描述我过度简化了问题,原始测试中有很多限制且时间有限。这个技巧花了我几分钟时间,正好得到了我需要的东西。