Pertanyaan Memahami Token Keaslian Rails


Saya mengalami beberapa masalah terkait Token Keaslian di Rails, seperti yang sering saya alami sekarang.

Tapi saya benar-benar tidak ingin memecahkan masalah ini dan terus berjalan. Saya benar-benar ingin memahami token Keaslian. Nah, pertanyaan saya adalah, apakah Anda memiliki sumber informasi lengkap mengenai hal ini atau apakah Anda akan menghabiskan waktu Anda untuk menjelaskan secara rinci di sini?


877
2018-06-02 20:01


asal


Jawaban:


Apa yang terjadi

Saat pengguna melihat formulir untuk membuat, memperbarui, atau menghancurkan sumber daya, aplikasi Rails akan membuat acak authenticity_token, simpan token ini di sesi, dan tempatkan di bidang tersembunyi dalam formulir. Ketika pengguna mengirimkan formulir, Rails mencari authenticity_token, bandingkan dengan yang disimpan dalam sesi, dan jika mereka cocok dengan permintaan, dibiarkan berlanjut.

Kenapa itu terjadi

Karena token keaslian disimpan dalam sesi, klien tidak dapat mengetahui nilainya. Ini mencegah orang mengirimkan formulir ke aplikasi Rails tanpa melihat formulir di dalam aplikasi itu sendiri. Bayangkan bahwa Anda menggunakan layanan A, Anda masuk ke layanan dan semuanya baik-baik saja. Sekarang bayangkan Anda menggunakan layanan B, dan Anda melihat gambar yang Anda suka, dan menekan gambar untuk melihat ukuran yang lebih besar. Sekarang, jika beberapa kode jahat ada di layanan B, itu mungkin mengirim permintaan ke layanan A (yang Anda masuki), dan meminta untuk menghapus akun Anda, dengan mengirim permintaan ke http://serviceA.com/close_account. Inilah yang dikenal sebagai CSRF (Cross Site Request Forgery).

Jika layanan A menggunakan token otentisitas, vektor serangan ini tidak lagi berlaku, karena permintaan dari layanan B tidak akan berisi token keaslian yang benar, dan tidak akan dibiarkan berlanjut.

Dokumen API menjelaskan detail tentang tag meta:

Perlindungan CSRF dihidupkan dengan protect_from_forgery metode,   yang memeriksa token dan me-reset sesi jika tidak sesuai dengan apa   diharapkan. Panggilan ke metode ini dihasilkan untuk Rails baru   aplikasi secara default.   Parameter token diberi nama authenticity_token secara default. Nama   dan nilai token ini harus ditambahkan ke setiap tata letak yang merender   formulir dengan memasukkan csrf_meta_tags di kepala HTML.

Catatan

Perlu diingat, Rails hanya memverifikasi bukan metode idempoten (POST, PUT / PATCH dan DELETE). Permintaan GET tidak diperiksa untuk token keaslian. Mengapa? karena spesifikasi HTTP menyatakan bahwa permintaan GET adalah idempoten dan seharusnya tidak membuat, mengubah, atau menghancurkan sumber daya di server, dan permintaan harus idempoten (jika Anda menjalankan perintah yang sama beberapa kali, Anda harus mendapatkan hasil yang sama setiap kali).

Juga implementasi sebenarnya sedikit lebih rumit seperti yang didefinisikan di awal, memastikan keamanan yang lebih baik. Rel tidak mengeluarkan token yang disimpan yang sama dengan setiap formulir. Juga tidak menghasilkan dan menyimpan token yang berbeda setiap waktu. Ini menghasilkan dan menyimpan hash kriptografi dalam sesi dan mengeluarkan token kriptografis baru, yang dapat dicocokkan dengan token yang disimpan, setiap kali halaman ditampilkan. Lihat request_forgery_protection.rb.

Pelajaran

Menggunakan authenticity_token untuk melindungi metode tidak idempoten Anda (POST, PUT / PATCH, dan DELETE). Juga pastikan untuk tidak mengizinkan permintaan GET yang berpotensi mengubah sumber daya di server.


EDIT: Memeriksa komentar oleh @erturne tentang MENDAPATKAN permintaan menjadi idempoten. Dia menjelaskannya dengan cara yang lebih baik daripada yang saya lakukan di sini.


1371
2017-10-15 11:52



Token otentisitas dirancang agar Anda tahu formulir Anda dikirimkan dari situs web Anda. Ini dihasilkan dari mesin yang dijalankan dengan pengenal unik yang hanya dapat diketahui oleh mesin Anda, sehingga membantu mencegah serangan pemalsuan permintaan lintas situs.

Jika Anda hanya mengalami kesulitan dengan rel yang menolak akses skrip AJAX Anda, Anda dapat menggunakannya

<%= form_authenticity_token %>

