Skip to main content

Pencegahan DOM Clobbering

Pendahuluan tentang Pencegahan DOM Clobbering

DOM Clobbering adalah jenis serangan injeksi HTML-only yang menggunakan kembali kode, di mana penyerang membingungkan aplikasi web dengan menyuntikkan elemen HTML yang atribut id atau name-nya cocok dengan nama variabel yang sensitif terhadap keamanan atau API browser, seperti variabel yang digunakan untuk mengambil konten jarak jauh (misalnya, skrip src), dan menutupi nilainya.

Hal ini khususnya relevan ketika injeksi skrip tidak memungkinkan, misalnya, ketika difilter oleh pembersih HTML, atau dikurangi dengan melarang atau mengendalikan eksekusi skrip. Dalam skenario ini, penyerang mungkin masih menyuntikkan markup HTML non-skrip ke halaman web dan mengubah markup yang awalnya aman menjadi kode yang dapat dieksekusi, sehingga mencapai Cross-Site Scripting (XSS).

Lembar contekan ini adalah daftar panduan, pola pengodean yang aman, dan praktik untuk mencegah atau membatasi dampak DOM Clobbering pada aplikasi web Anda.

Latar Belakang

Sebelum kita menyelami DOM Clobbering, mari segarkan pengetahuan kita dengan beberapa latar belakang Web dasar.

Saat halaman web dimuat, browser membuat pohon DOM yang mewakili struktur dan konten halaman, dan kode JavaScript memiliki akses baca dan tulis ke pohon ini.

Saat membuat pohon DOM, peramban juga membuat atribut untuk (beberapa) elemen HTML bernama pada objek window dan document. Elemen HTML bernama adalah elemen yang memiliki atribut id atau name. Misalnya, markup:

<form id=x></a>

akan menyebabkan peramban membuat referensi ke elemen formulir tersebut dengan atribut x dari window dan document:

var obj1 = document.getElementById('x');
var obj2 = document.x;
var obj3 = document.x;
var obj4 = window.x;
var obj5 = x; // secara default, objek termasuk dalam Window global, jadi x sama dengan window.x
console.log(
obj1 === obj2 && obj2 === obj3 &&
obj3 === obj4 && obj4 === obj5
); // true

Saat mengakses atribut objek window dan document, referensi elemen HTML bernama muncul sebelum pencarian API bawaan dan atribut lain pada window dan document yang telah ditetapkan pengembang, yang juga dikenal sebagai akses properti bernama. Pengembang yang tidak menyadari perilaku tersebut dapat menggunakan konten atribut window/document untuk operasi sensitif, seperti URL untuk mengambil konten jarak jauh, dan penyerang dapat mengeksploitasinya dengan menyuntikkan markup dengan nama yang bertabrakan. Mirip dengan atribut/variabel kustom, API browser bawaan dapat dibayangi oleh DOM Clobbering.

Jika penyerang dapat menyuntikkan markup HTML (non-skrip) di pohon DOM, ia dapat mengubah nilai variabel yang diandalkan aplikasi web karena akses properti bernama, menyebabkannya tidak berfungsi, mengekspos data sensitif, atau menjalankan skrip yang dikendalikan penyerang. DOM Clobbering bekerja dengan memanfaatkan perilaku (lama) ini, yang menyebabkan tabrakan namespace antara lingkungan eksekusi (yaitu, objek window dan document), dan kode JavaScript.

Contoh Serangan 1

let redirectTo = window.redirectTo || '/profile/';
location.assign(redirectTo);

Penyerang dapat:

  • menyuntikkan markup <a id=redirectTo href='javascript:alert(1)' dan memperoleh XSS. - menyuntikkan markup <a id=redirectTo href='phishing.com' dan memperoleh pengalihan terbuka.

Contoh Serangan 2

var script = document.createElement('script');
let src = window.config.url || 'script.js';
s.src = src;
document.body.appendChild(s);

Penyerang dapat menyuntikkan markup <a id=config><a id=config name=url href='malicious.js'> untuk memuat kode JavaScript tambahan, dan memperoleh eksekusi kode sisi klien yang sewenang-wenang.

Ringkasan Pedoman

Sebagai referensi cepat, berikut adalah ringkasan pedoman yang dibahas berikutnya.

PanduanDeskripsi
# 1Use HTML Sanitizerslink
# 2Use Content-Security Policylink
# 3Freeze Sensitive DOM Objectslink
# 4Validate All Inputs to DOM Treelink
# 5Use Explicit Variable Declarationslink
# 6Do Not Use Document and Window for Global Variableslink
# 7Do Not Trust Document Built-in APIs Before Validationlink
# 8Enforce Type Checkinglink
# 9Use Strict Modelink
# 10Apply Browser Feature Detectionlink
# 11Limit Variables to Local Scopelink
# 12Use Unique Variable Names In Productionlink
# 13Use Object-oriented Programming Techniques like Encapsulationlink

Teknik Mitigasi

#1: Sanitasi HTML

Sanitizer HTML yang kuat dapat mencegah atau membatasi risiko DOM Clobbering. Sanitizer dapat melakukannya dengan berbagai cara. Misalnya:

  • menghapus sepenuhnya properti bernama seperti id dan name. Meskipun efektif, hal ini dapat menghambat kegunaan saat properti bernama dibutuhkan untuk fungsi yang sah.

  • isolasi namespace, yang dapat berupa, misalnya, awalan nilai properti bernama dengan string konstan untuk membatasi risiko tabrakan penamaan.

  • memeriksa secara dinamis apakah properti bernama dari tanda input memiliki tabrakan dengan pohon DOM yang ada, dan jika demikian, hapus properti bernama dari markup input.

