Mencegah CSRF, XSSI, dan kebocoran informasi lintas asal.
Mengapa Anda perlu mengisolasi resource web?
Banyak aplikasi web rentan terhadap serangan lintas asal seperti pemalsuan permintaan lintas situs (CSRF), penyertaan skrip lintas situs (XSSI), serangan pengaturan waktu, kebocoran informasi lintas asal, atau serangan sisi saluran eksekusi spekulatif (Spectre).
Header permintaan Mengambil Metadata memungkinkan Anda men-deploy mekanisme pertahanan mendalam yang kuat—Kebijakan Isolasi Resource—untuk melindungi aplikasi Anda dari serangan lintas asal umum ini.
Umumnya, resource yang diekspos oleh aplikasi web tertentu hanya dimuat oleh aplikasi itu sendiri, bukan oleh situs lain. Dalam kasus tersebut, men-deploy Kebijakan Isolasi Resource berdasarkan header permintaan Mengambil Metadata tidak membutuhkan upaya yang besar, dan pada saat yang sama melindungi aplikasi dari serangan lintas situs.
Kompatibilitas browser
Header permintaan Mengambil Metadata didukung di semua mesin browser modern.
Latar belakang
Banyak serangan lintas situs yang mungkin terjadi karena web terbuka secara default dan server aplikasi Anda tidak dapat dengan mudah melindungi dirinya sendiri dari komunikasi yang berasal dari aplikasi eksternal. Serangan lintas origin yang umum terjadi adalah pemalsuan permintaan lintas situs (CSRF) saat penyerang mengarahkan pengguna ke situs yang mereka kontrol, lalu mengirimkan formulir ke server tempat pengguna login. Karena server tidak dapat mengetahui apakah permintaan berasal dari domain lain (lintas situs) dan browser secara otomatis melampirkan cookie ke permintaan lintas situs, server akan menjalankan tindakan yang diminta oleh penyerang atas nama pengguna.
Serangan lintas situs lainnya seperti penyertaan skrip lintas situs (XSSI) atau kebocoran informasi lintas asal pada dasarnya serupa dengan CSRF dan mengandalkan pemuatan resource dari aplikasi korban dalam dokumen yang dikontrol penyerang dan membocorkan informasi tentang aplikasi korban. Karena aplikasi tidak dapat dengan mudah membedakan permintaan tepercaya dan yang tidak tepercaya, aplikasi tidak dapat menghapus traffic lintas situs yang berbahaya.
Memperkenalkan Pengambilan Metadata
Header permintaan Mengambil Metadata adalah fitur keamanan platform web baru yang dirancang untuk membantu server mempertahankan diri dari serangan lintas asal. Dengan memberikan informasi tentang konteks permintaan HTTP dalam serangkaian header Sec-Fetch-*
, server respons dapat menerapkan kebijakan keamanan sebelum memproses permintaan. Hal ini memungkinkan developer memutuskan apakah akan menerima atau menolak permintaan berdasarkan cara permintaan tersebut dibuat dan konteks yang akan digunakan, sehingga hanya memungkinkan untuk merespons permintaan sah yang dibuat oleh aplikasi mereka sendiri.
![Permintaan pengambilan dari https://site.example untuk resource https://site.example/foo.json di JavaScript menyebabkan browser mengirim header permintaan HTTP 'Sec Fetch-Site: same-origin'.](https://web.dev/static/articles/fetch-metadata/image/a-fetch-request-https-c7b9ae23ad7f.png?authuser=19&hl=id)
Sec-Fetch-*
.
![Gambar di https://evil.example yang telah menetapkan atribut src dari elemen img ke 'https://site.example/foo.json' menyebabkan browser mengirimkan header permintaan HTTP 'Sec-Fetch-Site: cross-site'.](https://web.dev/static/articles/fetch-metadata/image/an-image-httpsevilex-f0db21158caeb.png?authuser=19&hl=id)
Sec-Fetch-Site
Sec-Fetch-Site
memberi tahu server situs mana yang mengirim permintaan. Browser menetapkan nilai ini ke salah satu nilai berikut:
same-origin
, jika permintaan dibuat oleh aplikasi Anda sendiri (mis.site.example
)same-site
, jika permintaan dibuat oleh subdomain situs Anda (mis.,bar.site.example
)none
, jika permintaan secara eksplisit disebabkan oleh interaksi pengguna dengan agen pengguna (misalnya, mengklik bookmark)cross-site
, jika permintaan dikirim oleh situs lain (mis.,evil.example
)
Sec-Fetch-Mode
Sec-Fetch-Mode
menunjukkan mode permintaan. Ini kira-kira sesuai dengan jenis permintaan dan memungkinkan Anda membedakan beban resource dari permintaan navigasi. Misalnya, tujuan navigate
menunjukkan permintaan navigasi tingkat atas, sementara no-cors
menunjukkan permintaan resource seperti memuat gambar.
Sec-Fetch-Dest
Sec-Fetch-Dest
mengekspos tujuan permintaan (misalnya jika tag script
atau img
menyebabkan resource diminta oleh browser).
Cara menggunakan Mengambil Metadata untuk melindungi dari serangan lintas asal
Informasi tambahan yang disediakan oleh header permintaan ini cukup sederhana, tetapi konteks tambahan memungkinkan Anda membuat logika keamanan yang andal di sisi server, yang juga disebut sebagai Kebijakan Isolasi Resource, hanya dengan beberapa baris kode.
Mengimplementasikan Kebijakan Isolasi Resource
Kebijakan Isolasi Resource mencegah resource Anda diminta oleh situs eksternal. Pemblokiran traffic tersebut akan mengurangi kerentanan web lintas situs yang umum, seperti CSRF, XSSI, serangan waktu, dan kebocoran informasi lintas asal. Kebijakan ini dapat diaktifkan untuk semua endpoint aplikasi Anda dan akan mengizinkan semua permintaan resource yang berasal dari aplikasi Anda sendiri serta navigasi langsung (melalui permintaan GET
HTTP). Endpoint yang seharusnya dimuat dalam konteks lintas situs (misalnya, endpoint yang dimuat menggunakan CORS) dapat dikecualikan dari logika ini.
Langkah 1: Izinkan permintaan dari browser yang tidak mengirim Metadata Pengambilan
Karena tidak semua browser mendukung Pengambilan Metadata, Anda harus mengizinkan permintaan yang tidak menetapkan header Sec-Fetch-*
dengan memeriksa keberadaan sec-fetch-site
.
if not req['sec-fetch-site']:
return True # Allow this request
Langkah 2: Izinkan permintaan yang dimulai oleh browser dan situs yang sama
Setiap permintaan yang tidak berasal dari konteks lintas origin (seperti evil.example
) akan diizinkan. Secara khusus, ini adalah permintaan yang:
- Berasal dari aplikasi Anda sendiri (misalnya permintaan origin yang sama tempat
site.example
memintasite.example/foo.json
akan selalu diizinkan). - Berasal dari subdomain Anda.
- Secara eksplisit disebabkan oleh interaksi pengguna dengan agen pengguna (mis. navigasi langsung atau dengan mengklik bookmark, dll.).
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True # Allow this request
Langkah 3: Izinkan navigasi tingkat atas dan iframing yang sederhana
Untuk memastikan situs Anda masih dapat ditautkan dari situs lain, Anda harus mengizinkan navigasi tingkat atas yang sederhana (HTTP GET
).
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
# <object> and <embed> send navigation requests, which we disallow.
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True # Allow this request
Langkah 4: Nonaktifkan endpoint yang dimaksudkan untuk menyalurkan traffic lintas situs (Opsional)
Dalam beberapa kasus, aplikasi Anda mungkin menyediakan resource yang dimaksudkan untuk dimuat lintas situs. Resource ini perlu dikecualikan berdasarkan per jalur atau per-endpoint. Contoh endpoint tersebut adalah:
- Endpoint dimaksudkan untuk diakses lintas origin: Jika aplikasi Anda menayangkan endpoint yang mengaktifkan
CORS
, Anda harus secara eksplisit tidak mengizinkan endpoint tersebut dari isolasi resource untuk memastikan bahwa permintaan lintas situs ke endpoint ini masih memungkinkan. - Resource publik (misalnya, gambar, gaya, dll.): Semua resource publik dan tidak terautentikasi yang seharusnya dapat dimuat lintas origin dari situs lain juga dapat dikecualikan.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
Langkah 5: Tolak semua permintaan lain yang bersifat lintas situs dan tidak bersifat navigasi
Permintaan lintas situs lainnya akan ditolak oleh Kebijakan Isolasi Resource ini, sehingga melindungi aplikasi Anda dari serangan lintas situs yang umum.
Contoh: Kode berikut menunjukkan implementasi lengkap Kebijakan Isolasi Resource yang kuat di server atau sebagai middleware untuk menolak permintaan resource lintas situs yang berpotensi berbahaya, sekaligus mengizinkan permintaan navigasi sederhana:
# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
# Allow requests from browsers which don't send Fetch Metadata
if not req['sec-fetch-site']:
return True
# Allow same-site and browser-initiated requests
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
return True
# Allow simple top-level navigations except <object> and <embed>
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
and req['sec-fetch-dest'] not in ('object', 'embed'):
return True
# [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
return True
# Reject all other requests that are cross-site and not navigational
return False
Men-deploy Kebijakan Isolasi Resource
- Instal modul seperti cuplikan kode di atas untuk mencatat dan memantau perilaku situs Anda serta pastikan pembatasannya tidak memengaruhi traffic yang sah.
- Perbaiki potensi pelanggaran dengan mengecualikan endpoint lintas origin yang sah.
- Terapkan kebijakan dengan membatalkan permintaan yang tidak mematuhi kebijakan.
Mengidentifikasi dan memperbaiki pelanggaran kebijakan
Sebaiknya uji kebijakan dengan cara bebas efek samping dengan terlebih dahulu mengaktifkannya dalam mode pelaporan pada kode sisi server. Atau, Anda dapat menerapkan logika ini di middleware, atau di reverse proxy yang mencatat pelanggaran apa pun yang mungkin dihasilkan oleh kebijakan Anda saat diterapkan ke traffic produksi.
Berdasarkan pengalaman kami dalam meluncurkan Kebijakan Isolasi Sumber Daya Metadata Mengambil di Google, sebagian besar aplikasi secara default kompatibel dengan kebijakan tersebut dan jarang memerlukan endpoint pengecualian untuk mengizinkan traffic lintas situs.
Menegakkan Kebijakan Isolasi Resource
Setelah memeriksa bahwa kebijakan Anda tidak memengaruhi traffic produksi yang sah, Anda siap menerapkan pembatasan, yang menjamin bahwa situs lain tidak akan dapat meminta resource Anda dan melindungi pengguna Anda dari serangan lintas situs.
Bacaan lebih lanjut
- Spesifikasi Header Permintaan Metadata Pengambilan W3C
- Mengambil Metadata Playground
- Diskusi Google I/O: Mengamankan Aplikasi Web dengan Fitur Platform Modern (Slide)