TL; DR
- Aplikasi menerima input, dalam hal ini 'Nancy', tanpa berusaha - membersihkan input, seperti dengan melarikan diri karakter khusus
sekolah => MASUKKAN KE DALAM NILAI siswa ( 'Nancy' ); INSERT 0 1
- Injeksi SQL terjadi ketika input ke dalam perintah basis data dimanipulasi untuk - menyebabkan server basis data mengeksekusi SQL
school => INSERT INTO students VALUES ( 'Robert' ); Siswa DROP TABLE ; - '); INSERT 0 1 TABEL DROP
- Catatan siswa sekarang hilang - itu bisa lebih buruk!
school => SELECT * FROM siswa ;
ERROR : hubungan "mahasiswa" tidak tidak ada
GARIS 1 : PILIH * DARI siswa ; ^
Ini menjatuhkan (menghapus) tabel siswa.
( Semua contoh kode dalam jawaban ini dijalankan pada server database PostgreSQL 9.1.2. )
Untuk memperjelas apa yang terjadi, mari coba ini dengan tabel sederhana yang hanya berisi bidang nama dan tambahkan satu baris:
school => CREATE TABLE siswa ( nama TEXT PRIMARY KEY );
PEMBERITAHUAN : CREATE TABLE / PRIMARY KEY akan membuat implisit indeks "students_pkey" untuk tabel "mahasiswa" MENCIPTAKAN TABLE
sekolah => INSERT INTO siswa NILAI ( 'John' ); INSERT 0 1
Mari kita asumsikan aplikasi menggunakan SQL berikut untuk memasukkan data ke dalam tabel:
INSERT INTO siswa NILAI ( 'foobar' );
Ganti foobar
dengan nama siswa yang sebenarnya. Operasi memasukkan normal akan terlihat seperti ini:
- Input: Nancy
sekolah => INSERT INTO siswa NILAI ( 'Nancy' ); INSERT 0 1
Saat kami menanyakan tabel, kami mendapatkan ini:
school => SELECT * FROM siswa ;
nama
-------
John
Nancy
( 2 baris )
Apa yang terjadi ketika kita memasukkan nama Little Bobby Tables ke dalam tabel?
- Input: Robert '); Siswa DROP TABLE; -
sekolah => MASUKKAN KE NILAI siswa ( 'Robert' ); Siswa DROP TABLE ; - '); INSERT 0 1 MEJA DROP
Injeksi SQL di sini adalah hasil dari nama siswa yang mengakhiri pernyataan dan termasuk DROP TABLE
perintah terpisah ; dua tanda hubung pada akhir input dimaksudkan untuk mengomentari kode sisa yang jika tidak akan menyebabkan kesalahan. Baris terakhir dari output mengonfirmasi bahwa server database telah menjatuhkan tabel.
Penting untuk diperhatikan bahwa selama INSERT
operasi aplikasi tidak memeriksa input untuk setiap karakter khusus, dan oleh karena itu memungkinkan input sewenang-wenang untuk dimasukkan ke dalam perintah SQL. Ini berarti bahwa pengguna jahat dapat memasukkan, ke dalam bidang yang biasanya dimaksudkan untuk input pengguna, simbol-simbol khusus seperti tanda kutip bersama dengan kode SQL sewenang-wenang untuk menyebabkan sistem database untuk mengeksekusinya, maka dari itu injeksi SQL .
Hasil?
school => SELECT * FROM siswa ;
ERROR : hubungan "mahasiswa" tidak tidak ada
GARIS 1 : PILIH * DARI siswa ; ^
Injeksi SQL adalah database yang setara dengan kerentanan eksekusi kode arbitrer jarak jauh dalam sistem operasi atau aplikasi. Dampak potensial dari serangan injeksi SQL yang sukses tidak dapat diremehkan - tergantung pada sistem database dan konfigurasi aplikasi, ini dapat digunakan oleh penyerang untuk menyebabkan kehilangan data (seperti dalam kasus ini), mendapatkan akses tidak sah ke data, atau bahkan mengeksekusi kode arbitrer pada mesin host itu sendiri.
Seperti dicatat oleh komik XKCD, salah satu cara untuk melindungi terhadap serangan injeksi SQL adalah membersihkan sanitas basis data, seperti dengan melarikan diri dari karakter khusus, sehingga mereka tidak dapat memodifikasi perintah SQL yang mendasarinya dan karena itu tidak dapat menyebabkan eksekusi kode SQL sewenang-wenang. Jika Anda menggunakan query parameter, seperti dengan menggunakan SqlParameter
dalam ADO.NET, input akan, setidaknya, secara otomatis dibersihkan untuk menjaga terhadap injeksi SQL.
Namun, membersihkan input pada level aplikasi mungkin tidak menghentikan teknik injeksi SQL yang lebih canggih. Misalnya, ada cara untuk menghindari mysql_real_escape_string
fungsi PHP . Untuk perlindungan tambahan, banyak sistem database mendukung pernyataan yang disiapkan . Jika diimplementasikan dengan benar di backend, pernyataan yang disiapkan dapat membuat injeksi SQL tidak mungkin dengan memperlakukan input data secara semantik terpisah dari sisa perintah.