OWASP merekomendasikan DOMPurify atau API Sanitizer untuk sanitasi HTML.

DOMPurify Sanitizer

Secara default, DOMPurify menghapus semua tabrakan clobbering dengan API dan properti bawaan (menggunakan opsi konfigurasi SANITIZE_DOM yang diaktifkan secara default).

Agar terlindungi dari clobbering variabel dan properti kustom, Anda perlu mengaktifkan konfigurasi SANITIZE_NAMED_PROPS:

var clean = DOMPurify.sanitize(dirty, {SANITIZE_NAMED_PROPS: true});

Ini akan mengisolasi namespace dari properti bernama dan variabel JavaScript dengan mengawalinya dengan string user-content-.

API Sanitizer

API Sanitizer bawaan browser yang baru tidak mencegah DOM Clobbering pada setelan default, tetapi dapat dikonfigurasi untuk menghapus properti bernama:

const sanitizerInstance = new Sanitizer({
blockAttributes: [
{'name': 'id', elements: '*'},
{'name': 'name', elements: '*'}
]
});
containerDOMElement.setHTML(input, {sanitizer: sanitizerInstance});

#2: Kebijakan Keamanan Konten

Kebijakan Keamanan Konten (CSP) adalah serangkaian aturan yang memberi tahu peramban sumber daya mana yang boleh dimuat di halaman web. Dengan membatasi sumber file JavaScript (misalnya, dengan perintah script-src), CSP dapat mencegah kode berbahaya dimasukkan ke dalam halaman.

Catatan: CSP hanya dapat mengurangi beberapa varian serangan DOM clobbering, seperti saat penyerang mencoba memuat skrip baru dengan menghancurkan sumber skrip, tetapi tidak saat kode yang sudah ada dapat disalahgunakan untuk eksekusi kode, misalnya, menghancurkan parameter konstruksi evaluasi kode seperti eval().

#3: Membekukan Objek DOM yang Sensitif

Cara sederhana untuk mengurangi DOM Clobbering terhadap objek individual adalah dengan membekukan objek DOM yang sensitif dan propertinya, misalnya, melalui metode Object.freeze().

Catatan: Membekukan properti objek mencegahnya ditimpa oleh elemen DOM bernama. Namun, menentukan semua objek dan properti objek yang perlu dibekukan mungkin tidak mudah, sehingga membatasi kegunaan pendekatan ini.

Panduan Pengodean yang Aman

Penghancuran DOM dapat dihindari dengan pemrograman defensif dan mematuhi beberapa pola dan panduan pengodean.

#4: Validasi Semua Input ke Pohon DOM

Sebelum memasukkan markup apa pun ke pohon DOM halaman web, bersihkan atribut id dan name (lihat pembersihan HTML).

#5: Gunakan Deklarasi Variabel Eksplisit

Saat menginisialisasi variabel, selalu gunakan deklarator variabel seperti var, let atau const, yang mencegah penghancuran variabel.

Catatan: Mendeklarasikan variabel dengan let tidak membuat properti pada window, tidak seperti var. Oleh karena itu, window.VARNAME masih dapat dihancurkan (dengan asumsi VARNAME adalah nama variabel).

#6: Jangan Gunakan Document dan Window untuk Variabel Global

Hindari penggunaan objek seperti document dan window untuk menyimpan variabel global, karena keduanya dapat dengan mudah dimanipulasi. (lihat, misalnya, di sini).

#7: Jangan Percayai API Bawaan Document Sebelum Validasi

Properti dokumen, termasuk yang bawaan, selalu dibayangi oleh DOM Clobbering, bahkan setelah diberi nilai.

Petunjuk: Hal ini disebabkan oleh apa yang disebut algoritme visibilitas properti bernama, di mana referensi elemen HTML bernama muncul sebelum pencarian API bawaan dan atribut lain pada document.

#8: Terapkan Pemeriksaan Tipe

Selalu periksa tipe properti document dan window sebelum menggunakannya dalam operasi sensitif, misalnya, menggunakan operator instanceof.

Petunjuk: Saat objek dihancurkan, objek tersebut akan merujuk ke instance Element, yang mungkin bukan tipe yang diharapkan.

#9: Gunakan Mode Ketat

Gunakan mode ketat untuk mencegah pembuatan variabel global yang tidak diinginkan, dan untuk menimbulkan kesalahan saat properti baca-saja dicoba untuk ditimpa.

#10: Terapkan Deteksi Fitur Peramban

Daripada mengandalkan fitur atau properti khusus peramban, gunakan deteksi fitur untuk menentukan apakah suatu fitur didukung sebelum menggunakannya. Ini dapat membantu mencegah kesalahan dan DOM Clobbering yang mungkin muncul saat menggunakan fitur tersebut di peramban yang tidak didukung.

Petunjuk: API fitur yang tidak didukung dapat bertindak sebagai variabel/properti yang tidak ditentukan di peramban yang tidak didukung, sehingga dapat ditimpa.

#11: Batasi Variabel ke Cakupan Lokal

Variabel global lebih rentan ditimpa oleh DOM Clobbering. Bila memungkinkan, gunakan variabel lokal dan properti objek.

#12: Gunakan Nama Variabel Unik dalam Produksi

Penggunaan nama variabel unik dapat membantu mencegah tabrakan penamaan yang dapat menyebabkan penimpaan yang tidak disengaja.

#13: Gunakan Teknik Pemrograman Berorientasi Objek seperti Enkapsulasi

Enkapsulasi variabel dan fungsi dalam objek atau kelas dapat membantu mencegahnya ditimpa. Dengan menjadikannya privat, variabel dan fungsi tidak dapat diakses dari luar objek, sehingga tidak mudah diretas oleh DOM.

Referensi