1 poin oleh GN⁺ 2024-10-18 | 1 komentar | Bagikan ke WhatsApp
  • Batas hak istimewa WebUI Chromium, fitur pengujian kebijakan enterprise, dan cacat pada API ekstensi DevTools saling terhubung, sehingga ekstensi Chrome berbahaya dapat mencapai eksekusi perintah shell hanya dengan sedikit interaksi pengguna
  • Jalur serangan memanggil API pengujian kebijakan yang tidak terdokumentasi di chrome://policy untuk mengubah kebijakan pengguna, lalu menyalahgunakan jalur dan argumen browser alternatif milik Browser Switcher sebagai perintah shell
  • chrome.devtools.inspectedWindow.reload() mengizinkan eksekusi injectedScript, dan karena keterlambatan pemblokiran akses saat navigasi WebUI atau permintaan Page.reload yang tertinggal setelah crash, kode dapat dijalankan di WebUI yang memiliki hak istimewa
  • Google mengklasifikasikan kerentanan ini sebagai P1/S1 dan menambahkan validasi loaderId pada Page.reload, pemeriksaan URL pada inspectedWindow.reload(), serta pemeriksaan aktivasi pengujian kebijakan pada handler WebUI
  • Kerentanan terkait diberi CVE-2024-5836 dan CVE-2024-6778, keduanya mendapat CVSS 8.8 High, dan hadiah akhirnya adalah $20,000

Batas WebUI Chromium dan sandbox

  • Chromium menjalankan kode yang tidak tepercaya di dalam sandbox, dan JavaScript dari ekstensi Chrome juga seharusnya hanya berjalan dalam izin yang diberikan dan API yang dapat diakses
  • Hanya dengan izin ekstensi pun data login atau riwayat peramban bisa dicuri, tetapi secara prinsip dampaknya seharusnya tetap terbatas di dalam browser
  • Sebagian GUI Chromium diimplementasikan sebagai WebUI seperti chrome://settings dan chrome://history
    • WebUI ditulis dengan HTML, CSS, dan JavaScript, tetapi karena harus menampilkan dan mengubah informasi internal browser, ia memiliki hak istimewa lebih tinggi daripada halaman web biasa
    • JavaScript frontend WebUI dapat berkomunikasi dengan kode C++ native browser melalui API privat
  • Jika eksekusi kode dimungkinkan di WebUI, itu dapat berujung pada bypass sandbox Chromium, sehingga penting mencegah penyerang menjalankan JavaScript tak tepercaya di halaman chrome://
  • Sebagai contoh, jika item unduhan .exe di chrome://downloads diklik, file executable bisa dibuka, sehingga Chromium memeriksa apakah tindakan membuka file benar-benar berasal dari input pengguna nyata

Bypass pada fitur pengujian kebijakan enterprise

  • Penelusuran kerentanan dimulai dari enterprise policy system milik Chromium
    • Sistem ini memungkinkan admin memaksakan pengaturan tertentu pada perangkat milik perusahaan atau sekolah
    • Kebijakan biasanya terikat ke akun Google dan diunduh dari server administrasi Google
  • Kebijakan dibagi menjadi device policies dan user policies
    • device policies mengelola pengaturan seluruh perangkat Chrome OS
    • user policies diterapkan pada pengguna tertentu atau instance browser tertentu dan tersedia di semua platform
    • Di Linux, user policies dapat diterapkan ke instance Google Chrome dengan menaruh file JSON di /etc/opt/chrome/policies, tetapi menulis ke direktori ini memerlukan hak root
  • Kebijakan yang sedang diterapkan pada perangkat saat ini dapat dilihat di WebUI chrome://policy
    • Halaman ini menyediakan daftar kebijakan yang diterapkan, log layanan kebijakan, dan fitur ekspor JSON
    • Normalnya tidak ada cara mengedit kebijakan dari halaman ini
  • Catatan rilis Chrome Enterprise untuk Chrome v117 menyebut bahwa halaman chrome://policy/test mengizinkan pengujian kebijakan pada kanal Beta, Dev, dan Canary
    • Fitur ini tidak disebut di dokumentasi Chromium selain catatan rilis tersebut
    • Agar aktif secara normal, diperlukan kebijakan tak terdokumentasi PolicyTestPageEnabled
    • Tanpa kebijakan ini, chrome://policy/test akan diarahkan ulang ke chrome://policy