untuk menghasilkan token yang benar saat Anda membuat formulir Anda.

Anda dapat membaca lebih lanjut tentang itu di dokumentasi.


129
2018-06-02 20:16



Apa itu CSRF?

Token Keaslian adalah tindakan balasan untuk Pemalsuan Permintaan Lintas Situs (CSRF). Apa itu CSRF, Anda bertanya?

Ini adalah cara penyerang berpotensi membajak sesi tanpa mengetahui token sesi.

Skenario:

  • Kunjungi situs bank Anda, masuk.
  • Kemudian kunjungi situs penyerang (misalnya iklan bersponsor dari organisasi yang tidak dipercaya).
  • Laman penyerang menyertakan formulir dengan bidang yang sama dengan formulir "Transfer Dana" bank.
  • Penyerang mengetahui info akun Anda, dan telah mengisi formulir formulir untuk mentransfer uang dari akun Anda ke akun penyerang.
  • Halaman penyerang termasuk Javascript yang mengirimkan formulir ke bank Anda.
  • Saat formulir dikirim, browser menyertakan cookie Anda untuk situs bank, termasuk token sesi.
  • Bank mentransfer uang ke akun penyerang.
  • Bentuknya bisa dalam iframe yang tidak terlihat, jadi Anda tidak pernah tahu serangan itu terjadi.
  • Ini disebut Pemalsuan Permintaan Lintas-Situs (CSRF).

Solusi CSRF:

  • Server dapat menandai formulir yang berasal dari server itu sendiri
  • Setiap formulir harus berisi token otentikasi tambahan sebagai bidang tersembunyi.
  • Token harus tidak dapat diprediksi (penyerang tidak dapat menebaknya).
  • Server menyediakan token yang valid dalam bentuk di halamannya.
  • Server memeriksa token ketika formulir diposting, menolak formulir tanpa token yang tepat.
  • Token contoh: pengidentifikasi sesi yang dienkripsi dengan kunci rahasia server.
  • Rel secara otomatis menghasilkan token seperti itu: lihat bidang input authenticity_token di setiap formulir.

77
2018-06-13 01:54



Contoh serangan minimal yang akan dicegah

Di situs web saya evil.com Saya meyakinkan Anda untuk mengirimkan formulir berikut:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

Jika Anda masuk ke bank Anda melalui cookie sesi, maka cookie akan dikirim dan transfer akan dilakukan tanpa Anda menyadarinya.

Itulah token CSRF yang dimainkan:

  • dengan respons GET yang mengembalikan formulir, Rails mengirimkan parameter tersembunyi acak yang sangat panjang
  • ketika browser membuat permintaan POST, itu akan mengirim parameter bersama, dan server hanya akan menerimanya jika cocok

Jadi bentuk pada browser yang autentik akan terlihat seperti:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

Dengan demikian, serangan saya akan gagal, karena itu tidak mengirim authenticity_token parameter, dan tidak ada cara saya bisa menebaknya karena itu adalah angka acak yang besar.

Teknik pencegahan ini disebut Pola Token Sinkronisasi.

Pola token sinkronisasi bekerja karena adanya Kebijakan Asal yang Sama: jika saya bisa membuat permintaan GET XHR ke bank Anda dari evil.com, dan membaca hasilnya, saya hanya bisa membaca token dan kemudian membuat permintaan nanti. Saya telah menjelaskan ini lebih lanjut di: https://security.stackexchange.com/a/72569/53321

Saya sangat menyarankan Anda untuk membaca panduan OWASP, tentang ini dan masalah keamanan lainnya.

Bagaimana Rails mengirimkan token

Ditutupi di: Rel: Bagaimana Cara Kerja csrf_meta_tag?

Pada dasarnya:

  • Pembantu HTML suka form_tag tambahkan bidang tersembunyi ke formulir untuk Anda jika bukan formulir GET

  • AJAX ditangani secara otomatis oleh jquery-ujs, yang membaca token dari meta elemen ditambahkan ke header Anda oleh csrf_meta_tags (hadir di template default), dan menambahkannya ke setiap permintaan yang dibuat.

    uJS juga mencoba memperbarui token dalam bentuk dalam fragmen cache yang kedaluwarsa.

Pendekatan pencegahan lainnya


36
2017-11-12 20:30



Itu Authenticity Token adalah metode rel untuk mencegah  'Pemalsuan permintaan lintas situs (CSRF atau XSRF)'.

Sederhananya, memastikan bahwa permintaan PUT / POST / DELETE (metode yang dapat memodifikasi konten) ke aplikasi web Anda dibuat dari browser klien dan bukan dari pihak ketiga (penyerang) yang memiliki akses ke cookie yang dibuat di sisi klien.


35
2018-06-02 20:17



