Saya mencoba menambahkan beberapa keamanan ke formulir di situs web saya. Salah satu formulir menggunakan AJAX dan yang lainnya adalah formulir "hubungi kami" langsung. Saya mencoba menambahkan token CSRF. Masalah yang saya hadapi adalah bahwa token hanya muncul di "nilai" HTML beberapa waktu. Sisa waktunya, nilainya kosong. Berikut adalah kode yang saya gunakan pada formulir AJAX:
PHP:
if (!isset($_SESSION)) {
session_start();
$_SESSION['formStarted'] = true;
}
if (!isset($_SESSION['token']))
{$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
}
HTML
<form>
//...
<input type="hidden" name="token" value="<?php echo $token; ?>" />
//...
</form>
Ada saran?
token_time
digunakan?token_time
. Saya akan membatasi waktu di mana token valid, tetapi belum sepenuhnya menerapkan kode. Demi kejelasan, saya telah menghapusnya dari pertanyaan di atas.Jawaban:
Untuk kode keamanan, jangan buat token Anda dengan cara ini:
$token = md5(uniqid(rand(), TRUE));
rand()
bisa ditebakuniqid()
hanya menambahkan hingga 29 bit entropimd5()
tidak menambahkan entropi, itu hanya mencampurkannya secara deterministikCoba ini:
Menghasilkan Token CSRF
PHP 7
Catatan: Salah satu proyek open source perusahaan saya adalah inisiatif untuk mendukung
random_bytes()
danrandom_int()
menjadi proyek PHP 5. Ini berlisensi MIT dan tersedia di Github dan Composer sebagai paragonie / random_compat .PHP 5.3+ (atau dengan ext-mcrypt)
Memverifikasi Token CSRF
Jangan hanya menggunakan
==
atau bahkan===
, gunakanhash_equals()
(hanya PHP 5.6+, tetapi tersedia untuk versi sebelumnya dengan pustaka hash-compat ).Melangkah Lebih Jauh dengan Token Per-Form
Anda selanjutnya dapat membatasi token agar hanya tersedia untuk formulir tertentu dengan menggunakan
hash_hmac()
. HMAC adalah fungsi hash berkunci tertentu yang aman digunakan, bahkan dengan fungsi hash yang lebih lemah (misalnya MD5). Namun, saya merekomendasikan menggunakan keluarga SHA-2 dari fungsi hash sebagai gantinya.Pertama, buat token kedua untuk digunakan sebagai kunci HMAC, lalu gunakan logika seperti ini untuk merendernya:
Dan kemudian menggunakan operasi yang kongruen saat memverifikasi token:
Token yang dihasilkan untuk satu formulir tidak dapat digunakan kembali dalam konteks lain tanpa diketahui
$_SESSION['second_token']
. Anda harus menggunakan token terpisah sebagai kunci HMAC daripada yang baru saja Anda jatuhkan di halaman.Bonus: Pendekatan Hibrid + Integrasi Ranting
Siapa pun yang menggunakan mesin template Twig dapat memanfaatkan strategi ganda yang disederhanakan dengan menambahkan filter ini ke lingkungan Twig mereka:
Dengan fungsi Twig ini, Anda dapat menggunakan kedua token tujuan umum seperti:
Atau varian yang dikunci:
Twig hanya berhubungan dengan rendering template; Anda masih harus memvalidasi token dengan benar. Menurut pendapat saya, strategi Twig menawarkan fleksibilitas dan kesederhanaan yang lebih besar, sambil mempertahankan kemungkinan untuk keamanan maksimum.
Token CSRF Sekali Pakai
Jika Anda memiliki persyaratan keamanan bahwa setiap token CSRF diizinkan untuk digunakan tepat sekali, strategi paling sederhana membuatnya kembali setelah setiap validasi berhasil. Namun, hal itu akan membatalkan setiap token sebelumnya yang tidak cocok dengan orang-orang yang menjelajahi banyak tab sekaligus.
Paragon Initiative Enterprises memiliki perpustakaan Anti-CSRF untuk kasus sudut ini. Ia bekerja dengan token sekali pakai per bentuk, secara eksklusif. Ketika cukup token disimpan dalam data sesi (konfigurasi default: 65535), itu akan menggilir token tertua yang belum ditebus terlebih dahulu.
sumber
Sepertinya Anda membutuhkan yang lain dengan if.
sumber
md5(uniqid(rand(), TRUE));
konteks keamanan.Variabel
$token
tidak diambil dari sesi saat berada di sanasumber