12 Okt 2014

Proteksi CSRF dengan PHP

Apa itu CSRF ? Dalam serangan Cross Site Request Forgery (CSRF), penyerang mengelabuhi korban u... thumbnail 1 summary

Apa itu CSRF ?
Dalam serangan Cross Site Request Forgery (CSRF), penyerang mengelabuhi korban untuk memuat informasi sensitif atau melakukan transaksi tanpa sepengetahuan mereka. Hal ini terutama terjadi pada aplikasi web yang buruk kode programnya untuk memicu logika bisnis menggunakan permintaan GET.
Idealnya, permintaan GET  idempoten secara alamiahnya. Idempotency berarti halaman yang sama dapat diakses beberapa kali tanpa menimbulkan efek samping. Oleh karena itu, permintaan GET harus digunakan hanya untuk mengakses informasi dan tidak untuk melakukan transaksi.
Contoh berikut menunjukkan bagaimana aplikasi dibuat menggunakan kode yang buruk sehingga mendukung serangan CSRF:
1
2
3
4
5
<?php
if (isset($_REQUEST["name"],$_REQUEST["amount"])) {
    // process the request and transfer the amount from
    // from the logged in user to the passed name.
}
Mari kita asumsikan Bob ingin melakukan serangan CSRF pada Alice, dan membangun sebuah URL seperti berikut dan mengirimkannya ke email Alice :
1
Jika Alice mengeklik link ini, dan sudah login ke website, permintaan ini akan memotong $1.000 dari rekening dan mentransfernya ke Bob! Atau, Bob dapat membuat image link yang mana atribut src  merujuk ke URL.
1
<img src="http://example.com/process.php?name=Bob&amount=1000"width="1" height="1"/>
Browser tidak dapat menampilkan gambar apapun seperti yang diharapkan, tetapi masih akan membuat permintaan menggunakan URL yang akan melakukan transaksi tanpa memberitahu Alice.
Solusinya adalah untuk memproses fungsi yang mengubah keadaan database dalam permintaan POST, dan hindari menggunakan $_REQUEST. Gunakan $_GET untuk mengambil parameter GET, dan menggunakan $_POST untuk mengambil parameter POST.
Selain itu, harus ada token acak disebut token CSRF terkait dengan setiap permintaan POST. Ketika user login ke akunnya, aplikasi harus menghasilkan token acak dan menyimpannya dalam sesi. Setiap kali form apapun akan ditampilkan kepada pengguna, token harus hadir di halaman sebagai field input tersembunyi. Logika aplikasi harus memeriksa token dan memastikan bahwa itu cocok dengan yang yang ada dalam session saat ini.
Sumber

Sekarang, mari kita bikin Proteksi CSRF yang mudah.

Buat 3 file php yaitu index.php , config.php dan output.php

Bikin kode config dulu yuk.

<?php
session_start(); 
function createToken()
{
$token= base64_encode(openssl_random_pseudo_bytes(32));
$_SESSION['csrfvalue']=$token;
return $token; }
function unsetToken()
{
unset($_SESSION['csrfvalue']);
}
function validation()
{ $csrfvalue = isset($_SESSION['csrfvalue']) ? mysql_real_escape_string($_SESSION['csrfvalue']) : ''; if(isset($_POST['csrf_name']))
{ $value_input=$_POST['csrf_name'];
if($value_input==$csrfvalue)
{
unsetToken();
return true; }else{
unsetToken();
return false;
}
}else{
unsetToken();
return false;
}
}
?>
Function createToken berfungsi untuk membuat ekripsi teks openssl_random_pseudo_bytes (kriptografi algorithma random value) dengan menggunakan base64. Lalu membuat sebuah session bernama csrfvalue berisikan data teks tadi.

Function validation berfungsi memvalidasi sebuah input $_POST , di sini saya membaca isi $_POST dari input name csrf_name.

Function unsetToken dijalankan saat akhir validation , fungsinya saat halaman menuju output.php maka $_SESSION['csrfvalue'] langsung dihapus. Tujuannya memproteksi resubmit pada output.php berkali-kali.


Sekarang kita membuat script pada index.php

<?php
require_once("config.php");
?>
<form action="output.php" method="post">
<input type="hidden" name="csrf_name" value="<?php echo createToken();?>"/>
<input type="text" name="nama"/>
<button type="submit">Kirim</button>
</form>
Pada halaman index.php ini ,includekan config.php tadi. Lalu sebuah form dibuat dengan method POST. untuk membuat CSRF proteksi, cukup buat input hidden dengan name csrf_name dan value nya generate fungsi createToken pada config.php

Sekarang kita buat script output.php

<?php
require_once("config.php");
if(validation()==true)
{
echo "Berhasil ".$_POST['nama'];
}else{
echo "Gagal";
}
?>
Untuk memvalidasi data yang telah di post pada halaman index.php. Setelah tampil halaman output.php maka resubmit lagi / tekan F5 atau Reload halaman.

Untuk tes artikel ini langsung, saya sudah sisipkan file nya dengan mengklik tombol Download di bawah ini