sejak Authenticity Token sangat penting, dan di Rails 3.0+ dapat Anda gunakan

 <%= token_tag nil %>

untuk membuat

<input name="authenticity_token" type="hidden" value="token_value">

di mana saja


32
2017-08-01 05:12



Berhati-hatilah pada mekanisme Token Tokenitas dapat menghasilkan kondisi balapan jika Anda memiliki beberapa permintaan bersamaan dari klien yang sama. Dalam situasi ini server Anda dapat menghasilkan token keaslian beberapa saat seharusnya hanya ada satu, dan klien yang menerima token sebelumnya dalam formulir akan gagal pada permintaan berikutnya karena token cookie sesi telah ditimpa. Ada yang menulis tentang masalah ini dan solusi yang tidak sepenuhnya sepele di sini: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


25
2017-08-30 23:52



Token otentisitas digunakan untuk mencegah serangan Pematian Permintaan Lintas Situs (CSRF). Untuk memahami token keaslian, Anda harus terlebih dahulu memahami serangan CSRF.

CSRF

Misalkan Anda adalah penulis bank.com. Anda memiliki formulir di situs Anda yang digunakan untuk mentransfer uang ke akun lain dengan permintaan GET:

enter image description here

Seorang peretas bisa saja mengirim permintaan HTTP ke server yang mengatakan GET /transfer?amount=$1000000&account-to=999999benar?

enter image description here

Salah. Serangan peretas tidak akan berfungsi. Server pada dasarnya akan berpikir?

Hah? Siapa orang ini yang mencoba melakukan transfer. Bukan pemilik akun, itu sudah pasti.

Bagaimana server tahu ini? Karena tidak ada session_id cookie yang mengautentikasi pemohon.

Saat Anda masuk dengan nama pengguna dan kata sandi Anda, server menyetel a session_id cookie di browser Anda. Dengan begitu, Anda tidak perlu mengotentikasi setiap permintaan dengan nama pengguna dan kata sandi Anda. Ketika browser Anda mengirim session_id cookie, server tahu:

Oh, itu John Doe. Dia masuk berhasil 2,5 menit yang lalu. Dia baik untuk pergi.

Seorang peretas mungkin berpikir:

Hmm Permintaan HTTP yang normal tidak akan berfungsi, tetapi jika saya bisa mendapatkan itu session_id cookie, saya akan emas.

Browser pengguna memiliki banyak cookie yang ditetapkan untuk bank.com domain. Setiap kali pengguna membuat permintaan ke bank.com domain, semua cookie dikirim bersama. Termasuk session_id Kue kering.

Jadi jika seorang hacker bisa kamu untuk membuat permintaan GET yang mentransfer uang ke akunnya, dia akan berhasil. Bagaimana dia bisa menipu Anda untuk melakukannya?  Dengan Pemalsuan Permintaan Lintas Situs.

Ini sebenarnya cukup sederhana. Peretas hanya bisa membuat Anda mengunjungi situs webnya. Di situs webnya, dia dapat memiliki tag gambar berikut:

<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

Ketika browser pengguna menemukan tag gambar itu, itu akan membuat permintaan GET ke url itu. Dan karena permintaan berasal dari browsernya, itu akan mengirimkan semua cookie yang terkait dengannya bank.com. Jika pengguna baru saja masuk ke bank.com... yang session_id cookie akan diatur, dan server akan berpikir bahwa pengguna bermaksud mentransfer $ 1.000.000 ke akun 999999!

enter image description here

Yah, jangan mengunjungi situs berbahaya dan Anda akan baik-baik saja.

Itu tidak cukup. Bagaimana jika seseorang memposting gambar itu ke Facebook dan muncul di dinding Anda? Bagaimana jika disuntikkan ke situs yang Anda kunjungi dengan serangan XSS?

Tidak terlalu buruk. Hanya permintaan GET yang rentan.

Tidak benar. Formulir yang mengirim permintaan POST dapat dibuat secara dinamis. Inilah contoh dari Panduan Rails tentang Keamanan:

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

Token Keaslian

Ketika Anda ApplicationController memiliki ini:

protect_from_forgery with: :exception

Ini:

<%= form_tag do %>
  Form contents
<% end %>

Dikompilasi menjadi ini:

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

Secara khusus, yang berikut ini dihasilkan:

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

Untuk melindungi terhadap serangan CSRF, jika Rails tidak melihat token keaslian dikirim bersama dengan permintaan, itu tidak akan mempertimbangkan permintaan aman.

Bagaimana penyerang seharusnya tahu token ini apa? Nilai yang berbeda dihasilkan secara acak setiap kali formulir dibuat:

enter image description here

Serangan Cross Site Scripting (XSS) - begitulah caranya. Tapi itu kerentanan yang berbeda untuk hari yang berbeda.


23
2018-04-14 04:33