Nonce CSP Mengikat Eksekusi Script ke Markup Pilihan Server
Content Security Policy (CSP) dapat membatasi script yang dieksekusi browser. Daftar source berbasis host merupakan salah satu cara menyatakan batas tersebut, tetapi host yang diizinkan adalah trust boundary yang kasar: setiap resource script yang cocok dengan source tersebut dapat memenuhi bagian policy itu.
Policy berbasis nonce mengubah unit otorisasinya. Server membuat nonce yang tidak dapat diprediksi untuk sebuah response, menaruh nonce tersebut pada policy script-src, lalu memasang nilai yang sama hanya pada elemen script yang dipilih untuk dieksekusi. Browser membandingkan kedua nilai saat menerapkan CSP.
Properti yang berguna adalah otorisasi yang terikat pada response. Nonce bukan credential permanen untuk URL atau origin script, dan reuse tidak boleh mengubahnya menjadi credential semacam itu.
Response membawa policy dan penanda otorisasi
Sebuah response dapat mengirim policy seperti berikut:
Content-Security-Policy: script-src 'nonce-r4Nd0mValue'Markup yang terkait membawa nonce yang sama pada elemen script yang memang ditujukan untuk berjalan:
<script nonce="r4Nd0mValue" src="/assets/app.js"></script>Dalam pencocokan nonce-source, browser memeriksa nonce elemen terhadap nonce source pada policy aktif. Nonce yang cocok dapat mengotorisasi elemen script tersebut meskipun URL-nya tidak direpresentasikan oleh host source expression.
Mekanisme ini memindahkan keputusan penting ke proses pembuatan response. Aplikasi tidak lagi menyatakan bahwa semua script dari lokasi yang luas dapat diterima. Aplikasi menandai elemen script tertentu dalam dokumen hasil render sebagai tepercaya untuk response tersebut.
Nonce harus baru dan tidak dapat diprediksi
Nilai keamanan nonce bergantung pada ketidakmampuan penyerang memprediksi nilai valid untuk response yang menjadi target. Reuse nonce tetap pada banyak response mengubah penanda otorisasi per-response menjadi nilai yang dapat digunakan kembali.
Pola pembuatannya secara konseptual sederhana:
request
|
v
nonce acak yang kuat secara kriptografis
|
+----> CSP response header
|
+----> elemen <script> yang dipilihNonce tidak perlu tetap rahasia setelah response sampai ke browser. Nilainya muncul di dokumen dan policy. Perlindungannya berasal dari sifat tidak dapat diprediksi sebelum server mengirim response dan dari tidak digunakannya kembali nilai tersebut pada response yang dibuat secara terpisah.
Caching karena itu perlu ditangani secara sengaja. Jika HTML yang memuat nonce di-cache bersama CSP header-nya, penyajian ulang cached response juga menyajikan ulang nonce. Kesesuaiannya bergantung pada arsitektur response dan threat model; desain yang mengandalkan nonce baru untuk tiap response harus menyelaraskan perilaku cache dengan syarat tersebut.
Nonce tidak melakukan sanitasi pada markup dari penyerang
CSP adalah lapisan enforcement pada browser, bukan HTML sanitizer. Aplikasi tetap perlu melakukan encoding atau sanitasi data tidak tepercaya sesuai konteks tempat data dimasukkan.
Boundary berbahaya muncul ketika data yang dikendalikan penyerang dapat memperoleh nonce valid. Template, misalnya, tidak boleh menyalin nonce ke markup arbitrer hanya karena sebuah fragment berisi elemen script. Server harus mengendalikan elemen mana yang menerima penanda otorisasi.
jalur template tepercaya ----> script + nonce valid ----> memenuhi syarat
input tidak tepercaya --------> injected script ---------> tanpa nonceJika injection flaw memungkinkan penyerang menaruh konten script di dalam block script ber-nonce yang sudah tepercaya, nonce tidak dapat membedakan byte tepercaya dari byte yang dikendalikan penyerang di dalam block tersebut. Aplikasi tetap memerlukan penanganan data yang aman pada injection boundary.
Hash source cocok untuk konten script statis
CSP juga mendukung hash source. Alih-alih memberi penanda baru pada elemen, policy dapat memuat cryptographic hash dari konten inline script yang diizinkan. Browser menghitung hash atas konten script yang relevan lalu membandingkan hasilnya dengan policy.
Model ini cocok ketika byte inline script stabil. Setiap perubahan konten memerlukan perubahan hash pada policy. Nonce cocok untuk dokumen hasil server rendering ketika proses pembuatan response dapat memasang nilai baru pada elemen script yang dipilih.
Kedua mekanisme tersebut tidak mengubah dynamic code arbitrer menjadi aman. Keduanya mengidentifikasi konten atau elemen script yang siap diotorisasi oleh policy.
strict-dynamic mengubah propagasi trust untuk script
CSP Level 3 mendefinisikan source expression 'strict-dynamic' untuk script policy. Pada user agent yang mendukungnya, expression ini mengubah cara trust script dapat diteruskan dari script yang diotorisasi oleh nonce atau hash ke script yang dimuat kode tepercaya melalui elemen script non-parser-inserted.
Policy dapat berbentuk seperti ini:
Content-Security-Policy: script-src 'nonce-r4Nd0mValue' 'strict-dynamic'Ini berbeda secara material dari menambah hostname ke allowlist. Trust anchor awalnya adalah script yang diotorisasi nonce atau hash. Pemuatan script yang dimulai oleh script tepercaya tersebut kemudian dapat mengikuti perilaku strict-dynamic yang ditetapkan CSP.
Propagasi tersebut kuat dan perlu disengaja. Jika bootstrap script tepercaya menerima URL yang dikendalikan penyerang lalu membuat elemen script dari URL itu, CSP tidak dapat memperbaiki keputusan trust yang tidak aman di dalam bootstrap script. Aplikasi telah mendelegasikan kewenangan memuat script kepada kode yang harus menangani inputnya secara tepat.
Source list dan nonce menyatakan boundary yang berbeda
Pertimbangkan host allowlist berikut:
Content-Security-Policy: script-src https://static.exampleBrowser dapat menerima request script yang cocok dengan source expression tersebut. Boundary policy berada pada source yang diizinkan.
Bandingkan dengan nonce policy:
Content-Security-Policy: script-src 'nonce-r4Nd0mValue'Otorisasi dipasang pada elemen script pilihan dalam response. Pendekatan ini dapat menghindari perlakuan terhadap seluruh host yang diizinkan seolah setara dengan script tertentu yang dipilih document generator.
Perbedaan tersebut relevan ketika host yang diizinkan melayani banyak resource, menerima konten yang dikendalikan user, melakukan redirect request, atau berubah secara independen dari aplikasi. Primitive otorisasi yang lebih sempit mengurangi luas namespace script yang direpresentasikan langsung dalam CSP source list, tetapi tidak menghapus kebutuhan untuk menilai perilaku script yang benar-benar dipercaya.
Report-Only dapat menunjukkan kerusakan policy sebelum enforcement
Penerapan script policy yang lebih ketat dapat merusak halaman yang masih bergantung pada inline handler, elemen script yang dibuat dinamis, atau third-party loader yang tidak sesuai dengan trust model yang dituju. CSP menyediakan mode report-only agar policy dapat dievaluasi tanpa menerapkan pembatasannya.
Content-Security-Policy-Report-Only: script-src 'nonce-r4Nd0mValue'Telemetry report-only berguna untuk menemukan policy violation, tetapi tidak adanya report bukan bukti bahwa setiap execution path sudah tercakup. Reporting dapat dipengaruhi perilaku client, konfigurasi pengiriman, pilihan sampling, dan path yang tidak dijalankan selama observasi.
Enforcement karena itu sebaiknya mengikuti pengujian spesifik aplikasi, bukan memperlakukan telemetry sebagai pemeriksaan kelengkapan formal.
CSP tetap menjadi satu lapisan dalam pertahanan XSS
CSP berbasis nonce yang kuat dapat membuat banyak jalur script injection lebih sulit berubah menjadi eksekusi script karena elemen hasil injection tidak memiliki penanda otorisasi pilihan server. Ini merupakan properti containment yang berarti, tetapi bukan pengganti perbaikan injection flaw.
Output encoding, contextual sanitization, DOM API yang aman, kontrol dependency, dan boundary template yang cermat tetap penting. CSP menambahkan pembatasan yang ditegakkan browser di sekitar eksekusi script ketika kontrol lain gagal atau kompleksitas aplikasi menyisakan jalur injection yang tidak diperkirakan.
Boundary desain yang bersih tetap sempit: buat nonce baru yang tidak dapat diprediksi untuk response, tampilkan hanya melalui policy dan elemen script yang memang diotorisasi server, jauhkan markup tidak tepercaya dari jalur otorisasi tersebut, dan perlakukan script tepercaya sebagai kode yang benar-benar memiliki kewenangan memuat script. Dengan batas ini, CSP tetap berfokus pada kontrol eksekusi dan tidak dipaksa menutupi data flow yang tidak aman di bagian lain aplikasi.
References
- W3C, Content Security Policy Level 3: https://www.w3.org/TR/CSP3/
- W3C, Content Security Policy Level 2: https://www.w3.org/TR/CSP2/