Kegagalan validasi setLocalTestPolicies

  • Kode JavaScript di chrome://policy/test menggunakan sendWithPromise('setLocalTestPolicies', ...) untuk menetapkan kebijakan uji
    • sendWithPromise() adalah wrapper untuk chrome.send(), API privat WebUI
    • Panggilan ini mengirim permintaan ke fungsi handler C++, dan handler tersebut dapat melakukan operasi internal browser
  • Saat setLocalTestPolicies dipanggil langsung dari konsol chrome://policy, browser awalnya crash, dan log menunjukkan bahwa array kebijakan diperlukan
  • Setelah format array kebijakan disesuaikan dan user policy seperti AllowDinosaurEasterEgg dikirimkan, kebijakan arbitrer ternyata dapat ditetapkan meski fitur itu tidak diaktifkan secara eksplisit
  • Handler HandleSetLocalTestPolicies di sisi C++ hanya memeriksa keberadaan local_test_provider, dan tidak memeriksa apakah fitur pengujian kebijakan benar-benar diizinkan
  • LocalTestPolicyProvider::CreateIfAllowed() memanggil IsPolicyTestingEnabled(nullptr, channel)
    • Karena argumen pertama pref_service bernilai null, pemeriksaan PolicyTestPageEnabled dilewati
    • Pemeriksaan yang tersisa hanya apakah release channel adalah CANARY atau DEFAULT
  • Pada build Chromium tanpa branding, kode GOOGLE_CHROME_BRANDING tidak dikompilasi sehingga channel tetap UNKNOWN
    • Dalam enum, UNKNOWN = 0 dan DEFAULT = UNKNOWN, sehingga pemeriksaan channel lolos pada Chromium dan build turunannya
    • Pada build stable Google Chrome yang diberi branding, release channel diatur dengan benar sehingga bug ini tidak bekerja di Google Chrome stable

Eksekusi perintah shell lewat Browser Switcher

  • Setelah kebijakan pengguna arbitrer dapat ditetapkan, modul kebijakan enterprise Chrome Legacy Browser Support menjadi jalur pelarian sandbox
  • Legacy Browser Support juga dikenal sebagai Browser Switcher, dan dirancang untuk menjalankan browser alternatif ketika pengguna mengunjungi URL tertentu dari Chromium
    • Fitur ini dibuat untuk mendukung pengguna Internet Explorer
    • Perilakunya dikendalikan oleh kebijakan
  • Dengan menggabungkan kebijakan AlternativeBrowserPath dan AlternativeBrowserParameters, Chromium dapat menjalankan perintah shell arbitrer sebagai “browser alternatif”
    • Kebijakan Browser Switcher ini hanya ada di Linux, macOS, dan Windows
  • Contoh alurnya sebagai berikut
    • Setel BrowserSwitcherEnabled ke true
    • Masukkan example.com ke BrowserSwitcherUrlList
    • Setel AlternativeBrowserPath ke /bin/bash di Linux
    • Setel AlternativeBrowserParameters menjadi seperti ["-c", "xcalc # ${url}"]
  • Saat browser bernavigasi ke example.com, Browser Switcher aktif dan perintah seperti /bin/bash -c 'xcalc # https://example.com' dijalankan
    • Nilai substitusi ${url} ditempatkan setelah # agar diperlakukan sebagai komentar shell
  • Setelah menetapkan kebijakan di chrome://policy, memanggil window.open("https://example.com";) saja sudah cukup untuk berlanjut ke eksekusi perintah shell arbitrer lewat JavaScript

Jalur bypass melalui API ekstensi DevTools

  • Dengan langkah sebelumnya saja, korban masih harus menempelkan kode berbahaya ke konsol browser di chrome://policy, sehingga kurang praktis
  • Jalur eksekusi otomatis kemudian ditemukan melalui ekstensi Chrome berbahaya
    • Ekstensi dapat menyisipkan JavaScript ke halaman, tetapi seharusnya tidak bisa menjalankan JavaScript di halaman WebUI yang memiliki hak istimewa
  • Ada empat API utama yang dipakai ekstensi untuk menjalankan JavaScript di halaman
    • chrome.scripting
    • chrome.tabs pada Manifest v2
    • chrome.debugger
    • chrome.devtools.inspectedWindow
  • Target penyelidikan adalah chrome.devtools.inspectedWindow, yang diperkirakan relatif kurang diperkuat
    • Ekstensi yang menggunakan API chrome.devtools harus memiliki field devtools_page di manifest
    • Saat pengguna membuka DevTools, halaman tersebut dimuat sebagai iframe dan API chrome.devtools dapat digunakan di dalamnya
  • Laporan bug sebelumnya dari David Erceg sudah menunjukkan kasus mencapai eksekusi kode di WebUI melalui chrome.devtools.inspectedWindow.eval()
    • Normalnya, jika halaman yang diperiksa bernavigasi ke WebUI, penggunaan API DevTools harus dinonaktifkan
    • Inti bypass-nya adalah mengirim permintaan eval sebelum Chrome menonaktifkan API, lalu membuat permintaan itu sampai ke halaman WebUI

