Secure Development on PHP – Part 1 : SQL Injection

thumbnail

Introduction

Berdasarkan data dari W3Techs pada April 2019, PHP merupakan bahasa pemrograman server-side terpopuler dan digunakan oleh 79% website yang ada. Tapi,apakah semua developer sudah tahu tentang secure development pada PHP? Lantas,bagaimana secure development pada PHP itu? Jawabannya ada pada artikel dibawah ini yang dibagi dalam beberapa part.

SQL Injection

SQL Injection adalah salah satu kerentanan aplikasi web paling berbahaya. Berdasarkan OWASP, SQL Injection secara konsisten menempati peringkat pertama. Jika Input User langsung ke Query SQL tanpa divalidasi, Attacker dapat memanipulasi Query tersebut dam mampu mengembalikan hasil sesuai keinginan mereka.

Serangan SQL Injection yang berhasil dapat mengakibatkan pelanggaran data seperti mengekspos nama pengguna, kata sandi, informasi kartu kredit, dan data sensitif lainnya. Dalam beberapa kasus, bahkan serangan SQL Injection juga mampu merusak seluruh server web.

Causes of Vulnerability

Sebagian besar kerentanan disebabkan oleh kebiasaan yang buruk dalam pengkodean atau kurangnya kesadaran akan keamanan pada aplikasi PHP di kalangan developer.

Dalam pemrograman server-side, harus diterapkan 2 prosedur utama yaitu validasi dan sanitasi. Dengan begitu, server side mampu melakukan validasi terhadap data yang diproses dan memastikan bahwa output yang muncul bukan kode yang berbahaya atau malicious. Jika kedua prosedur dasar ini diterapkan untuk setiap halaman web, maka meminimalkan kemungkinan terkena masalah yang kritis.

SQL Injection Prevention in PHP

Insecure Code Sample :
Pada contoh berikut, Parameter high3 masuk ke Query tanpa validasi.

$high3id = $_GET['high3'];
$query = "SELECT * FROM high3 WHERE high3id = '$high3id'"; 

Attacker dapat mengirim query tambahan yang nantinya akan di eksekusi oleh server. Sebagai contoh :

1'+union+select+1,version(),3,4,5

Sehingga query akan menjadi :

$query = "SELECT * FROM high3 WHERE high3id = '1'+union+select+1,version(),3,4,5";

Attacker bisa menambahkan query lain untuk mendapatkan informasi sensitif pada database.

Solusi untuk masalah ini dengan menggunakan parameterized SQL queries (prepared statement). Jika menggunakan parameterized queries, database tahu bagian mana yang merupakan query dan mana yang merupakan data (input pengguna) karena request dikirimkan terpisah dan menghilangkan kemungkinan tercampurnya input pengguna dan SQL query.

Disarankan untuk menggunakan PHP Data Objects (PDO) untuk mengeksekusi statement dalam script PHP. PDO diperkenalkan di PHP 5.1 dan tersedia sebagai ekstensi PECL di PHP 5.0. Hindari menggunakan ekstensi mysql dan mysqli dalam kode PHP karena sudah deprecated/outdated dan ganti dengan PDO.

Secure Code Sample :
Dalam contoh file PHP ini, user_id tidak diteruskan ke query secara langsung. Sebaliknya, user_id diganti dengan placeholder. Database backend akan tahu apa yang harus diganti dengan placeholder ketika fungsi execute () dijalankan.

// User ID must not be empty, must be numeric and must be less than 5 characters long
if((!empty($_GET['user_id'])) && (is_numeric($_GET['user_id'])) && (mb_strlen($_GET['user_id'])<5)) {

  $servername = "localhost";
  $username = "username";
  $password = "password";
  $database = "dbname"; 

  // Establish a new connection to the SQL server using PDO
  try { 
    $conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password); 

    // Assign user input to the $user_id variable 
    $user_id = $_GET['user_id']; 

    // Prepare the query and set a placeholder for user_id 
    $sth = $conn->prepare('SELECT user_name, user_surname FROM users WHERE user_id=?');

    // Execute the query by providing the user_id parameter in an array
    $sth->execute(array($user_id));

    // Fetch all matching rows
    $user = $sth->fetch();

    // If there is a matching user, display their info
    if(!empty($user)) {
      echo "Welcome ".$user['user_name']." ".$user['user_surname']; 
    } else {
      echo "No user found"; 
    }

    // Close the connection
    $dbh = null; 
  } catch(PDOException $e) {
    echo "Connection failed."; 
  }
} else {
  echo "User ID not specified or invalid."; 
}

Conclusion

Parameterized query memecahkan kerentanan SQL Injection. Contoh ini menggunakan PDO untuk memperbaiki kerentanan tetapi juga masih bisa menggunakan fungsi mysqli untuk mencegah SQL Injection. Namun, PDO lebih mudah digunakan, lebih portabel, dan mendukung penggunaan named parameters.

Reference :

Ingin tahu bagaimana attacking SQL Injection dengan tools bernama SQLMap? kunjungi SQLMap for SQL Injection.

One thought on “Secure Development on PHP – Part 1 : SQL Injection

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top