Rabu, 12 April 2017

[PHP+MySQL] Mencegah SQL Injection pada Form Login

(image source :www.sitepoint.com)


SQL Injection adalah tehnik menginjeksi (memasukkan) kode SQL atau SQL Command kedalam SQL Statement melalui field input atau URL suatu website. Kode SQL yang diinject akan berdampak langsung pada database website tersebut, misalnya mem-bypass autentikasi login, melakukan drop table atau mengubah data.

Mengapa bisa begitu? karena kode SQL yang diinject juga akan ikut dijalankan bersamaan dengan SQL Command atau query yang sudah ada.

Biasanya SQL injection terjadi akibat programmer tidak atau kurang memperhatikan input yang didapat dari suatu field atau parameter. Di artikel ini kita akan mempelajari cara mencegah tehnik SQL injection, khususnya mem-bypass autentikasi pada form login. Pada artikels ederhana ini, saya menggunakan PHP 7.0.9, jadi sesuaikan versi PHP yang anda gunakan terlebih dahulu :) .

Persiapan Data
Buat Database dengan nama bebas, misalnya db_test.

Buat tabel bernama t_user seperti berikut :


isi dengan data sebagai berikut :



perhatikan bahwa isi dari field password di hash dengan MD5.

Download file login.php di Google Drive

Buat file dashboard.php ketikkan kode sebagai berikut :

<?php
session_start();
if(isset($_SESSION['sess_adm'])){
echo "Selamat datang : ".$_SESSION['sess_adm'];
?>
Klik disini untuk logout : <a href="logout.php">logout</a>
<?php
}else{
header("location:login.php");
}
?>

Buat file logout.php, ketikkan kode sebagai berikut :

<?php
session_start();
   if(session_destroy()) {
      header("Location: login.php");
   }
?>

Test pertama
buka file login.php yang sudah kita punya, kemudian input username dengan nilai "coba" dan password dengan nilai "1234".

Maka akan muncul pemberitahuan bahwa username atau password salah, ini benar karena username yang benar adalah admin dan passwordnya barbatos.

Pada test pertama, query yang terbentuk seperti berikut:

SELECT t_user_id, username FROM t_user WHERE username = 'test' and password = '81dc9bdb52d04dc20036dbd8313ed055' and is_admin = 1 AND is_active=1 LIMIT 1

Catatan : String 81dc9bdb52d04dc20036dbd8313ed055 berasal dari nilai "1234" yang telah dihash menggunakan MD5, silahkan lihat kode di file login.php untuk lebih lengkapnya.

Test kedua
buka file login.php yang sudah kita punya, kemudian input username dengan nilai"admin" dan password dengan nilai "barbatos"



Maka login sukses dan berhasil masuk ke dashboard.

Test ketiga
Sekarang kita coba SQL Injection, logout terlebih dahulu kemudian ketikkan nilai "admin' or 1=1 #" pada username dan "1234" pada password


Maka hasilnya :



Yap, anda berhasil masuk sebagai admin tanpa tahu password nya terlebih dahulu ;)

Penjelasan
Pada test ketiga ini, query yang terbentuk adalah:

SELECT t_user_id, username FROM t_user WHERE username = 'admin' or 1=1 #' and password = '81dc9bdb52d04dc20036dbd8313ed055' and is_admin = 1 AND is_active=1 LIMIT 1

Query tersebut jika dijalankan via phpmyadmin menghasilkan sebagai berikut :



Query yang terbentuk adalah : SELECT t_user_id, username FROM t_user WHERE username = 'admin' or 1=1
Mengapa begitu? karena saat kita menginput nilai "admin' or 1=1 #" pada textbox username, karakter setelah # akan dianggap sebagai komentar sehingga diabaikan. Sedangkan OR 1=1 berfungsi agar kondisi apapun selalu bernilai TRUE karena memang nilai 1=1.

Catatan :
sebenarnya, tanpa mengetahui username nya adalah admin, kita tetap bisa masuk sebagai "admin",contohnya dengan query SELECT t_user_id, username FROM t_user WHERE username = 'x' or 1=

Pencegahan
Untuk pencegahan terhadap SQL Injection seperti ini, kita bisa menggunakan fungsi mysqli_real_escape_string atau menggunakan prepared statement.

Test ke-empat
ubah kode pada file login.php dari :

$myusername = $_POST['username'];
$mypassword = $_POST['password'];

menjadi

$myusername = mysqli_real_escape_string($db,$_POST['username']);
$mypassword = mysqli_real_escape_string($db,$_POST['password']);


Nantinya setiap terdapat karakter escape string seperti kutip satu (') atau kutip dua ("), akan ditambahkan karakter backslash (\) sehingga query pada test ketiga menjadi :


SELECT t_user_id, username FROM t_user WHERE username = 'admin\' or 1=1 #' and password = '81dc9bdb52d04dc20036dbd8313ed055' and is_admin = 1 AND is_active=1 LIMIT 1


Sehingga return yang didapat dari query tersebut adalah empty atau kosong.

Semoga bermanfaat

                http://php.net/manual/en/mysqli.real-escape-string.php

Artikel ini dibuat oleh Yudha Tri Putra sebagai penulis artikel, diperbolehkan menyalin artikel ini secara utuh tanpa mengubah atau menambah isi artikel.

2 komentar:

(C) 2018. Diberdayakan oleh Blogger.

Categories

Followers