Model keamanan web berakar pada kebijakan origin yang sama. Kode
dari https://mybank.com
hanya boleh memiliki akses ke data
https://mybank.com
, dan https://evil.example.com
seharusnya tidak pernah diizinkan aksesnya.
Setiap origin tetap terisolasi dari bagian web lainnya, sehingga memberi developer sandbox
yang aman untuk membangun dan bermain. Secara teori, ini benar-benar brilian. Pada praktiknya, penyerang telah menemukan cara pintar untuk merusak sistem.
Serangan pembuatan skrip lintas situs (XSS), misalnya, mengabaikan kebijakan origin yang sama dengan mengelabui situs agar mengirimkan kode berbahaya bersama dengan konten yang diinginkan. Ini adalah masalah besar, karena browser memercayai semua kode yang muncul di halaman sebagai bagian yang sah dari asal keamanan halaman tersebut. Tips Praktis XSS adalah panduan lintas bagian yang lama namun representatif dari metode yang mungkin digunakan penyerang untuk melanggar kepercayaan ini dengan memasukkan kode berbahaya. Jika penyerang berhasil memasukkan apa pun kode, itu sudah hampir selesai: data sesi pengguna disusupi dan informasi yang harus dirahasiakan akan dieksfiltrasi ke The Bad Guys. Tentu saja kami akan mencegah hal itu terjadi.
Ringkasan ini menyoroti pertahanan yang dapat secara signifikan mengurangi risiko dan dampak serangan XSS di browser modern: Kebijakan Keamanan Konten (CSP).
TL;DR (Ringkasan)
- Gunakan daftar yang diizinkan untuk memberi tahu klien apa saja yang diizinkan dan tidak diizinkan.
- Pelajari perintah yang tersedia.
- Ketahui kata kunci yang mereka ambil.
- Kode inline dan
eval()
dianggap berbahaya. - Laporkan pelanggaran kebijakan ke server Anda sebelum menerapkannya.
Daftar sumber yang diizinkan
Masalah yang dieksploitasi oleh serangan XSS adalah ketidakmampuan browser untuk membedakan
antara skrip yang merupakan bagian dari aplikasi dan skrip yang telah
diinjeksikan dengan niat jahat oleh pihak ketiga. Misalnya, tombol +1 Google di bagian bawah halaman ini memuat dan mengeksekusi kode dari https://apis.google.com/js/plusone.js
dalam konteks asal halaman ini. Kami
mempercayai kode itu, tetapi kami tidak dapat mengharapkan browser untuk mengetahui sendiri bahwa kode
dari apis.google.com
luar biasa, sedangkan kode dari apis.evil.example.com
mungkin tidak. Browser dengan senang hati mendownload dan menjalankan kode apa pun yang diminta halaman, apa pun sumbernya.
Alih-alih memercayai semua yang diberikan server, CSP menentukan
header HTTP Content-Security-Policy
, yang memungkinkan Anda membuat daftar sumber
konten tepercaya yang diizinkan, dan menginstruksikan browser untuk hanya mengeksekusi atau merender
resource dari sumber tersebut. Meskipun penyerang dapat menemukan lubang untuk
memasukkan skrip, skrip tidak akan cocok dengan daftar yang diizinkan, sehingga tidak akan
dieksekusi.
Karena kita memercayai apis.google.com
untuk mengirimkan kode yang valid, dan kita memercayai diri kita
untuk melakukan hal yang sama, mari tentukan kebijakan yang hanya mengizinkan skrip untuk dijalankan jika
berasal dari salah satu dari dua sumber tersebut:
Content-Security-Policy: script-src 'self' https://apis.google.com
Sederhana, bukan? Seperti yang mungkin sudah Anda duga, script-src
adalah perintah yang
mengontrol sekumpulan hak istimewa terkait skrip untuk halaman tertentu. Kami telah menetapkan
'self'
sebagai satu sumber skrip yang valid, dan https://apis.google.com
sebagai
sumber skrip lainnya. Browser dengan patuh mendownload dan menjalankan JavaScript dari
apis.google.com
melalui HTTPS, serta dari asal halaman saat ini.
Setelah kebijakan ini ditentukan, browser hanya akan menampilkan error, bukan memuat skrip dari sumber lainnya. Jika penyerang yang pintar berhasil memasukkan kode ke situs Anda, ia akan langsung mendapatkan pesan error, dan bukan mendapatkan keberhasilan yang diharapkan.
Kebijakan berlaku untuk berbagai macam resource
Meskipun resource skrip merupakan risiko keamanan yang paling jelas, CSP menyediakan beragam
rangkaian perintah kebijakan yang memungkinkan kontrol yang cukup terperinci atas resource
yang dapat dimuat oleh halaman. Anda sudah melihat script-src
, jadi konsepnya
harus jelas.
Mari kita telusuri dengan cepat perintah sumber daya lainnya. Daftar di bawah ini menunjukkan status perintah pada tingkat 2. Spesifikasi level 3 telah dipublikasikan, tetapi sebagian besar tidak diterapkan di browser utama.
base-uri
membatasi URL yang dapat muncul di elemen<base>
halaman.child-src
mencantumkan URL untuk pekerja dan konten frame tersemat. Misalnya:child-src https://youtube.com
akan memungkinkan penyematan video dari YouTube, tetapi bukan dari origin lainnya.connect-src
membatasi origin yang dapat Anda hubungkan (melalui XHR, WebSockets, dan EventSource).font-src
menentukan origin yang dapat menyalurkan font web. Font web Google dapat diaktifkan melaluifont-src https://themes.googleusercontent.com
.form-action
mencantumkan endpoint yang valid untuk pengiriman dari tag<form>
.frame-ancestors
menentukan sumber yang dapat menyematkan halaman saat ini. Perintah ini berlaku untuk tag<frame>
,<iframe>
,<embed>
, dan<applet>
. Perintah ini tidak dapat digunakan dalam tag<meta>
dan hanya berlaku untuk resource non-HTML.frame-src
tidak digunakan lagi di level 2, tetapi dipulihkan di level 3. Jika tidak ditampilkan, nilai akan kembali kechild-src
seperti sebelumnya.img-src
menentukan origin tempat gambar dapat dimuat.media-src
membatasi origin yang diizinkan untuk menayangkan video dan audio.object-src
memungkinkan kontrol atas plugin Flash dan plugin lainnya.plugin-types
membatasi jenis plugin yang dapat dipanggil oleh halaman.report-uri
menentukan URL tempat browser akan mengirim laporan saat kebijakan keamanan konten dilanggar. Perintah ini tidak dapat digunakan dalam tag<meta>
.style-src
adalah pasanganscript-src
untuk stylesheet.upgrade-insecure-requests
menginstruksikan agen pengguna untuk menulis ulang skema URL, mengubah HTTP ke HTTPS. Perintah ini ditujukan untuk situs dengan banyak URL lama yang perlu ditulis ulang.worker-src
adalah perintah CSP Level 3 yang membatasi URL yang dapat dimuat sebagai pekerja, pekerja bersama, atau pekerja layanan. Mulai Juli 2017, perintah ini memiliki penerapan yang terbatas.
Secara default, direktif terbuka lebar. Jika Anda tidak menetapkan kebijakan khusus untuk suatu perintah, misalkan font-src
, maka perintah tersebut akan berperilaku secara default meskipun Anda telah menentukan *
sebagai sumber yang valid (misalnya, Anda dapat memuat font dari mana saja, tanpa batasan).
Anda dapat mengganti perilaku default ini dengan menentukan perintah
default-src
. Perintah ini menentukan default untuk sebagian besar
perintah yang dibiarkan tidak ditentukan. Secara umum, ini berlaku untuk perintah apa pun yang
diakhiri dengan -src
. Jika default-src
disetel ke https://example.com
, dan Anda gagal
menentukan perintah font-src
, Anda dapat memuat font dari
https://example.com
, bukan dari tempat lain. Kita hanya menentukan script-src
dalam contoh
sebelumnya, yang berarti gambar, font, dan sebagainya dapat dimuat dari
asal mana pun.
Perintah berikut tidak menggunakan default-src
sebagai penggantian. Ingat bahwa tidak menetapkan mereka sama dengan mengizinkan apa pun.
base-uri
form-action
frame-ancestors
plugin-types
report-uri
sandbox
Anda dapat menggunakan sebanyak atau sesedikit mungkin perintah ini untuk aplikasi spesifik Anda, cukup dengan mencantumkan setiap perintah di header HTTP, dan memisahkan perintah dengan titik koma. Pastikan Anda mencantumkan semua
resource yang diperlukan dari jenis tertentu dalam satu perintah. Jika Anda menulis sesuatu seperti script-src https://host1.com; script-src https://host2.com
, perintah kedua akan diabaikan. Sesuatu seperti berikut akan
menentukan kedua origin dengan benar sebagai valid:
script-src https://host1.com https://host2.com
Misalnya, jika Anda memiliki aplikasi yang memuat semua resource-nya dari
jaringan penayangan konten (misalnya, https://cdn.example.net
), dan mengetahui bahwa Anda
tidak memerlukan konten atau plugin dalam frame, kebijakan Anda mungkin terlihat seperti
berikut:
Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'
Detail implementasi
Anda akan melihat header X-WebKit-CSP
dan X-Content-Security-Policy
dalam berbagai
tutorial di web. Ke depannya, Anda harus mengabaikan
header berawalan ini. Browser modern (dengan pengecualian IE) mendukung header
Content-Security-Policy
tanpa awalan. Itulah {i>header<i} yang harus Anda gunakan.
Apa pun header yang digunakan, kebijakan ditentukan berdasarkan halaman demi halaman: Anda harus mengirim header HTTP beserta setiap respons yang ingin Anda pastikan terlindungi. Cara ini memberikan banyak fleksibilitas, karena Anda dapat menyesuaikan kebijakan untuk halaman tertentu berdasarkan kebutuhan spesifiknya. Mungkin satu kumpulan halaman di situs Anda memiliki tombol +1, sementara yang lain tidak: Anda dapat mengizinkan kode tombol dimuat hanya jika diperlukan.
Daftar sumber di setiap perintah bersifat fleksibel. Anda dapat menentukan sumber berdasarkan
skema (data:
, https:
), atau mulai dari kekhususan dari nama host
(example.com
, yang cocok dengan origin apa pun di host tersebut: skema apa pun, port apa pun) hingga
URI yang sepenuhnya memenuhi syarat (https://example.com:443
, yang hanya cocok dengan HTTPS, hanya
example.com
, dan hanya port 443). Karakter pengganti diterima, tetapi hanya sebagai skema,
port, atau di posisi paling kiri nama host: *://*.example.com:*
akan
cocok dengan semua subdomain example.com
(tetapi bukan example.com
itu sendiri), menggunakan
skema apa pun, di port mana pun.
Daftar sumber juga menerima empat kata kunci:
'none'
, seperti yang mungkin Anda harapkan, tidak cocok.'self'
cocok dengan asal saat ini, tetapi tidak subdomainnya.'unsafe-inline'
mengizinkan JavaScript dan CSS inline. (Kita akan membahasnya secara lebih detail sebentar lagi.)'unsafe-eval'
mengizinkan mekanisme teks ke JavaScript sepertieval
. (Kita juga akan membahasnya.)
Kata kunci ini memerlukan tanda kutip tunggal. Misalnya, script-src 'self'
(dengan tanda kutip) mengizinkan eksekusi JavaScript dari host saat ini; script-src self
(tanpa tanda kutip) memungkinkan JavaScript dari server bernama "self
" (dan bukan dari host saat ini), yang mungkin bukan maksud Anda.
Sandboxing
Ada satu perintah lagi yang perlu dibahas: sandbox
. Ini sedikit
berbeda dari lainnya yang telah kita lihat, karena perintah ini menempatkan batasan pada tindakan
yang dapat diambil halaman, bukan pada resource yang dapat dimuat halaman. Jika
perintah sandbox
ada, halaman akan diperlakukan seolah-olah dimuat
di dalam <iframe>
dengan atribut sandbox
. Hal ini dapat memiliki berbagai
efek di halaman: memaksa halaman ke asal yang unik, dan mencegah pengiriman
formulir. Ini sedikit di luar cakupan artikel ini, tetapi Anda dapat menemukan detail lengkap tentang atribut sandbox yang valid di bagian "Sandboxing" pada spesifikasi HTML5.
Tag meta
Mekanisme pengiriman yang disukai CSP adalah header HTTP. Namun, sebaiknya setel kebijakan di halaman secara langsung di markup. Lakukan hal tersebut menggunakan tag <meta>
dengan
atribut http-equiv
:
<meta
http-equiv="Content-Security-Policy"
content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>
Fitur ini tidak dapat digunakan untuk frame-ancestors
, report-uri
, atau sandbox
.
Kode {i>inline<i} dianggap berbahaya
Jelas bahwa CSP didasarkan pada asal daftar yang diizinkan, karena ini merupakan cara yang tidak ambigu untuk menginstruksikan browser memperlakukan kumpulan resource tertentu sebagai dapat diterima dan menolak sisanya. Namun, daftar yang diizinkan berbasis origin tidak
menyelesaikan ancaman terbesar yang ditimbulkan oleh serangan XSS: injeksi skrip inline.
Jika penyerang dapat memasukkan tag skrip yang secara langsung berisi beberapa payload
berbahaya (<script>sendMyDataToEvilDotCom();</script>
),
browser tidak memiliki mekanisme yang dapat digunakan untuk membedakannya dengan tag skrip inline
yang sah. CSP mengatasi masalah ini dengan memblokir skrip inline sepenuhnya:
ini adalah satu-satunya cara untuk memastikan.
Pemblokiran ini tidak hanya mencakup skrip yang disematkan secara langsung di tag script
, tetapi juga
pengendali peristiwa inline dan URL javascript:
. Anda harus memindahkan konten
tag script
ke file eksternal, dan mengganti URL javascript:
dan <a ... onclick="[JAVASCRIPT]">
dengan panggilan addEventListener()
yang sesuai. Misalnya, Anda dapat menulis ulang kode berikut ini dari:
<script>
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>
menjadi sesuatu yang lebih seperti:
<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>
<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('amazing').addEventListener('click', doAmazingThings);
});
Kode yang ditulis ulang memiliki sejumlah keunggulan yang sangat bagus untuk digunakan bersama CSP. Kode ini sudah menjadi praktik terbaik, terlepas dari penggunaan CSP Anda. JavaScript inline menggabungkan struktur dan perilaku dengan cara yang tidak seharusnya. Resource eksternal lebih mudah di-cache oleh browser, lebih mudah dipahami oleh developer, serta kondusif untuk kompilasi dan minifikasi. Anda akan menulis kode yang lebih baik jika melakukan pemindahan kode ke resource eksternal.
Gaya inline diperlakukan dengan cara yang sama: atribut style
dan tag style
harus digabungkan ke dalam stylesheet eksternal untuk melindungi
dari berbagai metode pemindahan data yang sangat pintar
yang dimungkinkan oleh CSS.
Jika harus memiliki skrip dan gaya inline, Anda dapat mengaktifkannya
dengan menambahkan 'unsafe-inline'
sebagai sumber yang diizinkan dalam perintah
script-src
atau style-src
. Anda juga dapat menggunakan nonce atau {i>hash<i} (lihat di bawah ini), tetapi sebaiknya tidak.
Pemblokiran skrip inline adalah keuntungan keamanan terbesar yang disediakan CSP, dan
pemblokiran gaya inline juga akan memperkuat aplikasi Anda. Dibutuhkan sedikit
upaya untuk memastikan semuanya berfungsi dengan benar setelah memindahkan semua kode
keluar dari baris, tetapi itu adalah konsekuensi yang patut dilakukan.
Jika Anda terpaksa harus
CSP Level 2 menawarkan kompatibilitas mundur untuk skrip inline dengan memungkinkan Anda menambahkan skrip inline tertentu ke daftar yang diizinkan menggunakan nonce kriptografis (angka digunakan satu kali) atau hash. Meskipun merepotkan, cara ini cukup berguna.
Untuk menggunakan nonce, berikan atribut nonce pada tag skrip Anda. Nilainya harus sama dengan salah satu nilai dalam daftar sumber tepercaya. Contoh:
<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
// Some inline code I can't remove yet, but need to asap.
</script>
Sekarang, tambahkan nonce ke perintah script-src
Anda yang ditambahkan ke kata kunci nonce-
.
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
Ingat bahwa nonce harus dibuat ulang untuk setiap permintaan halaman dan harus tidak dapat ditebak.
{i>Hash<i} bekerja dengan
cara yang hampir sama. Daripada menambahkan kode ke tag skrip, buat hash SHA skrip itu sendiri dan tambahkan ke perintah script-src
.
Misalnya, halaman Anda berisi ini:
<script>
alert('Hello, world.');
</script>
Kebijakan Anda akan berisi hal berikut:
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
Ada beberapa hal yang perlu diperhatikan di sini. Awalan sha*-
menentukan algoritma
yang menghasilkan hash. Dalam contoh di atas, sha256-
digunakan. CSP juga mendukung sha384-
dan sha512-
. Saat membuat hash, jangan sertakan
tag <script>
. Kapitalisasi dan spasi kosong juga sangat penting, termasuk spasi kosong di awal atau di akhir.
Penelusuran Google tentang cara membuat hash SHA akan mengarahkan Anda ke solusi dalam sejumlah bahasa. Dengan Chrome 40 atau yang lebih baru, Anda dapat membuka DevTools lalu memuat ulang halaman. Tab Console akan berisi pesan error dengan hash sha256 yang benar untuk setiap skrip inline Anda.
Evaluasi juga
Meskipun penyerang tidak dapat menginjeksikan skrip secara langsung, penyerang tersebut mungkin dapat mengelabui
aplikasi Anda agar mengonversi teks inert menjadi JavaScript yang dapat dieksekusi
dan mengeksekusinya atas nama mereka. eval()
, new
Function() , setTimeout([string], ...)
, dan
setInterval([string], ...)
adalah vektor yang membuat teks yang
diinjeksi dapat mengeksekusi sesuatu yang berbahaya secara tidak terduga. Respons default CSP terhadap risiko ini adalah memblokir sepenuhnya semua vektor tersebut.
Dampaknya tidak cukup besar pada cara Anda membangun aplikasi:
- Anda harus mengurai JSON melalui
JSON.parse
bawaan, bukan mengandalkaneval
. Operasi JSON native tersedia di setiap browser mulai dari IE8, dan sepenuhnya aman. - Tulis ulang panggilan
setTimeout
atausetInterval
yang saat ini Anda lakukan dengan fungsi inline, bukan string. Contoh:
setTimeout("document.querySelector('a').style.display = 'none';", 10);
akan lebih baik ditulis sebagai:
setTimeout(function () {
document.querySelector('a').style.display = 'none';
}, 10);
- Hindari pembuatan template inline saat runtime: Banyak library pembuatan template menggunakan
new Function()
secara bebas untuk mempercepat pembuatan template saat runtime. Machine learning merupakan aplikasi yang bagus dari pemrograman dinamis, tetapi berisiko mengevaluasi teks yang berbahaya. Beberapa framework otomatis mendukung CSP, yang beralih kembali ke parser yang tangguh jika tidak adaeval
. Perintah ng-csp dari AngularJS adalah contoh yang baik untuk perintah ini.
Namun, pilihan yang lebih baik adalah bahasa template yang menawarkan
prakompilasi (misalnya,
Handlebars). Prakompilasi template dapat membuat pengalaman pengguna jauh
lebih cepat daripada implementasi runtime tercepat, dan juga lebih aman. Jika eval dan saudara teks ke JavaScript-nya sangat penting untuk aplikasi, Anda dapat mengaktifkannya dengan menambahkan 'unsafe-eval'
sebagai sumber yang diizinkan dalam perintah script-src
, tetapi kami sangat tidak menyarankannya. Pemblokiran kemampuan untuk mengeksekusi
string akan mempersulit penyerang untuk mengeksekusi kode
yang tidak sah di situs Anda.
Pelaporan
Kemampuan CSP untuk memblokir resource yang tidak tepercaya di sisi klien memberikan keuntungan besar bagi pengguna
Anda, tetapi akan sangat membantu jika memiliki beberapa jenis notifikasi
yang dikirim kembali ke server sehingga Anda dapat mengidentifikasi dan menghancurkan semua bug yang memungkinkan
injeksi berbahaya sejak awal. Untuk melakukannya, Anda dapat menginstruksikan
browser ke POST
laporan pelanggaran berformat JSON ke lokasi
yang ditentukan dalam perintah report-uri
.
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
Laporan tersebut akan terlihat seperti berikut:
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
Ini berisi bagian informasi yang bagus yang akan membantu Anda melacak
penyebab spesifik pelanggaran, termasuk halaman tempat pelanggaran
terjadi (document-uri
), perujuk halaman tersebut (perhatikan bahwa tidak seperti kolom header
HTTP, kuncinya tidak salah eja), resource yang melanggar
kebijakan halaman (blocked-uri
), perintah spesifik yang dilanggar
(violated-directive
), dan kebijakan lengkap halaman (original-policy
).
Hanya Laporan
Jika Anda baru mulai menggunakan CSP, sebaiknya evaluasi status aplikasi saat ini
sebelum meluncurkan kebijakan yang kejam kepada pengguna.
Sebagai batu loncatan untuk menyelesaikan deployment, Anda dapat meminta browser untuk memantau kebijakan, melaporkan pelanggaran, tetapi tidak menerapkan pembatasan. Kirim header Content-Security-Policy-Report-Only
, bukan mengirim header Content-Security-Policy
.
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
Kebijakan yang ditetapkan dalam mode laporan saja tidak akan memblokir resource yang dibatasi, tetapi akan mengirim laporan pelanggaran ke lokasi yang Anda tentukan. Anda bahkan dapat mengirim kedua header, dengan menerapkan satu kebijakan sekaligus memantau kebijakan lainnya. Ini adalah cara yang tepat untuk mengevaluasi efek perubahan pada CSP aplikasi Anda: aktifkan pelaporan untuk kebijakan baru, pantau laporan pelanggaran, dan perbaiki bug yang muncul; jika Anda sudah puas dengan efeknya, mulailah menerapkan kebijakan baru.
Penggunaan di Dunia Nyata
CSP 1 cukup dapat digunakan di Chrome, Safari, dan Firefox, tetapi memiliki dukungan yang sangat terbatas di IE 10. Anda dapat melihat detail selengkapnya di caniuse.com. CSP Level 2 telah tersedia di Chrome sejak versi 40. Situs besar seperti Twitter dan Facebook telah men-deploy header tersebut (studi kasus Twitter layak dibaca), dan standarnya sangat siap bagi Anda untuk mulai di-deploy di situs Anda sendiri.
Langkah pertama dalam membuat kebijakan untuk aplikasi Anda adalah mengevaluasi resource yang benar-benar Anda muat. Setelah Anda merasa memahami cara menggabungkan berbagai hal dalam aplikasi Anda, siapkan kebijakan berdasarkan persyaratan tersebut. Mari kita pelajari beberapa kasus penggunaan umum dan tentukan cara terbaik untuk mendukungnya dalam batasan perlindungan CSP.
Kasus penggunaan #1: widget media sosial
Tombol +1 Google menyertakan skrip dari
https://apis.google.com
, dan menyematkan<iframe>
darihttps://plusone.google.com
. Anda memerlukan kebijakan yang menyertakan kedua origin ini agar dapat menyematkan tombol. Kebijakan minimalnya adalahscript-src https://apis.google.com; child-src https://plusone.google.com
. Anda juga harus memastikan bahwa cuplikan JavaScript yang disediakan Google ditarik ke dalam file JavaScript eksternal. Jika Anda memiliki kebijakan berbasis Level 1 yang menggunakanframe-src
Level 2, Anda harus mengubahnya menjadichild-src
. Ini tidak lagi diperlukan di CSP Level 3.Tombol Suka Facebook memiliki sejumlah opsi implementasi. Sebaiknya tetap gunakan versi
<iframe>
karena sudah di-sandbox dengan aman dari bagian lain situs Anda. Diperlukan perintahchild-src https://facebook.com
agar dapat berfungsi dengan benar. Perlu diketahui bahwa, secara default, kode<iframe>
yang disediakan Facebook akan memuat URL relatif,//facebook.com
. Ubah bahwa untuk menentukan HTTPS secara eksplisit:https://facebook.com
. Anda tidak perlu menggunakan HTTP jika tidak perlu.Tombol Tweet Twitter mengandalkan akses ke skrip dan frame, keduanya dihosting di
https://platform.twitter.com
. (Selain itu, Twitter menyediakan URL relatif secara default; edit kode untuk menentukan HTTPS saat menyalin/menempelnya secara lokal.) Anda akan siap menggunakanscript-src https://platform.twitter.com; child-src https://platform.twitter.com
selama Anda memindahkan cuplikan JavaScript yang disediakan Twitter ke dalam file JavaScript eksternal.Platform lain memiliki persyaratan serupa, dan dapat ditangani dengan cara serupa. Sebaiknya cukup setel
default-src
dari'none'
, dan pantau konsol Anda untuk menentukan resource mana yang perlu Anda aktifkan agar widget berfungsi.
Penyertaan beberapa widget sangat mudah: cukup gabungkan perintah kebijakan, dan ingat untuk menggabungkan semua resource dari satu jenis menjadi satu perintah. Jika Anda menginginkan ketiga widget media sosial tersebut, kebijakannya akan terlihat seperti ini:
script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com
Kasus penggunaan #2: kunci total
Asumsikan bahwa Anda menjalankan situs perbankan dan ingin memastikan bahwa
hanya resource yang telah Anda tulis sendiri yang dapat dimuat. Dalam skenario ini,
mulai dengan kebijakan default yang memblokir semuanya (default-src 'none'
), lalu lanjutkan dari sana.
Misalkan bank memuat semua gambar, gaya, dan skrip dari CDN di https://cdn.mybank.net
, dan terhubung melalui XHR ke https://api.mybank.com/
untuk menarik berbagai bit data. Frame digunakan, tetapi hanya untuk halaman yang bersifat lokal ke
situs (tidak ada origin pihak ketiga). Tidak ada Flash di situs, tidak ada font, tidak ada
tambahan. Header CSP paling ketat yang bisa kita kirim adalah ini:
Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'
Kasus penggunaan #3: khusus SSL
Seorang admin forum diskusi cincin pernikahan ingin memastikan bahwa semua resource hanya dimuat melalui saluran yang aman, tetapi tidak benar-benar menulis banyak kode; menulis ulang sebagian besar software forum pihak ketiga yang diisi sampai ke tepi dengan skrip dan gaya inline berada di luar kemampuannya. Kebijakan berikut akan berlaku:
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
Meskipun https:
ditentukan dalam default-src
, perintah skrip dan gaya tidak otomatis mewarisi sumber tersebut. Setiap perintah sepenuhnya
menimpa default untuk jenis resource tertentu.
Acara mendatang
Kebijakan Keamanan Konten Level 2 adalah Rekomendasi Kandidat. Web Application Security Working Group W3C telah mulai mengerjakan iterasi spesifikasi berikutnya, Kebijakan Keamanan Konten Level 3.
Jika Anda tertarik dengan diskusi seputar fitur mendatang ini, lihat arsip milis public-webappsec@, atau gabung ke dalam diskusi dengan Anda.