这篇文章总结了我对处理复制和粘贴问题的研究:浏览器、流行的所见即所得编辑器和网站。其主要目标是提高人们对以下情况可能使用户面临攻击的认识:
在接下来的几节中,我将解释如何识别和利用这些问题。
我不是第一个承保与复制和粘贴相关的安全风险的人。2015年,伟大的马里奥·海德里奇(Mario Heiderich)就这个话题做了一场名为“复制与害虫”(Copy&;Pest)的演讲。Mario专注于从非浏览器应用程序(如LibreOffice或MS Word)复制数据和在浏览器中粘贴数据,并展示了这可能导致XSS。
XSS不是处理剪贴板数据的唯一问题;渗出是另一个风险,
即使浏览器不会出现此类错误,JavaScript WYSIWYG编辑器仍可能引入安全问题。
最后,我认为包括在两个浏览器选项卡之间复制和粘贴的攻击方案比从外部应用程序复制并粘贴到浏览器中更有可能被利用。
在这篇文章中,我将解释浏览器中的4个安全问题和富编辑器中的5个漏洞,我总共获得了超过3万美元的赏金。
复制和粘贴是在两个应用程序之间共享数据的最常见的用户交互之一。剪贴板可以包含各种类型的数据,例如:
在本文中,我将重点介绍格式化文本,因为它等同于浏览器世界中的HTML标记。这意味着如果您复制以下文本:“hello here”,则剪贴板将包含HTML内容:Hello<;b>;here<;/b。
有趣的是,浏览器公开了允许您从JavaScript代码设置任意剪贴板内容的API。考虑以下示例:
为了确保阻止浏览器复制的标准行为,并且剪贴板只用clipboardData.setData的第二个参数填充,需要调用event.prevenentDefault()。
这里明显的攻击载体是将XSS有效负载放到剪贴板中的能力:
浏览器供应商完全了解此攻击场景。作为一种预防方法,他们在粘贴时引入了内容清理;即删除被认为有害的元素和属性。
我已经创建了一个名为“Copy&;Paste Playround”的简单网站,以简化在浏览器中查找清理错误的过程。
在左侧,您可以输入HTML标记,并查看浏览器生成的DOM树。然后,单击“复制为HTML”后,您输入的确切HTML将复制到剪贴板。
另一方面,右侧包含一个丰富的编辑器(或所见即所得编辑器),您可以在其中从剪贴板粘贴。编辑器的内容还显示了DOM树,这样就可以很容易地与左侧进行比较,找出浏览器是如何清理HTML的。
在图1的示例中:首先,我在HTML输入字段中输入了以下XSS有效负载:<;img src=1onerror=alert(1)>;;其次,我单击“copy as HTML”;最后,我将其粘贴到粘贴目标中。通过DOM树的视图,可以很容易地看到浏览器在粘贴之后去掉了onerror属性。您还可以使用“复制和粘贴操场”通过复制和粘贴外部页面来测试XSS问题;首先从操场复制任意HTML,然后将其粘贴到外部页面(甚至外部应用程序)。
考虑到浏览器在决定是否应该清理任何HTML元素或属性之后必须采用一些逻辑,我决定看一看它们,并尝试找到旁路。结果,我发现在所有主流浏览器中至少有一个绕过了杀菌器:Chrome、Firefox、Safari和经典的Edge。
在本节中,我将详细描述我确定的一些剪贴板消毒器问题。
我发现的第一个bug是一个通用的xss,修复于Chromium 79(crbug.com/1011950)。在粘贴带有<;div>;元素的HTML代码时,我注意到一个有趣的特性。粘贴后创建的DOM树取决于粘贴发生的确切位置。考虑一下简单的HTML代码片段:
这是意料之中的,因为生成的HTML与复制到剪贴板的HTML相同。但是,如果将代码段粘贴到1234的中间,则会呈现不同的HTML:
这种行为似乎不同寻常:粘贴的内容中完全省略了<;div>;元素,而在<;div>;通常应该结束的位置,出现了<;br>;标记。对于任何具有CSS RULE:DISPLAY:BLOCK的HTML元素,都会观察到相同的行为。这看起来真的很有希望,因为我们看到的是一种突变。如果说浏览器的历史告诉我们什么的话,那就是突变往往会导致漏洞。
经过一些调查,<;数学>;元素被证明是有用的。它通常可以方便地绕过各种杀毒程序,因为它引入了所谓的“外来内容”,并且当它是<;ath>;元素的后代时,某些标记的解析方式与HTML的任何其他部分都不同。
让我们来看一个简单的例子。在<;style>;元素的HTML分析中,不能生成除文本节点以外的任何子元素。例如,以下标记:
结论是<;style>;中的内容被视为文本。但是,如果<;style>;元素成为<;数学>;元素的后代,则解析会发生巨大变化。以下代码。
在这种情况下,<;style>;元素可以具有子元素。在某些情况下,这种差异可能会导致跨站点脚本(例如绕过我的DOMPurify)。
DOM树看起来很安全:<;img>;元素在title属性中,因此不会呈现它。尽管如此,在删除<;ath>;元素之后,解析HTML代码会产生一个不同的DOM树:
XSS有效负载作为<;/style>;结束标记(最初放在title属性中)执行,现在关闭<;style>;元素,因为没有引入外来内容。
回到Copy&;Paste,我想知道当剪贴板内容包含一个<;Math>;元素(该元素包含style=display:block的子元素)时,会发生什么情况,因为我知道后者会导致粘贴时发生变化。我创建了以下代码片段:
(附注:所有元素都有一个文本节点,因为如果没有文本,Chromium往往会在粘贴后完全省略HTML元素)。
然后,我将其粘贴到一个富编辑器的中间,该编辑器只包含一个内容为:";1234";的文本节点。粘贴后的DOM树为:
请注意,";test&34;字符串最初位于<;XSS&>元素内(扩展为<;MATH&>元素),在突变后放在<;MATH&>;之外。
在将其粘贴到富编辑器的中间之后,它创建了以下DOM树:
突变后,<;img>;元素从title属性中“逃脱”并被放入DOM树中,而不进行任何清理。为了证明Chromium安全团队利用该漏洞有效,我向他们提供了以下视频,显示我可以在Gmail、维基百科和博客上触发XSS。
当我向Chromium报告通用XSS时,我附带提到了滥用剪贴板的另一种方式是注入<;style>;元素以泄露页面数据(例如:CSRF令牌或用户的个人信息)。对原始问题的修复并不能解决这个问题,因此谷歌员工创建了另一个问题(crbug/1017871)来确定注入css是否存在安全风险。
滥用样式表从网站泄露数据并不是什么新鲜事。例如,2018年Pepe Vila展示了一个单一的注射点就足以从CSS泄露数据,同样的技巧后来在2019年被d0ut重新发现。今年年初,我还写了一篇关于通过单一注入点在Firefox中渗出CSS数据的文章(尽管文章标题明确提到了Firefox,但同样的代码也适用于Chromium)。
因此,我的工作是说服Chromium安全人员,通过复制和粘贴注入样式确实有安全隐患。我用下面的视频证明了Gmail中当前登录用户的电子邮件地址是可以泄露的。
如果您希望弄清利用漏洞的确切工作原理,请参阅有关通过单个注入点的数据外泄的文章。对于这个漏洞,谷歌决定悬赏1万美元。
我向Chromium报告了另外两个复制和粘贴错误(crbug/1040755和crbug/1065761),一个是Safari,另一个是经典的Edge。然而,所有这些错误都非常相似,考虑到并不是所有的错误都得到了修复或解除限制,我决定暂时不透露它们。
然而,我完全可以透露另外两个bug,它们发生在Firefox中:CVE-2019-17016和CVE-2019-17022。这两个版本都在2020年1月7日发布的Firefox72中得到了修复。
Firefox允许从剪贴板粘贴样式表。例如,如果我们复制以下HTML:
然后,在粘贴时,Firefox不会更改它;也就是说,背景立即变为黄色。请务必注意,粘贴的内容中不允许使用某些CSS规则,因此会将其删除。@import就是一个例子,它对于任何实际的CSS泄漏攻击都是必需的。
我们再一次处理突变,但这一次是样式表突变。Firefox CSS Saniizer检查样式表是否包含任何需要清理的规则。如果是,则删除有问题的规则并重写整个样式表。否则,样式表将被逐字粘贴。这创建了一个新的攻击面,因为重写样式表可能会引入新的、意想不到的规则。
我注意到Firefox错误地处理了相当模糊的CSS特性,即@Namespace at-Rule。根据MDN的说法:“@NAMESPACE规则通常只在处理包含多个名称空间的文档时才有用--比如具有内联SVG或MathML的HTML5,或者混合了多个词汇表的XML”。
从剪贴板复制并粘贴后,它被变形为以下形式:
因为单引号被双引号取代,所以很自然地会检查当您将双引号放入URL中时会发生什么。
Firefox错误地重写了这个样式表,并且没有正确地转义双引号字符:
这使得在样式表中包含任意规则成为可能。证明我可以在样式表中包含我自己的@import规则的最终有效负载如下:
乍一看,@import似乎会被忽略,因为它不是样式表中的第一个规则(CSS规范要求),但它会被处理,因为@NAMESPACE规则无效(因为多余的x)并且被解析器忽略。
为了向Mozilla证明利用漏洞确实有效,我创建了一个视频,该视频泄漏了一个示例页面中的CSRF令牌。请参考关于通过Firefox中的单个注入点使用CSS窃取数据的文章,了解利用漏洞的确切情况。
此外,我向火狐报告了另一个问题,跟踪为cve-2019-17022,它向火狐引入了一个突变的xss。
这个问题的根本原因与上一个问题完全相同,但这一次被利用的方式有所不同。
请注意<;\/style>;如何转换为<;/style>;。这本身不会引入安全问题,因为样式表的文本节点是直接修改的,因此内部的<;/style>;不会结束标记。但是,如果该网站执行类似以下操作:
那么它就容易受到XSS的攻击,因为<;img>;元素会离开<;style>;元素。我假设某些所见即所得编辑器可能会这样做,因为本质上将一个元素的innerHTML分配给另一个元素应该是无害的。此外,某些所见即所得编辑器允许浏览器处理剪贴板内容,然后在对其进行预清理后对其执行一些转换。
我查看了名为awawed-wysiwyg的gihub repo,看看Firefox的行为是否让任何编辑器容易受到攻击。搜索时间并不长,因为自上而下的第一个编辑:Aloha Editor碰巧易受攻击。粘贴上述有效负载后,XSS立即触发。
粘贴时,剪贴板内容将粘贴到元素中,然后通过删除某些元素的handleContent函数进行处理:
handleContent:function(Content){var$content;if(typeof content=';string';){$content=$(';<;div>;';+content+';<;/div>;';);}false if(content instanceof$){$content=$(';<;div>;';).append。}return$content.html();}。
当内容变量(包含浏览器预先清理的HTML)用作jQuery$函数中的参数时,会触发突变XSS。此时,内容包含:
Aloha Editor并不是唯一可能触发突变XSS的编辑器。我把它作为一种练习留给读者去寻找其他人。
现在,让我们假设我们生活在一个完美的世界中,在这个世界中,浏览器修复了所有的消毒器绕过,并且不再存在。这是否意味着当我们从不受信任的网站粘贴数据时,我们是安全的?简短的答案是:不。
JavaScript代码可以完全忽略浏览器的清理过程,并手动处理它。这种方法需要监听Paste事件,例如:
addEventListener(';粘贴';,Event=>;{Event.PrevenentDefault();const html=event.clipboardData.getData(';text/html';);//处理HTML.。//.。例如,某些Element.innerHTML=html;//😱});
在代码片段中,剪贴板内容被分配给html变量,而html变量又被分配给元素的innerHTML,从而导致XSS。
基本上每个流行的WYSIWYG编辑器都会自己处理Paste事件。这样做有几个原因:
在接下来的几节中,我将介绍几个网站和流行的所见即所得编辑器错误处理剪贴板内容的真实示例。
TinyMCE自称是“最先进的所见即所得HTML编辑器”,根据我的经验,它确实是最受欢迎的编辑器之一(如果不是最受欢迎的)。
在粘贴时,TinyMCE通过解析HTML、应用一些转换,然后将其序列化为HTML来处理内容。TinyMCE不使用JavaScript中提供的任何HTML解析器(如DOMParser),但采用了自己的解决方案。
作为TinyMCE清理的示例,请考虑从剪贴板粘贴以下HTML代码段:
然后,它决定<;b>;元素应该替换为<;strong>;,并且注释应该保持不变。然后将DOM树序列化为:
到目前一切尚好。TinyMCE的解析器的问题在于它无法识别HTML5中--!>;是有效的注释结尾。因此,以下HTML:
由于编辑器假设树是无害的,因此将其序列化为相同的形式:
并将其分配给outterHTML。赋值之后,轮到浏览器解析HTML,并且它的操作方式有所不同:
我向TinyMCE报告了这个漏洞(以及其他几个漏洞),他们发布了两个安全建议:
如果您是使用TinyMCE的应用程序开发人员,请确保将其更新到版本5.2.2或更高版本。
CKEditor 4是另一个非常受欢迎的WYSIWYG编辑器,它将自己标榜为“功能最多的排名第一的富文本编辑器”。
CKEditor有一个有趣的概念,即在复制时“保护”某些数据,以便粘贴完全相同的标记。例如,如果CKEditor中的HTML包含注释:
然后,如果从编辑器复制,剪贴板将包含以下HTML:
其想法是,CKEditor希望确保评论按原样粘贴,而不会出现任何乱七八糟的情况。问题(又一次出现了!)。CKEditor没有意识到--!>;关闭了HTML注释,从而允许隐藏任意标记。因此,以下有效负载触发了XSS:
CKEditor假定--!>;<;img src=1 onerror=alert(1)>;是注释的文本并逐字粘贴,而浏览器在--!>;关闭它并呈现<;img>;元素。
据其官方网站介绍,Froala是一个所见即所得的编辑器,“在考虑到更好的开发人员和用户体验的情况下,为快速开发而构建编辑软件”。
我描述的bug是0天的,截至2020年6月4日,它仍然在当前的稳定版本中工作。我在2020年1月22日报告了这个错误,我得到的唯一答案是:“我已经将这个问题提交给开发人员,但还没有确定修复的时间表”。在此期间,我就这个问题问了三次,都没有结果。
Froala使用正则表达式和字符串处理执行大量HTML处理。下面我展示的只是一个由此产生的问题,但我相信还会有更多的问题。
从剪贴板粘贴后,Froala获取HTML并(除其他操作外)执行以下操作:
将regex:/(?:(?!<;\/noscript>;)<;[^<;])*<;\/noscript>;/gi的所有匹配项替换为[FROALA.EDITOR.NOSCRIPT0](如果找到更多<;noscript>;标记,则该数字会递增)。正则表达式的目标是匹配所有<;noscript>;元素及其内容。
标记是安全的,因为XSS有效负载包含在title属性中。但是,在第一步之后,Froala将其更改为:
请注意单引号是如何替换为双引号的。之后,[FROALA.EDITOR.NOSCRIPT 0]将替换为原始<;noscript>;元素:
这会触发XSS。另一个很好的例子是,将HTML作为字符串处理几乎总是一个坏主意!
Gmail使用Google自己的Close Library消毒器对剪贴板内容进行消毒化。处理Paste事件的代码大致相当于以下代码片段:
虽然乍一看它可能是安全的,但有一个警告:如果sanitiseWithClosure抛出异常,则从不调用event.prevenentDefault(),这意味着完全忽略了闭包消毒器,而使用了浏览器的消毒器。当我向谷歌报告这个错误时,Chromium#1的问题还没有修复,因此退回到浏览器的杀菌剂可能会导致XSS。
剩下的问题是:我们如何才能使闭包抛出异常?我发现了一种触发异常的方法:需要向消毒器提供以下代码:
这似乎是一个封闭的错误(实际上很容易识别某个网站是否在使用它),但谷歌并没有修复它。如果您想要自己修补的话,我已经在https://jsbin.com/mahinanuru/edit?html,Output创建了一个闭合游乐场。只要您在<;ath>;元素中有一个带有style属性的元素,就会触发该错误。
利用此问题的有效负载与Chromium中的有效负载相同(因为有效负载已经具有<;Math>;内部具有style属性的元素):
尽管利用该问题需要浏览器中存在漏洞,但谷歌支付了5000美元的全额赏金。
在这篇文章的前几节中,我只提到了text/html在粘贴时可能会有危险。但是,一些网站定义了它们自己的非HTML内容类型。
谷歌文档(Google Docs)就是这种情况。如果您从Google Docs复制任何东西,那么它会用Content-Type:application/x-vnd.google-docs-document-slice-clip+wrapped设置数据,这只是一个很大的JSON对象:
此JSON的某些部分反映在HTML中。我注意到JSON有一个键hclr_color,它包含文档中元素的颜色。对这个问题的利用非常简单,只需将其设置为:
<;!doctype html>;<;meta charset=utf-8>;<;script id=data type=application/json>;{";已解析";:
..