MySQL - dan SQL Injection

Jika Anda mengambil input pengguna melalui halaman web dan memasukkannya ke database MySQL, ada kemungkinan Anda membiarkan diri Anda terbuka lebar untuk masalah keamanan yang dikenal sebagai SQL Injection. Bab ini akan mengajari Anda cara membantu mencegah hal ini terjadi dan membantu Anda mengamankan skrip dan pernyataan MySQL Anda.

SQL Injection biasanya terjadi ketika Anda meminta input pengguna, seperti nama mereka dan alih-alih nama mereka memberi Anda pernyataan MySQL yang secara tidak sadar akan Anda jalankan di database Anda.

Jangan pernah mempercayai data yang diberikan oleh pengguna, proses data ini hanya setelah validasi; biasanya, ini dilakukan dengan pencocokan pola. Dalam contoh berikut, nama pengguna dibatasi untuk karakter alfanumerik ditambah garis bawah dan dengan panjang antara 8 dan 20 karakter - ubah aturan ini sesuai kebutuhan.

if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
   $result = mysql_query("SELECT * FROM users WHERE username = $matches[0]");
} else  {
   echo "username not accepted";
}

Untuk mendemonstrasikan masalah ini, pertimbangkan kutipan berikut.

// supposed input
$name = "Qadir'; DELETE FROM users;";
mysql_query("SELECT * FROM users WHERE name = '{$name}'");

Panggilan fungsi seharusnya mengambil record dari tabel users, di mana kolom nama cocok dengan nama yang ditentukan oleh pengguna. Dalam keadaan normal, $ name hanya akan berisi karakter alfanumerik dan mungkin spasi. Tapi di sini, dengan menambahkan kueri yang sama sekali baru ke$name, panggilan ke database berubah menjadi bencana. Kueri DELETE yang disuntikkan menghapus semua catatan dari pengguna.

Untungnya, jika Anda menggunakan MySQL, file mysql_query()function tidak mengizinkan query stacking atau mengeksekusi beberapa query dalam satu panggilan fungsi. Jika Anda mencoba untuk menumpuk kueri, panggilan gagal.

Namun, ekstensi database PHP lainnya, seperti SQLite dan PostgreSQL, dengan senang hati menjalankan kueri bertumpuk, menjalankan semua kueri yang disediakan dalam satu string dan membuat masalah keamanan yang serius.

Mencegah Injeksi SQL

Anda dapat menangani semua karakter escape dengan cerdas dalam bahasa skrip seperti PERL dan PHP. Ekstensi MySQL untuk PHP menyediakan fungsi tersebutmysql_real_escape_string() untuk menghindari karakter input yang khusus untuk MySQL.

if (get_magic_quotes_gpc()) {
   $name = stripslashes($name);
}

$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM users WHERE name = '{$name}'");

The LIKE Quandary

Untuk mengatasi masalah LIKE, mekanisme pelolosan khusus harus mengonversi karakter% dan _ yang disediakan pengguna menjadi literal. Menggunakanaddcslashes(), fungsi yang memungkinkan Anda menentukan rentang karakter yang akan diloloskan.

$sub = addcslashes(mysql_real_escape_string("%something_"), "%_");
// $sub == \%something\_
mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");