Data Exfiltration via CSS + SVG Font
本文将展示如何利用SVG字体和CSS来读取页面的文本内容。
目前已有多种已知的通过CSS读取页面文本内容的方法。这些已知技术在Juan Manuel Fernández的以下文章中已有详尽的阐述: CSS Injection Primitives :: DoomsDay Vault
在某些情况下,这些技术对攻击者非常有用。例如,当用户输入被严格过滤、只能使用有限的HTML标签时,或者由于内容安全策略(CSP)的限制而无法执行JavaScript时。
我今天要介绍的技术便是其中之一。其基本思路与Michał Bentkowski提出的字体连字技巧相同。 Stealing Data in Great style – How to Use CSS to Attack Web Application. - research.securitum.com
我的方法与之大体相同,但我未曾见过任何文章提及我接下来要介绍的这种技术。我认为它值得被提及,因为在我将要解释的特定情境下(例如当Michał的技术因CSP限制而无法使用时),它会非常有用,所以我写了这篇文章。
在我日语的博客文章中,我曾详细解释过Michał的技巧。不过阅读本文的读者应该懂英文,所以请先阅读他的文章 :)
好了,你已经读完了,对吧?从他的文章中你了解到,他使用了从SVG字体转换而来的WOFF字体。而在我的技巧中,我直接使用SVG字体而不进行转换。Michał曾提到"浏览器已经停止支持字体中的SVG格式(因此需要使用WOFF格式)",但事实上,Safari仍然支持它。
归根结底,我要介绍的技巧只不过是将他的技巧替换为SVG字体。然而,我仍然想要介绍这个技巧的原因是,即使字体加载被CSP策略阻止,SVG字体依然可以使用。也就是说,即使在CSP禁止加载字体的页面上,SVG字体也允许读取文本内容。这是因为SVG字体不仅可以像WOFF字体那样从URL加载,其所有字体组件都可以以内联方式定义,无需从URL加载。
让我们看看如何替换Michał的技巧。
在他的技巧中,WOFF字体通过<style>中的@font-face加载。
|
|
这个样式可以用以下内联SVG替换。
|
|
现在,如果通过CSS将font-family属性设置为"hack",那么这个SVG字体将应用于SVG外部的目标文本。即使CSP设置了font-src 'none',这也不会被阻止。(注意,为了观察泄漏的数据,此技巧与Michał的技巧一样,同样使用了背景图片请求。因此,至少需要在img-src指令中允许可以观察到请求的主机。)
我将向你展示概念验证(PoC)。假设存在如下漏洞页面:
https://vulnerabledoma.in/svg_font/xss.html?xss=%3Cs%3EXSS%3Cscript%3Ealert(1)%3C/script%3E
|
|
我将展示SVG字体如何泄露"secret"变量。
你可以在Safari中打开以下URL并点击"Go"按钮来复现。
PoC: https://l0.cm/svg_font/poc.php
完整代码可以在以下地址找到:https://github.com/masatokinugawa/css-exfiltration-svg-font
如果PoC正确运行,如下方视频所示,多个新窗口将会打开。等待一段时间后,secret变量的字符串将会一点一点地显示在包含"Go"按钮的页面上,例如"573b …"。
除了使用SVG字体外,它与Michał的PoC几乎相同,但有一些改动。在他的PoC中,他将目标页面加载到iframe中,但在我的PoC中,我使用了window.open()来代替。这是因为Safari现在默认阻止所有第三方Cookie,我认为在Safari中使用iframe进行攻击的PoC不太现实。同时,我改变了传递数据的方式。同样,由于第三方Cookie被阻止,加载背景图片时无法设置Cookie,因此我改用URL参数传递会话ID。
顺便说一下,如果你习惯使用Chrome,你可能会好奇为什么一次点击会打开多个新窗口。这是因为Safari虽然有弹窗拦截器,但对于一次点击能打开的窗口数量没有限制。得益于此,可以利用多个窗口高效地尝试读取数据。
就是这样。感谢阅读!希望这篇文章对你有帮助。