Clickjacking Defense¶
Pendahuluan¶
Lembar contekan ini dimaksudkan untuk memberikan panduan bagi para pengembang tentang cara melindungi diri dari Clickjacking, yang juga dikenal sebagai UI redress attacks.
Ada tiga mekanisme utama yang dapat digunakan untuk melindungi diri dari serangan ini:
Mencegah peramban memuat halaman dalam bingkai menggunakan header HTTP X-Frame-Options atau Content Security Policy (frame-ancestors).
Mencegah kuki sesi disertakan saat halaman dimuat dalam bingkai menggunakan atribut cookie SameSite.
Mengimplementasikan kode JavaScript di halaman untuk mencoba mencegahnya dimuat dalam frame (dikenal sebagai "frame-buster").
Perlu diketahui bahwa semua mekanisme ini independen satu sama lain, dan jika memungkinkan, lebih dari satu mekanisme harus diimplementasikan untuk memberikan pertahanan yang mendalam.
Melindungi dengan direktif Content Security Policy (CSP) frame-ancestors¶
Direktif frame-ancestors dapat digunakan dalam header respons HTTP Content-Security-Policy untuk menunjukkan apakah peramban diizinkan untuk merender halaman dalam <frame> atau <iframe>. Situs dapat menggunakan ini untuk menghindari serangan Clickjacking dengan memastikan bahwa konten mereka tidak disematkan ke situs lain.
frame-ancestors memungkinkan situs untuk mengotorisasi beberapa domain menggunakan semantik Content Security Policy yang normal.
contoh Content-Security-Policy: frame-ancestors¶
CSP frame-ancestors yang umum digunakan:
- Content-Security-Policy: frame-ancestors 'none';
Ini mencegah domain apa pun membingkai konten. Pengaturan ini direkomendasikan kecuali kebutuhan khusus untuk pembingkaian telah diidentifikasi.
- Content-Security-Policy: frame-ancestors 'self';
Ini hanya memungkinkan situs saat ini untuk membingkai konten.
- Content-Security-Policy: frame-ancestors 'self' *.somesite.com https://myfriend.site.com;
Ini memungkinkan situs saat ini, serta halaman mana pun di somesite.com (menggunakan protokol apa pun), dan hanya halaman myfriend.site.com, menggunakan HTTPS hanya pada port default (443).
Perhatikan bahwa tanda kutip tunggal diperlukan di sekitar "self" dan "none", tetapi tidak boleh digunakan di sekitar ekspresi sumber lainnya.
Lihat dokumentasi berikut untuk detail lebih lanjut dan contoh yang lebih kompleks:
Keterbatasan¶
X-Frame-Options diprioritaskan: Bagian "Terkait dengan X-Frame-Options" dari Spesifikasi CSP menyatakan: "Jika suatu sumber daya dikirimkan dengan kebijakan yang menyertakan direktif bernama frame-ancestors dan disposisinya adalah "enforce", maka header X-Frame-Options HARUS diabaikan", tetapi versi peramban yang lebih lama (misalnya, Chrome 40 & Firefox 35) mengabaikan persyaratan ini dan mengikuti header X-Frame-Options sebagai gantinya.
Browser Support¶
Untuk melihat browsers yang support CSP frame-ancestors.
Bertahan dengan Header Response X-Frame-Options¶
Header respons HTTP X-Frame-Options dapat digunakan untuk menunjukkan apakah peramban diizinkan untuk merender halaman dalam <frame> atau <iframe>. Situs dapat menggunakan ini untuk menghindari serangan Clickjacking, dengan memastikan konten mereka tidak disematkan ke situs lain. Atur header X-Frame-Options untuk semua respons yang berisi konten HTML. Nilai yang mungkin adalah "DENY", "SAMEORIGIN", atau "ALLOW-FROM uri".
Tipe X-Frame-Options Header¶
Ada tiga kemungkinan nilai untuk header X-Frame-Options:
DENY, yang mencegah domain apa pun membingkai konten. Pengaturan "DENY" direkomendasikan kecuali jika kebutuhan khusus telah diidentifikasi untuk pembingkaian.
SAMEORIGIN, yang hanya mengizinkan situs saat ini untuk membingkai konten.
- ALLOW-FROM uri, yang mengizinkan 'uri' yang ditentukan untuk membingkai halaman ini. (misalnya, ALLOW-FROM http://www.example.com).
Ini adalah direktif usang yang tidak lagi berfungsi di peramban modern.
Periksa batasan di bawah ini karena ini akan gagal dibuka jika peramban tidak mendukungnya.
Peramban lain mendukung direktif frame-ancestors CSP yang baru. Beberapa peramban mendukung keduanya.
Browser support¶
Perambah yang mensupport X-Frame-Options headers.
Implementasi¶
Untuk menerapkan perlindungan ini, Anda perlu menambahkan header Respons HTTP X-Frame-Options ke halaman mana pun yang ingin Anda lindungi dari clickjacking melalui framebusting. Salah satu cara untuk melakukannya adalah dengan menambahkan Header Respons HTTP secara manual ke setiap halaman. Cara yang mungkin lebih sederhana adalah dengan menerapkan filter yang secara otomatis menambahkan header ke setiap halaman atau menambahkannya di Web Application Firewall (WAF) di tingkat Web/Application Server.
Kesalahan Umum Pertahanan¶
Meta-tag yang mencoba menerapkan direktif X-Frame-Options TIDAK BERFUNGSI. Misalnya, <meta http-equiv="X-Frame-Options" content="deny"> tidak akan berfungsi. Anda harus menerapkan direktif X-FRAME-OPTIONS sebagai Header Respons HTTP seperti dijelaskan di atas.
Keterbatasan¶
Per-page policy specification: Kebijakan perlu ditentukan untuk setiap halaman, yang dapat mempersulit penerapan. Menyediakan kemampuan untuk menerapkannya di seluruh situs, misalnya saat masuk, dapat menyederhanakan penerapan.
Masalah dengan situs multi-domain: Implementasi saat ini tidak memungkinkan administrator situs web untuk menyediakan daftar domain yang diizinkan untuk membingkai halaman. Meskipun mencantumkan domain yang diizinkan dapat berbahaya, dalam beberapa kasus administrator situs web mungkin tidak punya pilihan selain menggunakan lebih dari satu nama host.
Dukungan browser ALLOW-FROM: Opsi ALLOW-FROM sudah usang dan tidak lagi berfungsi di browser modern. HATI-HATILAH TERGANTUNG PADA ALLOW-FROM. Jika Anda menerapkannya dan browser tidak mendukungnya, maka Anda TIDAK akan memiliki pertahanan clickjacking.
Beberapa opsi tidak didukung: Tidak ada cara untuk mengizinkan situs saat ini dan situs pihak ketiga untuk membingkai respons yang sama. Browser hanya menggunakan satu header X-Frame-Options dan hanya satu nilai pada header tersebut.
- Nested Frames tidak berfungsi dengan SAMEORIGIN dan ALLOW-FROM: Dalam situasi berikut, frame
http://framed.invalid/childtidak dimuat karena ALLOW-FROM berlaku untuk konteks penelusuran tingkat atas, bukan konteks induk langsung. Solusinya adalah menggunakan ALLOW-FROM baik di frame induk maupun anak (tetapi ini mencegah pemuatan frame anak jika halaman//framed.invalid/parentdimuat sebagai dokumen tingkat atas).
- Nested Frames tidak berfungsi dengan SAMEORIGIN dan ALLOW-FROM: Dalam situasi berikut, frame
X-Frame-Options Deprecated Meskipun header X-Frame-Options didukung oleh browser utama, header ini telah ditinggalkan dan digantikan oleh direktif frame-ancestors dari spesifikasi CSP Level 2
Proxies Proksi web terkenal karena menambahkan dan menghapus header. Jika proksi web menghapus header X-Frame-Options, situs tersebut kehilangan perlindungan framing-nya.
Skrip Pemutus Frame Browser Lama Terbaik Saat Ini¶
Salah satu cara untuk mencegah clickjacking adalah dengan menyertakan skrip "frame-breaker" di setiap halaman yang seharusnya tidak dibingkai. Metodologi berikut akan mencegah halaman web dibingkai bahkan di browser lama yang tidak mendukung X-Frame-Options-Header.
Pada elemen HEAD dokumen, tambahkan kode berikut:
Terapkan ID ke elemen gaya itu sendiri terlebih dahulu:
<style id="antiClickjack">
body{display:none !important;}
</style>
Kemudian, hapus gaya tersebut berdasarkan ID-nya segera setelah di skrip:
<script type="text/javascript">
if (self === top) {
var antiClickjack = document.getElementById("antiClickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
top.location = self.location;
}
</script>
Dengan cara ini, semuanya dapat berada di dokumen HEAD dan Anda hanya memerlukan satu metode/taglib di API Anda.
Perlindungan window.confirm()¶
Penggunaan X-Frame-Options atau skrip pemutus frame merupakan metode perlindungan clickjacking yang lebih aman. Namun, dalam skenario di mana konten harus dapat dibingkai, window.confirm() dapat digunakan untuk membantu mengurangi Clickjacking dengan memberi tahu pengguna tentang tindakan yang akan mereka lakukan.
Memanggil window.confirm() akan menampilkan jendela pop-up yang tidak dapat dibingkai. Jika window.confirm() berasal dari dalam iframe dengan domain yang berbeda dari induknya, maka kotak dialog akan menampilkan domain asal window.confirm(). Dalam skenario ini, peramban menampilkan asal kotak dialog untuk membantu mengurangi serangan Clickjacking. Misalnya:
<script type="text/javascript">
var action_confirm = window.confirm("Are you sure you want to delete your youtube account?")
if (action_confirm) {
//... Perform action
} else {
//... The user does not want to perform the requested action.`
}
</script>
Skrip Tidak Aman yang Tidak Berfungsi JANGAN DIGUNAKAN¶
Perhatikan cuplikan kode berikut yang TIDAK direkomendasikan untuk melindungi dari clickjacking:
<script>if (top!=self) top.location.href=self.location.href</script>
Skrip pemutus bingkai sederhana ini mencoba mencegah halaman dimasukkan ke dalam bingkai atau iframe dengan memaksa jendela induk memuat URL bingkai saat ini. Sayangnya, beberapa cara untuk menggagalkan skrip jenis ini telah dipublikasikan. Kami menguraikan beberapa di antaranya di sini.
Pembingkaian Ganda¶
Beberapa teknik pembobolan bingkai menavigasi ke halaman yang benar dengan menetapkan nilai ke parent.location. Ini berfungsi dengan baik jika halaman korban dibingkai oleh satu halaman. Namun, jika penyerang mengurung korban dalam satu bingkai di dalam bingkai lain (bingkai ganda), maka mengakses parent.location menjadi pelanggaran keamanan di semua peramban populer, karena kebijakan navigasi bingkai turunan. Pelanggaran keamanan ini menonaktifkan navigasi tindakan balasan.
Victim frame busting code:
if(top.location != self.location) {
parent.location = self.location;
}
Attacker top frame:
<iframe src="attacker2.html">
Attacker sub-frame:
<iframe src="http://www.victim.com">
Peristiwa onBeforeUnload¶
Pengguna dapat secara manual membatalkan permintaan navigasi apa pun yang dikirimkan oleh halaman yang dibingkai. Untuk memanfaatkan hal ini, halaman bingkai mendaftarkan pengendali onBeforeUnload yang dipanggil setiap kali halaman bingkai akan dibongkar karena navigasi. Fungsi pengendali ini mengembalikan string yang menjadi bagian dari prompt yang ditampilkan kepada pengguna.
Misalnya, penyerang ingin membingkai PayPal. Ia mendaftarkan fungsi pengendali unload yang mengembalikan string "Apakah Anda ingin keluar dari PayPal?". Ketika string ini ditampilkan kepada pengguna, kemungkinan besar navigasi akan dibatalkan, sehingga menggagalkan upaya pembobolan bingkai PayPal.
Penyerang melancarkan serangan ini dengan mendaftarkan peristiwa unload di halaman atas menggunakan kode berikut:
<script>
window.onbeforeunload = function(){
return "Asking the user nicely";
}
</script>
<iframe src="http://www.paypal.com">
Kode pembongkar bingkai PayPal akan menghasilkan peristiwa BeforeUnload yang mengaktifkan fungsi kami dan meminta pengguna untuk membatalkan peristiwa navigasi.
No-Content Flushing¶
Meskipun serangan sebelumnya memerlukan interaksi pengguna, serangan yang sama dapat dilakukan tanpa meminta izin pengguna. Peramban modern memungkinkan penyerang untuk secara otomatis membatalkan permintaan navigasi yang masuk dalam pengendali peristiwa onBeforeUnload dengan mengirimkan permintaan navigasi berulang kali ke situs yang merespons dengan "204 - No Content".
Menavigasi ke situs Tanpa Konten pada dasarnya merupakan NOP, tetapi akan membersihkan alur permintaan, sehingga membatalkan permintaan navigasi awal. Berikut contoh kode untuk melakukannya:
var preventbust = 0
window.onbeforeunload = function() { killbust++ }
setInterval( function() {
if(killbust > 0){
killbust = 2;
window.top.location = 'http://nocontent204.com'
}
}, 1);
<iframe src="http://www.victim.com">
Zona terbatas¶
Sebagian besar frame busting bergantung pada JavaScript di halaman yang dibingkai untuk mendeteksi pembingkaian dan melakukan pembingkaian sendiri. Jika JavaScript dinonaktifkan dalam konteks subframe, kode frame busting tidak akan berjalan. Sayangnya, ada beberapa cara untuk membatasi JavaScript di subframe:
Chrome:
<iframe src="http://www.victim.com" sandbox></iframe>
Firefox
Aktifkan designMode di halaman induk. Meskipun designMode masih didukung di peramban modern, efektivitasnya sebagai vektor serangan clickjacking dapat bervariasi di versi peramban saat ini.
document.designMode = "on";