inspectedWindow.reload() dan kekhususan about:blank

  • chrome.devtools.inspectedWindow.reload() juga dapat menjalankan JavaScript di halaman yang diperiksa jika argumen injectedScript diberikan
  • Saat inspectedWindow.reload() dipanggil pada halaman about:blank yang dibuka oleh WebUI, JavaScript dapat dijalankan pada halaman yang memiliki hak istimewa
    • about:blank sendiri bukan URL yang istimewa, tetapi mewarisi hak istimewa dan origin dari halaman yang membukanya
    • about:blank yang dibuka oleh chrome://settings menjadi halaman ber-origin chrome://settings yang memiliki hak istimewa
  • Kode penonaktifan API DevTools hanya memeriksa URL target inspeksi, bukan origin-nya
    • Jadi meski URL terlihat biasa, origin-nya bisa saja origin yang memiliki hak istimewa
  • Jalur about:blank saja sulit langsung dipakai dalam rantai exploit karena chrome://policy tidak membuka popup about:blank
  • Namun inspectedWindow.reload() tetap bisa menjalankan JavaScript di chrome://settings bahkan dalam situasi ketika inspectedWindow.eval() gagal
    • Ini menunjukkan eval() punya pemeriksaan internal sendiri yang setara dengan pemeriksaan origin, sedangkan reload() tidak memiliki tingkat pemeriksaan yang sama

Menstabilkan dari race condition ke metode berbasis crash

  • Rantai exploit pertama mengulang panggilan inspectedWindow.reload() untuk membidik jendela waktu singkat setelah halaman yang diperiksa bernavigasi ke WebUI tetapi sebelum halaman DevTools menonaktifkan API
    • Ini bergantung pada fakta bahwa halaman yang diperiksa dan halaman DevTools berada di proses yang berbeda
    • Jika permintaan reload() masuk di antara saat navigasi ke chrome://policy dan penonaktifan API DevTools, kode dapat dieksekusi di WebUI
  • Metode ini berhasil, tetapi reliabilitasnya rendah
    • Setelah penyesuaian, tingkat keberhasilannya sekitar 70%
    • Meskipun kerentanannya serius, ketidakstabilan ini dapat menurunkan severity
  • Selanjutnya diuji apakah, seperti pendekatan lama David Erceg, perilaku permintaan debugger yang tertinggal setelah tab crash juga bisa diterapkan ke inspectedWindow.reload()
  • Jika pernyataan debugger dipicu dua kali berturut-turut, tab akan crash, dan permintaan Page.reload dapat tertinggal di antrean lalu dieksekusi setelah berpindah ke WebUI
    • Cara ini menghilangkan kebutuhan race condition sehingga bekerja 100% reliable
  • Pada patch bug sebelumnya, Google memperbaiki penghapusan pending debugger requests setelah crash, tetapi permintaan Page.reload dibiarkan sebagai pengecualian
    • inspectedWindow.reload() secara internal mengirim permintaan Page.reload, sehingga terkena dampak pengecualian ini
    • Patch saat itu tidak mencegah fakta bahwa Page.reload bisa menjalankan skrip
  • Crash tab juga bisa dipicu dengan metode kehabisan memori selain pendekatan debugger, tetapi PoC akhir memakai crash via debugger yang lebih cepat

Rantai exploit akhir dan interaksi pengguna

  • PoC akhir bekerja dengan urutan berikut
    • Menggunakan kerentanan chrome.devtools.inspectedWindow.reload() untuk menjalankan payload JavaScript di chrome://policy
    • Payload memanggil sendWithPromise("setLocalTestPolicies", policy) untuk menetapkan kebijakan pengguna
    • Menetapkan BrowserSwitcherEnabled, BrowserSwitcherUrlList, AlternativeBrowserPath, dan AlternativeBrowserParameters
    • Memicu Browser Switcher melalui window.open() atau navigasi halaman untuk menjalankan perintah shell
  • PoC menggunakan perintah menjalankan kalkulator sesuai OS
    • Windows: C:\Windows\System32\cmd.exe dan calc.exe
    • Linux: /bin/bash dan xcalc
    • macOS: /bin/bash dan open -na Calculator
  • Interaksi pengguna yang diperlukan hanya sebatas membuat mereka membuka DevTools
    • Tulisan “extension install error” pada layar contoh dipakai untuk menipu pengguna agar membuka DevTools
    • Begitu DevTools dibuka, rantai yang mengarah ke sandbox escape dimulai

