Token CSRF diperlukan saat menggunakan Autentikasi Stateless (= Sessionless)?

125

Apakah perlu menggunakan Perlindungan CSRF ketika aplikasi mengandalkan otentikasi tanpa kewarganegaraan (menggunakan sesuatu seperti HMAC)?

Contoh:

  • Kami punya app halaman (jika tidak kita harus menambahkan tanda pada setiap link: <a href="...?token=xyz">...</a>.

  • Pengguna mengautentikasi dirinya sendiri menggunakan POST /auth. Jika otentikasi berhasil, server akan mengembalikan beberapa token.

  • Token akan disimpan melalui JavaScript di beberapa variabel di dalam aplikasi halaman tunggal.

  • Token ini akan digunakan untuk mengakses URL terbatas seperti /admin.

  • Token akan selalu dikirim di dalam HTTP Headers.

  • TIDAK ADA Sesi Http, dan NO Cookies.

Sejauh yang saya mengerti, seharusnya (?!) tidak ada kemungkinan untuk menggunakan serangan lintas situs, karena browser tidak akan menyimpan token, dan karenanya tidak dapat secara otomatis mengirimkannya ke server (itulah yang akan terjadi saat menggunakan Cookies / Sidang).

Apakah saya melewatkan sesuatu?

Benjamin M
sumber
6
Berhati-hatilah dengan Basic Auth. Banyak browser secara otomatis akan mengirimkan header autentikasi dasar untuk sisa sesi. Hal ini dapat membuat autentikasi dasar rentan terhadap CSRF seperti halnya autentikasi cookie.
fila

Jawaban:

159

Saya menemukan beberapa informasi tentang CSRF + tidak menggunakan cookie untuk otentikasi:

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    "karena Anda tidak mengandalkan cookie, Anda tidak perlu melindungi dari permintaan lintas situs"

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    "Jika kami menggunakan cookie, Anda benar-benar perlu melakukan CSRF untuk menghindari permintaan lintas situs. Itu adalah sesuatu yang kami bisa lupakan saat menggunakan JWT seperti yang akan Anda lihat. "
    (JWT = Json Web Token, otentikasi berbasis Token untuk aplikasi stateless)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    "Cara termudah untuk melakukan otentikasi tanpa risiko kerentanan CSRF adalah dengan menghindari penggunaan cookie untuk mengidentifikasi pengguna "

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    "Masalah terbesar dengan CSRF adalah bahwa cookie sama sekali tidak memberikan pertahanan terhadap jenis serangan ini. Jika Anda menggunakan otentikasi cookie Anda juga harus menerapkan tindakan tambahan untuk melindungi terhadap CSRF. Tindakan pencegahan paling dasar yang dapat Anda lakukan adalah memastikan bahwa aplikasi Anda tidak pernah melakukan efek samping sebagai respons terhadap permintaan GET. "

Ada lebih banyak halaman, yang menyatakan bahwa Anda tidak memerlukan perlindungan CSRF, jika Anda tidak menggunakan cookie untuk otentikasi. Tentu saja Anda masih dapat menggunakan cookie untuk yang lainnya, tetapi hindari menyimpan apa pun seperti session_iddi dalamnya.


Jika Anda perlu mengingat pengguna, ada 2 opsi:

  1. localStorage: Penyimpanan nilai kunci dalam browser. Data yang disimpan akan tersedia bahkan setelah pengguna menutup jendela browser. Data tersebut tidak dapat diakses oleh situs web lain, karena setiap situs mendapatkan penyimpanannya sendiri.

  2. sessionStorage: Juga penyimpanan data di browser. Perbedaannya adalah: Data dihapus saat pengguna menutup jendela browser. Tapi itu tetap berguna, jika aplikasi web Anda terdiri dari banyak halaman. Jadi, Anda dapat melakukan hal berikut:

    • Pengguna masuk, lalu Anda menyimpan tokennya sessionStorage
    • Pengguna mengklik link, yang memuat halaman baru (= a real hubungan, dan tidak ada javascript konten-ganti)
    • Anda masih dapat mengakses token dari sessionStorage
    • Untuk keluar, Anda dapat menghapus token dari secara manual sessionStorageatau menunggu pengguna menutup jendela browser, yang akan menghapus semua data yang disimpan.

(untuk keduanya, lihat di sini: http://www.w3schools.com/html/html5_webstorage.asp )


Apakah ada standar resmi untuk token auth?

JWT (Json Web Token): Menurut saya ini masih berupa draf, tetapi sudah digunakan oleh banyak orang dan konsepnya terlihat sederhana dan aman. (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
Ada juga perpustakaan untuk banyak kerangka kerja yang tersedia. Hanya google untuk itu!

Benjamin M
sumber
37
Ringkasan bagus tentang CSRF! Saya akan mencatat bahwa menyimpan token Anda di localStorage atau sessionStorage rentan terhadap serangan XSS dan bahwa datanya dapat dilihat oleh skrip di halaman - jadi jika Anda memiliki skrip yang disusupi yang disajikan dari CDN atau jika ada kode berbahaya di salah satu Perpustakaan JS, mereka dapat mencuri token dari tempat penyimpanan itu. Lihat: stormpath.com/blog/… Saya pikir pendekatan yang paling aman adalah dengan menyimpan token JWT + CSRF di cookie, lalu tempatkan JWT yang dihitung dengan token CSRF di dalamnya di header permintaan.
Aaron Gray
Mengenai: "Tindakan pencegahan paling dasar yang dapat Anda lakukan adalah memastikan bahwa aplikasi Anda tidak pernah melakukan efek samping apa pun sebagai respons terhadap permintaan GET." Apakah mungkin serangan CSRF memalsukan permintaan POST?
Costa
Tergantung pada Aplikasi Sisi Server, ini DAPAT. Ada Kerangka Web, yang menggunakan sesuatu seperti http://.../someRestResource?method=POST. Jadi pada dasarnya ini adalah GETpermintaan, tetapi Aplikasi Server menafsirkannya sebagai POSTpermintaan, karena telah dikonfigurasi untuk menggunakan methodparameter, bukan header HTTP. ...Mengenai browser web umum, mereka memberlakukan Kebijakan Asal-Sama dan hanya akan menjalankan GETpermintaan ke server asing. Meskipun bisa mungkin untuk mengeksekusi POSTpermintaan jika web browser tidak berlaku standar-standar web (bug, malware).
Benjamin M
1
Selain itu Server Side App: Mengirim Badan Permintaan masih belum dapat dilakukan, karena browser umum tidak mengizinkannya. Namun, jika Aplikasi Server memungkinkan method=POST, itu mungkin juga memungkinkan body={someJson}untuk mengganti isi permintaan default. Itu desain API yang sangat buruk dan sangat berisiko. Meskipun jika Aplikasi Server http://...?method=POST&body={someJson}Anda memungkinkan Anda harus benar-benar memikirkan secara berlebihan apa yang Anda lakukan di sana dan mengapa dan jika itu perlu sama sekali. (Saya akan mengatakan dalam 99,9999% kasus itu tidak perlu). Selain itu, browser hanya dapat mengirim beberapa kilobyte dengan cara ini.
Benjamin M
@BenjaminM memperhatikan bahwa Kebijakan Asal yang Sama hanya mencegah kode javaScript mengakses hasil jadi sementara permintaan "diblokir" itu benar-benar mencapai server - jsbin.com/mewaxikuqo/edit?html,js,output Saya hanya menguji ini di firefox, tetapi Anda dapat membuka alat pengembang dan melihat bahwa meskipun Anda mendapatkan "Permintaan Lintas Asal Diblokir", server jarak jauh benar-benar melihat seluruh permintaan. itulah mengapa Anda harus memiliki token atau tajuk khusus (dan jika memungkinkan keduanya) untuk semua permintaan POST Anda
Yoni Jah
59

TL; DR

JWT, jika digunakan tanpa Cookies, meniadakan kebutuhan token CSRF - TAPI! dengan menyimpan JWT di session / localStorage, Anda mengekspos JWT Anda dan identitas pengguna jika situs Anda memiliki kerentanan XSS (cukup umum). Lebih baik menambahkan csrfTokenkunci ke JWT dan menyimpan JWT dalam cookie dengan securedanhttp-only atribut set.

Baca artikel ini dengan deskripsi yang bagus untuk info lebih lanjut https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

Anda dapat membuat perlindungan CSRF ini tanpa kewarganegaraan dengan menyertakan klaim JWT xsrfToken:

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "[email protected]", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

Jadi, Anda perlu menyimpan csrfToken di localStorage / sessionStorage serta di JWT itu sendiri (yang disimpan dalam cookie khusus http dan aman). Kemudian untuk perlindungan csrf, verifikasi bahwa token csrf di JWT cocok dengan header csrf-token yang dikirimkan.

Scott Jungwirth
sumber
2
Haruskah seseorang mengecualikan penggunaan token csrf selama otentikasi api pengguna?
pengguna805981
3
Perlu ditunjukkan (seperti yang disebutkan orang lain dalam komentar di tautan sumber) bahwa mitigasi CSRF apa pun yang menggunakan a) cookie, yang bukan hanya http atau b) menyimpan token CSRF di penyimpanan lokal rentan terhadap XSS. Ini berarti bahwa pendekatan yang disajikan dapat membantu menjaga rahasia JWT dari penyerang yang menggunakan XSS, tetapi penyerang masih dapat menjalankan permintaan jahat di API Anda karena dia dapat memberikan JWT yang valid (melalui cookie, terima kasih browser) dan token CSRF (baca melalui JS yang disuntikkan dari penyimpanan / cookie lokal).
Johannes Rudolph
1
Sebenarnya bahkan token CSRF tidak dapat melindungi Anda pada tingkat XSS ini, karena Anda mengasumsikan penyerang dapat mengakses Penyimpanan lokal, yang satu-satunya cara saat ini untuk mengaksesnya adalah memiliki akses tingkat skrip, yang mana mereka dapat melihat token CSRF. .
valid
1
Bukankah itu yang dikatakan @JohannesRudolph? Segera setelah Anda menyimpan Token CSRF di Penyimpanan Web / cookie non-http saja, Anda meningkatkan jejak serangan XSS karena itu dapat diakses melalui JS.
adam-beck
1
Bukan ahli total di sini, tetapi jika Anda masih terpapar XSS seperti pada awalnya, saya tidak yakin bagiannya. Lebih baik menambahkan ... benar-benar berlaku. Mungkin sedikit (?) Lebih rumit bagi penyerang untuk mendapatkan token CSRF, tetapi pada akhirnya dia masih dapat melakukan permintaan atas nama Anda, bahkan tanpa benar-benar mengetahui token JWT. Apakah itu benar? Terima kasih
superjos