Skip to content

Mencegah SQL Injection dengan Prepared Statements dan Parameterized Queries

Updated: at 07.24

Dalam pengembangan aplikasi web, keamanan adalah aspek yang sangat penting untuk diperhatikan. Salah satu ancaman keamanan yang sering terjadi adalah serangan SQL Injection. SQL Injection adalah teknik di mana penyerang memasukkan kode SQL berbahaya melalui input pengguna yang tidak tervalidasi, yang dapat mengakibatkan akses tidak sah ke database atau manipulasi data.

Salah satu cara paling efektif untuk mencegah serangan SQL Injection adalah dengan menggunakan Prepared Statements dengan Parameterized Queries. Dalam artikel ini, kita akan membahas apa itu Prepared Statements, bagaimana cara menggunakannya dengan Parameterized Queries, dan mengapa pendekatan ini sangat direkomendasikan untuk mengamankan aplikasi Anda.

Apa itu Prepared Statements? Prepared Statements adalah fitur yang disediakan oleh banyak database modern seperti PostgreSQL, MySQL, SQL Server, dan Oracle. Dengan menggunakan Prepared Statements, Kita dapat memisahkan struktur query SQL dari nilai parameter yang akan dimasukkan ke dalamnya.

Alih-alih membangun query SQL secara dinamis dengan menggabungkan nilai parameter secara langsung, Kita menentukan struktur query terlebih dahulu dengan placeholder untuk nilai parameter. Placeholder ini biasanya ditandai dengan tanda tanya (?) atau nama parameter dengan awalan titik dua (:).

Contoh Prepared Statement dalam PostgreSQL:

SELECT account_balance FROM user_data WHERE user_name = $1;

Dalam contoh di atas, $1 adalah placeholder untuk nilai parameter user_name.

Bagaimana Prepared Statements Mencegah SQL Injection? Prepared Statements bekerja dengan cara yang berbeda dibandingkan query SQL dinamis biasa. Ketika menggunakan Prepared Statements, query SQL dikirim sebagai suatu template ke database, dan database sudah mengetahui secara tepat apa yang akan dilakukan oleh query tersebut. Baru setelah itu, nilai parameter seperti username dan password dimasukkan ke dalam query hanya sebagai nilai saja.

Ini berarti nilai parameter tidak dapat mempengaruhi logika atau struktur dari query SQL itu sendiri, karena database sudah tahu apa yang akan dilakukan query tersebut sebelum memasukkan nilai parameternya. Database akan memperlakukan nilai parameter sebagai teks biasa dan bukan sebagai bagian dari perintah SQL.

Misalnya, jika ada query yang diparameterisasi seperti ini:

SELECT * FROM users WHERE username = ? AND password = ?;

Meskipun seseorang memasukkan nilai seperti admin' -- ke dalam parameter username dengan tujuan untuk mengubah logika query, database sudah tahu bahwa query tersebut mencari username dan password yang spesifik. Sehingga database akan mencari username yang bernilai persis admin' -- dan menganggapnya sebagai nilai literal, bukan sebagai bagian dari perintah SQL.

Ini berbeda dengan query SQL dinamis yang rentan, di mana nilai yang diinputkan oleh user digabungkan langsung ke dalam string query, sehingga dapat mengubah logika query dan menyebabkan SQL Injection.

Bagaimana Cara Menggunakan Prepared Statements dengan Parameterized Queries? Setelah Kita menentukan struktur query dengan placeholder, Kita dapat menggunakan Parameterized Queries untuk mengirimkan nilai parameter secara terpisah. Berikut adalah langkah-langkah menggunakan Prepared Statements dengan Parameterized Queries dalam Node.js dengan library node-pg:

  1. Instal library node-pg:

    npm install pg
    
  2. Buat instance dari Pool yang dikonfigurasi dengan informasi koneksi database:

    import { Pool } from "pg";
    
    const pool = new Pool({
      // Konfigurasi koneksi database
    });
    
  3. Definisikan fungsi yang akan mengeksekusi query dengan Prepared Statement:

    async function getUserBalance(customerName) {
      const query = "SELECT account_balance FROM user_data WHERE user_name = $1";
      const values = [customerName];
    
      try {
        const result = await pool.query(query, values);
        return result.rows[0].account_balance;
      } catch (error) {
        console.error("Error executing query", error);
        throw error;
      }
    }
    

    Dalam contoh di atas, query SQL didefinisikan dengan placeholder $1, dan nilai parameter customerName dikirimkan melalui array values.

  4. Panggil fungsi dengan nilai parameter yang diinginkan:

    getUserBalance("john_doe")
      .then(balance => {
        console.log("Account balance:", balance);
      })
      .catch(error => {
        console.error("Error:", error);
      });
    

Mengapa Menggunakan Prepared Statements dengan Parameterized Queries? Ada beberapa alasan kuat mengapa Kita harus menggunakan Prepared Statements dengan Parameterized Queries dalam pengembangan aplikasi:

  1. Keamanan: Prepared Statements dengan Parameterized Queries memisahkan data dari perintah SQL. Nilai parameter dikirimkan secara terpisah dari query SQL, sehingga database dapat membedakan antara kode SQL dan data. Ini mencegah serangan SQL Injection karena nilai parameter tidak diinterpretasikan sebagai bagian dari perintah SQL. Penyerang tidak dapat memanipulasi query SQL dengan memasukkan kode berbahaya melalui nilai parameter.

  2. Performansi: Prepared Statements dapat di-compile dan di-optimize oleh database sebelum dieksekusi. Ketika menggunakan Prepared Statements, database hanya perlu melakukan parsing dan kompilasi sekali untuk struktur query yang sama, dan dapat menggunakan rencana eksekusi yang sama untuk eksekusi selanjutnya dengan nilai parameter yang berbeda. Ini mengurangi overhead parsing dan kompilasi berulang, sehingga meningkatkan performansi aplikasi.

  3. Readability dan Maintainability: Penggunaan Prepared Statements dengan Parameterized Queries membuat kode lebih mudah dibaca dan dipelihara. Query SQL terpisah dari nilai parameter, sehingga struktur query lebih jelas. Ini juga mengurangi kesalahan pengetikan atau kesalahan sintaksis dalam membangun query secara dinamis.

  4. Kompatibilitas: Prepared Statements didukung oleh sebagian besar database modern seperti PostgreSQL, MySQL, SQL Server, dan Oracle. Menggunakan Prepared Statements memastikan kompatibilitas yang lebih baik dengan berbagai database dan memudahkan portabilitas kode.

Kesimpulan Menggunakan Prepared Statements dengan Parameterized Queries adalah praktik terbaik dalam pengembangan aplikasi untuk mencegah serangan SQL Injection. Dengan memisahkan struktur query dari nilai parameter, Kita dapat menghindari risiko keamanan yang terkait dengan pembuatan query secara dinamis.

Selain meningkatkan keamanan, Prepared Statements juga menawarkan manfaat dalam hal performansi, readability, dan maintainability kode. Sebagai developer, sangat penting untuk memahami dan menerapkan teknik ini dalam pengembangan aplikasi Anda.

Dengan menggunakan Prepared Statements dan Parameterized Queries, Kita dapat membangun aplikasi yang lebih aman, efisien, dan mudah dipelihara. Jadi, pastikan untuk selalu menggunakan pendekatan ini saat berinteraksi dengan database dalam proyek-proyek Anda.

Referensi