Prosedur yang tersimpan tidak secara ajaib mencegah injeksi SQL, tetapi prosedur ini membuatnya mencegahnya menjadi jauh lebih mudah. Yang harus Anda lakukan adalah sesuatu seperti yang berikut ini (contoh Postgres):
CREATE OR REPLACE FUNCTION my_func (
IN in_user_id INT
)
[snip]
SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]
Itu dia! Masalahnya hanya muncul ketika membentuk kueri melalui rangkaian string (yaitu SQL dinamis), dan bahkan dalam kasus tersebut Anda mungkin dapat mengikat! (Tergantung pada database.)
Cara menghindari injeksi SQL dalam kueri dinamis Anda:
Langkah 1) Tanyakan pada diri Anda apakah Anda benar-benar membutuhkan permintaan dinamis. Jika Anda menyatukan string hanya untuk mengatur input, maka Anda mungkin melakukan kesalahan. (Ada pengecualian untuk aturan ini - satu pengecualian adalah untuk melaporkan permintaan pada beberapa database, Anda mungkin memiliki masalah kinerja jika Anda tidak memaksanya untuk mengkompilasi permintaan baru dengan setiap eksekusi. Tetapi teliti masalah ini sebelum Anda langsung membahasnya. )
Langkah 2) Meneliti cara yang tepat untuk mengatur variabel untuk RDBMS khusus Anda. Sebagai contoh, Oracle memungkinkan Anda melakukan hal berikut (mengutip dari dokumen mereka):
sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE '
|| v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!
Di sini Anda masih belum menyatukan input. Anda mengikat dengan aman! Hore!
Jika database Anda tidak mendukung sesuatu seperti di atas (semoga tidak satupun dari mereka yang seburuk ini, tapi saya tidak akan terkejut) - atau jika Anda masih benar-benar harus menyatukan input Anda (seperti dalam kasus "kadang-kadang" melaporkan kueri pelaporan sebagai Saya mengisyaratkan di atas), maka Anda harus menggunakan fungsi melarikan diri yang tepat. Jangan menulisnya sendiri. Misalnya postgres menyediakan fungsi quote_literal (). Jadi, Anda akan menjalankan:
sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);
Dengan cara ini jika in_name adalah sesuatu yang licik seperti '[snip] atau 1 = 1' (bagian "atau 1 = 1" berarti memilih semua baris, yang memungkinkan pengguna untuk melihat gaji yang seharusnya tidak seharusnya!), Maka quote_literal menyimpan pantat Anda dengan membuat string yang dihasilkan:
SELECT salary FROM employees WHERE name = '[snip] or 1=1'
Tidak ada hasil yang ditemukan (kecuali jika Anda memiliki beberapa karyawan dengan nama yang sangat aneh.)
Itulah intinya! Sekarang biarkan saya meninggalkan Anda dengan tautan ke posting klasik oleh guru Oracle Tom Kyte tentang masalah SQL Injection, untuk mengarahkan poinnya: Linky