Perbaikan Google dan penetapan CVE

Jadwal publikasi dan materi

  • Timeline-nya adalah sebagai berikut
    • 16 April: bug test policies ditemukan
    • 29 April: bug race condition inspectedWindow.reload() ditemukan
    • 1 Mei: bug dilaporkan ke Google
    • 4 Mei: Google mengklasifikasikannya sebagai P1/S1
    • 5 Mei: bug terkait crash halaman yang diperiksa ditemukan dan laporan diperbarui
    • 6 Mei: Google meminta laporan bug terpisah untuk tiap bagian dari chain
    • 8 Juli: laporan bug ditandai fixed
    • 13 Juli: diteruskan ke panel Chrome VRP untuk penentuan hadiah
    • 17 Juli: panel VRP menetapkan hadiah $20,000
    • 15 Oktober: seluruh laporan bug dipublikasikan
  • Laporan bug asli terkait dapat dilihat di crbug.com/338248595
  • PoC untuk tiap bagian kerentanan dipublikasikan di repositori GitHub
  • Bug inspectedWindow.reload bekerja hingga Chrome v45
  • Jika fitur yang tidak terdokumentasi, belum matang, dan tidak aman dirilis ke semua pengguna, kesalahan-kesalahan sederhana dapat saling berpadu dan berujung pada kerentanan dengan tingkat keparahan tinggi

1 komentar

 
GN⁺ 2024-10-18
Komentar di Hacker News
  • URL halaman diganti menjadi ${url}, dan disebutkan bahwa jika diletakkan setelah # agar tidak merusak perintah, itu akan menjadi komentar. Tapi apakah di kebijakan ini ada semacam logika validasi bahwa URL harus diteruskan ke suatu tempat di AlternativeBrowserParameters?

  • Seorang siswa SMA yang tertarik pada pemrograman, pengembangan web, dan keamanan siber—benar-benar mengesankan

    • Bakat teknis yang luar biasa, ketekunan, serta kemampuan dokumentasi dan komunikasi yang semuanya sangat bagus
      Etika profesionalnya juga hebat karena mengikuti proses pengungkapan yang bertanggung jawab, dan tampaknya akan menjadi orang besar ke depannya
  • Tulisan dan pekerjaannya luar biasa, dan rasanya seperti ikut mengikuti proses ketika kegembiraan makin menumpuk seiring berlanjutnya penemuan
    Ia juga sangat pantas mendapatkan imbalan yang memadai

  • Rangkaian eksploitasi kerentanannya rapi dan tulisannya juga bagus. Saya juga suka bagaimana ia memecah dan menunjukkan cara kerja kode yang rentan
    Trik sederhana seperti “tekan F12 untuk mencoba lagi” selalu membuat saya kagum setiap kali melihatnya, benar-benar penuh keisengan

    • Saya tinggal di Missouri, dan dulu ketika saya menekan F12 sekali, gubernur mencoba menangkap saya
  • Ini mengingatkan saya pada kejadian dulu ketika saya men-debug shell crosh di Chrome OS dengan API yang sama untuk melewati perlindungan OS dan bahkan mendapatkan akses root pada perangkat developer. Itu adalah CVE-2014-3172
    Namun penulis artikel ini harus melewati rintangan yang jauh lebih sulit, dan ini benar-benar pekerjaan yang hebat

  • Karena sudah terlalu larut malam, sulit untuk menggali lebih dalam apa yang rusak pada validasi WebUI, tetapi saya suka bahwa ia mengusutnya sampai tuntas dan menemukan penyebabnya
    Mencurigai dan tidak memercayai toolchain dari hal-hal yang kita deploy adalah sikap yang cukup standar, tetapi pada saat yang sama kita terlalu memercayai alat pengembangan yang nyaman bak sihir dari perusahaan besar seperti Google atau Microsoft. Pada akhirnya, itu karena saya ingin menulis dan menguji kode saya sendiri, alih-alih mengkhawatirkan apa yang tersembunyi di dalam Chromium atau VSCode

  • Ini salah satu tulisan terbaik yang pernah saya baca
    Benar-benar pekerjaan pelacakan yang cerdik

  • Upaya menggali kode browser sampai menemukan hal ini luar biasa, dan tulisannya juga sangat menarik serta mendetail

  • Masih siswa SMA, wow, benar-benar hebat

  • Proyek Chromium menghapus chrome://net-internals dengan alasan terlalu rumit, lalu menambahkan chrome://policy dengan dukungan pengeditan JSON yang setengah matang