Model keamanan web berakar pada
kebijakan origin yang sama. Kode
dari https://mybank.com
hanya boleh mengakseshttps://mybank.com
data, dan https://evil.example.com
tentu saja tidak boleh
mengizinkan akses.
Setiap origin tetap terisolasi dari keseluruhan web, sehingga memberikan keamanan bagi developer
sandbox tempat membangun dan bermain. Secara teori, ini benar-benar brilian. Di beberapa
penyerang telah menemukan cara
cerdas untuk menumbangkan sistem.
Pembuatan skrip lintas situs (XSS) serangan, misalnya, mengabaikan kebijakan origin yang sama dengan mengelabui situs agar mengirimkan kode berbahaya beserta konten yang diinginkan. Ini adalah pengalaman karena browser memercayai semua kode yang muncul di halaman sebagai merupakan bagian sah dari asal keamanan halaman tersebut. Tujuan Tips Praktis XSS adalah lintas metode yang sudah lama namun representatif dan mungkin digunakan melanggar kepercayaan ini dengan cara memasukkan kode berbahaya. Jika penyerang berhasil memasukkan kode apa pun, ini sudah selesai: data sesi pengguna disusupi dan informasi yang harus dirahasiakan yang dipindahkan ke The Bad Teman-teman. Tentu saja kami akan mencegah hal itu terjadi.
Ikhtisar ini menyoroti pertahanan yang dapat mengurangi risiko dan dampak serangan XSS di browser modern: Kebijakan Keamanan Konten (CSP).
TL;DR
- 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 Anda dan skrip yang telah
secara berbahaya oleh
pihak ketiga. Misalnya, tombol +1 Google di
bagian bawah halaman ini memuat dan menjalankan kode dari
https://apis.google.com/js/plusone.js
dalam konteks asal halaman ini. Rab
memercayai kode itu, tetapi kita tidak bisa berharap {i>browser<i}
mengetahui kode itu sendiri
dari apis.google.com
luar biasa, sedangkan kode dari apis.evil.example.com
mungkin tidak. Browser dengan senang hati mendownload dan mengeksekusi kode apa pun
permintaan, terlepas dari sumbernya.
CSP mendefinisikan atribut semua yang diberikan server, bukan memercayai
header HTTP Content-Security-Policy
, yang memungkinkan Anda membuat daftar
sumber konten tepercaya, dan menginstruksikan browser untuk hanya menjalankan atau merender
resource dari sumber tersebut. Bahkan jika penyerang dapat
menemukan lubang yang bisa dilalui
untuk memasukkan skrip, skrip tidak akan cocok dengan daftar yang diizinkan, sehingga tidak akan
telah dijalankan.
Karena kita memercayai apis.google.com
untuk mengirimkan kode yang valid, dan kita mempercayai diri sendiri
untuk melakukan hal yang sama, mari kita tentukan kebijakan yang
hanya mengizinkan skrip untuk dieksekusi
berasal dari salah satu dari dua sumber berikut:
Content-Security-Policy: script-src 'self' https://apis.google.com
Sederhana, bukan? Seperti yang mungkin Anda duga, script-src
adalah perintah yang
mengontrol sekumpulan hak istimewa terkait skrip untuk halaman tertentu. Kita telah menentukan
'self'
sebagai satu sumber skrip yang valid, dan https://apis.google.com
sebagai
lain. Browser dengan patuh mengunduh dan
menjalankan JavaScript dari
apis.google.com
melalui HTTPS, serta dari asal halaman saat ini.
Setelah kebijakan ini ditetapkan, browser akan menampilkan error, bukan memuat skrip dari sumber lain. Ketika penyerang yang pintar berhasil memasukkan kode ke situs, maka mereka akan langsung menerima pesan {i>error<i}, dari kesuksesan yang mereka harapkan.
Kebijakan berlaku untuk berbagai macam resource
Meskipun sumber daya skrip adalah risiko keamanan yang paling jelas, CSP menyediakan
serangkaian perintah kebijakan yang memungkinkan kontrol yang cukup terperinci atas resource
bahwa halaman diizinkan untuk dimuat. Anda sudah melihat script-src
, jadi konsepnya
harus jelas.
Mari kita telusuri dengan cepat perintah sumber daya lainnya. Daftar di bawah ini mewakili status perintah pada tingkat 2. Spesifikasi level 3 telah dipublikasikan, tetapi sebagian besar tidak diterapkan dalam laporan browser.
base-uri
membatasi URL yang dapat muncul di elemen<base>
halaman.child-src
mencantumkan URL untuk pekerja dan konten frame tersemat. Sebagai contoh:child-src https://youtube.com
akan mengaktifkan penyematan video dari YouTube, tetapi bukan dari origin yang lain.connect-src
membatasi origin yang dapat Anda hubungkan (melalui XHR, WebSockets, dan EventSource).font-src
menentukan origin yang dapat menyalurkan font web. Web Google font 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 di tag<meta>
dan hanya berlaku untuk non-HTML Google Cloud Platform.frame-src
tidak digunakan lagi di level 2, tetapi dipulihkan di level 3. Jika tidak ada, nilai tersebut masih 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 yang akan digunakan browser untuk mengirim laporan kebijakan keamanan konten dilanggar. Perintah ini tidak dapat digunakan di<meta>
{i>tag<i}.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 web dengan sejumlah besar URL lama yang perlu ditulis ulang.worker-src
adalah perintah CSP Level 3 yang membatasi URL yang mungkin dimuat sebagai pekerja, pekerja bersama, atau pekerja layanan. Mulai Juli 2017, direktif memiliki penerapan yang terbatas.
Secara default, direktif terbuka lebar. Jika Anda tidak menetapkan
kebijakan khusus untuk
, misalkan font-src
, maka perintah tersebut secara default akan berperilaku sebagai
meskipun Anda telah menentukan *
sebagai sumber yang valid (misalnya, Anda dapat memuat font dari
di mana saja, tanpa batasan).
Anda dapat mengganti perilaku default ini dengan menentukan default-src
direktif. Direktif ini mendefinisikan
default untuk sebagian besar
direktif yang tidak ditentukan. Umumnya, ini berlaku
untuk setiap direktif yang
diakhiri dengan -src
. Jika default-src
disetel ke https://example.com
, dan Anda gagal
untuk menentukan direktif font-src
, maka Anda dapat memuat font dari
https://example.com
, dan tidak di tempat lain. Kita hanya menentukan script-src
dalam
contoh sebelumnya, yang berarti bahwa gambar, {i>font<i}, dan sebagainya dapat dimuat dari
asal apa pun.
Perintah berikut tidak menggunakan default-src
sebagai penggantian. Perlu diingat bahwa
gagal mengaturnya sama
dengan mengizinkan apa pun.
base-uri
form-action
frame-ancestors
plugin-types
report-uri
sandbox
Anda dapat menggunakan sebanyak atau sesedikit mungkin
direktif ini yang sesuai untuk
aplikasi tertentu, cukup mencantumkan
masing-masing di {i>header<i} HTTP, 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
direktif kedua
akan diabaikan. Sesuatu seperti berikut ini akan
menentukan kedua origin dengan benar sebagai valid:
script-src https://host1.com https://host2.com
Misalnya, jika Anda memiliki aplikasi yang memuat semua sumber dayanya dari
jaringan penayangan konten (misalnya, https://cdn.example.net
), dan mengetahui bahwa Anda
tidak memerlukan konten atau plugin berbingkai, maka kebijakan Anda mungkin terlihat
seperti berikut ini:
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 awalan ini
{i>header<i}. Browser modern (dengan pengecualian IE) mendukung awalan
Header Content-Security-Policy
. Itulah {i>header<i} yang harus Anda gunakan.
Terlepas dari header yang Anda gunakan, kebijakan ditentukan berdasarkan halaman demi halaman: Anda harus mengirim {i>header<i} HTTP beserta setiap respons yang ingin Anda dipastikan terlindungi. Hal ini memberikan banyak fleksibilitas, karena Anda dapat melakukan penyesuaian kebijakan untuk halaman tertentu berdasarkan kebutuhan spesifik mereka. Mungkin satu set halaman di situs Anda memiliki tombol +1, sementara yang lain tidak: Anda dapat mengizinkan kode tombol hanya dimuat jika diperlukan.
Daftar sumber di setiap perintah bersifat fleksibel. Anda dapat menentukan sumber dengan
skema (data:
, https:
), atau dengan kekhususan mulai dari nama host saja
(example.com
, yang cocok dengan origin apa pun di host tersebut: skema apa pun, port apa pun) dengan
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 dari example.com
(tetapi bukan example.com
itu sendiri), menggunakan
skema apa pun, di porta apa 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 di secara lebih detail sebentar lagi.)'unsafe-eval'
mengizinkan mekanisme teks ke JavaScript sepertieval
. (Kita akan mendapatkan dengan teks ini juga.)
Kata kunci ini memerlukan tanda kutip tunggal. Misalnya, script-src 'self'
(dengan tanda kutip)
memberikan otorisasi eksekusi JavaScript dari host saat ini; script-src self
(tanpa tanda kutip) mengizinkan JavaScript dari server bernama "self
" (dan bukan dari
{i>host<i} saat ini), yang mungkin bukan
yang Anda maksudkan.
Sandboxing
Ada satu perintah lagi yang patut dibahas: sandbox
. Sedikit peduli
berbeda dari yang lain yang telah kita lihat, karena
perintah ini menempatkan pembatasan pada tindakan
yang diambil oleh halaman, bukan pada
resource yang dapat dimuat halaman. Jika
Perintah sandbox
ada, halaman diperlakukan seolah-olah dimuat
di dalam <iframe>
dengan atribut sandbox
. {i>Dataframe<i} ini dapat memiliki berbagai
efek pada halaman: memaksa halaman ke asal yang unik, dan mencegah formulir
kiriman, antara lain. Ini sedikit di luar cakupan artikel ini, tetapi Anda
Anda dapat menemukan detail selengkapnya tentang atribut sandbox yang valid di
"Sandbox" di bagian spesifikasi HTML5.
Tag meta
Mekanisme pengiriman yang disukai CSP adalah header HTTP. Hal ini dapat berguna,
untuk menetapkan kebijakan pada laman
langsung di {i>markup<i}. Lakukan hal ini 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
Harus jelas bahwa CSP didasarkan pada origin daftar yang diizinkan, karena
cara yang tidak ambigu dalam memerintahkan browser untuk memperlakukan kumpulan resource tertentu
masih dapat diterima dan
menolak sisanya. Daftar yang diizinkan berbasis origin tidak
tetapi, mengatasi ancaman terbesar yang ditimbulkan oleh serangan XSS: injeksi skrip inline.
Jika penyerang dapat menyuntikkan tag skrip yang secara langsung berisi beberapa {i>malware <i}
payload (<script>sendMyDataToEvilDotCom();</script>
),
browser tidak memiliki mekanisme untuk membedakannya dari browser
tag skrip inline. CSP mengatasi masalah ini dengan memblokir skrip inline sepenuhnya:
satu-satunya cara
untuk memastikannya.
Larangan ini tidak hanya mencakup skrip yang disematkan langsung dalam tag script
, tetapi juga
pengendali peristiwa inline, dan javascript:
URL. Anda harus memindahkan konten
script
tag ke dalam file eksternal, dan ganti URL javascript:
dan <a ... onclick="[JAVASCRIPT]">
dengan panggilan addEventListener()
yang sesuai. Misalnya,
Anda dapat menulis ulang kode berikut ini:
<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 lebih dari sekedar bekerja dengan baik dengan CSP; itu sudah menjadi praktik terbaik, apa pun penggunaan CSP Anda. Bagian dari teks JavaScript mencampur struktur dan perilaku dengan cara yang tidak seharusnya Anda lakukan. Sumber daya eksternal lebih mudah di-cache oleh browser, lebih mudah dipahami developer, dan kondusif untuk kompilasi dan minifikasi. Anda akan menulis dengan lebih baik kode jika Anda melakukan pekerjaan untuk memindahkan kode ke resource eksternal.
Gaya inline diperlakukan dengan cara yang sama: atribut style
dan style
tag harus digabungkan ke dalam stylesheet eksternal untuk melindungi dari
variasi yang sangat pintar
metode pemindahan data yang tidak sah
yang dimungkinkan oleh CSS.
Jika harus memiliki skrip dan gaya inline, Anda dapat mengaktifkannya
dengan menambahkan 'unsafe-inline'
sebagai sumber yang diizinkan di script-src
atau style-src
direktif. Anda juga dapat menggunakan nonce atau {i>hash<i} (lihat di bawah ini), tetapi sebaiknya tidak.
Pemblokiran skrip sebaris adalah kemenangan keamanan terbesar yang disediakan CSP, dan
{i>banning<i} {i>inline<i} juga akan
mengeraskan aplikasi Anda. Ini sedikit
dari awal untuk memastikan bahwa semuanya
bekerja dengan benar setelah memindahkan semua kode
di luar cakupan, tapi itu adalah
kompromi yang layak dilakukan.
Jika Anda terpaksa harus
CSP Level 2 menawarkan kompatibilitas mundur untuk skrip sebaris dengan memungkinkan Anda untuk tambahkan skrip inline tertentu ke daftar yang diizinkan menggunakan nonce kriptografi (angka digunakan sekali) atau sebuah {i>hash.<i} Meskipun mungkin merepotkan, cara ini berguna terburu-buru.
Untuk menggunakan nonce, berikan atribut nonce pada tag skrip Anda. Nilainya harus sama dengan satu 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 bisa ditebak.
{i>Hash<i} bekerja dengan
cara yang hampir sama. Alih-alih 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 {i>hash<i}. Dalam contoh di atas, sha256-
digunakan. CSP juga
mendukung sha384-
dan sha512-
. Saat membuat {i>hash<i}, jangan sertakan
Tag <script>
. Kapitalisasi dan spasi kosong juga penting, termasuk awal atau
spasi kosong di akhir.
Penelusuran Google tentang pembuatan {i>hash<i} SHA akan mengarahkan Anda ke solusi dalam hal apa pun jumlah bahasa. Dengan Chrome 40 atau yang lebih baru, Anda bisa membuka DevTools lalu muat ulang halaman Anda. Tab Console akan berisi pesan {i>error<i} dengan {i>hash sha256<i} untuk setiap skrip {i>inline<i} Anda.
Evaluasi juga
Bahkan ketika penyerang tidak dapat menyuntikkan skrip secara langsung, mereka mungkin dapat mengelabui
aplikasi Anda menjadi konversi teks inert yang lain menjadi JavaScript yang dapat dieksekusi
dan mengeksekusinya atas nama mereka. eval()
, baru
Function() , setTimeout([string], ...)
, dan
setInterval([string], ...)
adalah semua vektor yang diinjeksikan
mungkin akhirnya mengeksekusi
sesuatu yang berbahaya secara tidak terduga. Default CSP
respons terhadap risiko ini adalah dengan memblokir
semua vektor ini.
Dampaknya tidak cukup besar pada cara Anda membangun aplikasi:
- Anda harus mengurai JSON melalui
JSON.parse
bawaan, bukan mengandalkaneval
. Operasi JSON bawaan tersedia di semua browser sejak IE8, dan ini benar-benar aman. - Menulis 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. Ini adalah aplikasi yang bagus dari pemrograman dinamis, tetapi berisiko mengevaluasi teks berbahaya. Beberapa kerangka kerja mendukung CSP siap pakai, kembali ke parser yang andal jika tidak adaeval
. Perintah ng-csp dari AngularJS adalah contoh yang baik.
Namun, pilihan yang lebih baik adalah bahasa template yang menawarkan
prakompilasi (Handlebars melakukannya,
). Prakompilasi {i>template<i} Anda dapat
membuat pengalaman pengguna
lebih cepat daripada implementasi
{i>runtime<i} tercepat, dan juga lebih aman. Jika eval dan
saudara teks-ke-JavaScript-nya sangat penting untuk aplikasi Anda, Anda dapat
aktifkan dengan menambahkan 'unsafe-eval'
sebagai sumber yang diizinkan di script-src
tetapi kami sangat tidak menyarankannya. Memblokir kemampuan untuk menjalankan
{i>string<i} akan mempersulit penyerang untuk
melakukan eksekusi tanpa izin
pada situs Anda.
Pelaporan
Kemampuan CSP untuk memblokir sumber daya yang tidak
tepercaya dari sisi klien adalah kemenangan besar bagi
pengguna, tetapi akan sangat membantu
untuk memiliki beberapa jenis notifikasi
dikirim kembali ke server sehingga Anda dapat mengidentifikasi
dan menghancurkan semua {i>bug<i} yang memungkinkan
injeksi berbahaya sejak awal. Untuk tujuan ini, Anda dapat menginstruksikan
browser agar POST
laporan pelanggaran berformat JSON ke suatu 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 sepotong informasi yang baik
yang akan membantu Anda melacak
penyebab spesifik pelanggaran, termasuk halaman tempat pelanggaran
terjadi (document-uri
), perujuk halaman tersebut (perhatikan bahwa tidak seperti permintaan HTTP
header, kunci 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, masuk akal untuk mengevaluasi
aplikasi Anda 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. Daripada fokus pada
mengirim header Content-Security-Policy
, mengirim
Header Content-Security-Policy-Report-Only
.
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 Google akan mengirimkan laporan pelanggaran ke lokasi yang Anda tentukan. Anda bahkan dapat mengirim kedua header, menerapkan satu kebijakan sekaligus memantau kebijakan lainnya. Ini adalah cara untuk mengevaluasi efek perubahan pada CSP aplikasi Anda: aktifkan untuk membuat kebijakan baru, memantau laporan pelanggaran, dan memperbaiki {i>bug<i} munculkan; jika Anda puas dengan penerapannya, mulailah menerapkan kebijakan baru.
Penggunaan di Dunia Nyata
CSP 1 sangat berguna di Chrome, Safari, dan Firefox, tetapi sangat terbatas. di IE 10. Anda dapat lihat detailnya di caniuse.com. CSP Level 2 telah tersedia di Chrome sejak versi 40. Situs besar seperti Twitter dan Facebook telah menyebarkan {i>header<i} (Studi kasus Twitter layak dibaca), dan standarnya sangat siap untuk mulai menerapkan di situs Anda sendiri.
Langkah pertama dalam membuat kebijakan untuk aplikasi Anda adalah mengevaluasi sumber daya yang benar-benar Anda muat. Setelah Anda berpikir bahwa Anda dapat memahami semua hal dikumpulkan di aplikasi Anda, siapkan kebijakan berdasarkan hal-hal tersebut lainnya. Mari kita telusuri beberapa kasus penggunaan umum dan tentukan bagaimana kita paling mampu mendukung mereka 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 untuk menyematkan tombol. Kebijakan minimalnya adalahscript-src https://apis.google.com; child-src https://plusone.google.com
. Anda juga memerlukan untuk memastikan bahwa cuplikan JavaScript yang disediakan Google ditarik ke dalam file JavaScript eksternal. Jika Anda memiliki kebijakan berbasis Level 1 menggunakanframe-src
Level 2 mengharuskan Anda untuk mengubahnya menjadichild-src
. Tindakan ini tidak lagi diperlukan di CSP Level 3.Tombol Suka Facebook memiliki sejumlah opsi implementasi. Sebaiknya tetap ikuti
<iframe>
karena di-sandbox dengan aman dari bagian lain situs Anda. Ini memerlukan perintahchild-src https://facebook.com
agar dapat berfungsi dengan baik. Catatan secara default, kode<iframe>
yang disediakan Facebook akan memuat URL,//facebook.com
. Ubah untuk menentukan HTTPS secara eksplisit:https://facebook.com
. Anda tidak perlu menggunakan HTTP jika tidak perlu.Tombol Tweet Twitter bergantung pada akses ke skrip dan {i>frame<i}, keduanya di-{i>host<i} di
https://platform.twitter.com
. (Twitter juga menyediakan URL relatif dengan 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. Kami sarankan cukup setel
default-src
dari'none'
, dan tonton konsol Anda untuk menentukan resource yang harus Anda aktifkan agar widget berfungsi.
Penyertaan beberapa widget sangat mudah: cukup gabungkan kebijakan perintah, ingat untuk menggabungkan semua sumber daya dari satu jenis menjadi satu direktif. Jika Anda ingin ketiga widget media sosial tersebut, kebijakan 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 sumber daya yang Anda tulis sendiri yang dapat dimuat. Dalam skenario ini,
mulailah dengan kebijakan default yang memblokir semua (default-src 'none'
) dan membangun dari sana.
Katakanlah 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 ke bawah. Bingkai digunakan, namun hanya untuk laman yang bersifat lokal untuk
(tidak ada origin pihak ketiga). Tidak ada Flash di situs, tidak ada font, tidak
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
Admin forum diskusi cincin pernikahan ingin memastikan bahwa semua sumber daya hanya dimuat melalui saluran aman, tetapi tidak benar-benar menulis banyak kode; menulis ulang potongan besar perangkat lunak forum pihak ketiga yang penuh dengan skrip dan gaya inline di luar kemampuannya. Kebijakan berikut akan efektif:
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
Meskipun https:
ditentukan dalam default-src
, skrip dan gaya
tidak secara otomatis
mewarisi sumber tersebut. Setiap perintah sepenuhnya
menimpa default untuk jenis resource tertentu.
Acara mendatang
Kebijakan Keamanan Konten Tingkat 2 adalah Rekomendasi Kandidat. Grup Kerja Keamanan Aplikasi Web W3C telah mulai mengerjakan iterasi spesifikasi berikutnya, Kebijakan Keamanan Konten Level 3.
Jika Anda tertarik untuk diskusi seputar fitur-fitur yang akan datang ini, membaca sekilas arsip milis publik-webappsec@, atau bergabung dalam diri Anda sendiri.