it-swarm.asia

Apakah prosedur tersimpan mencegah injeksi SQL?

Benarkah prosedur tersimpan mencegah serangan injeksi SQL terhadap database PostgreSQL? Saya melakukan sedikit riset dan menemukan bahwa SQL Server, Oracle dan MySQL tidak aman terhadap injeksi SQL bahkan jika kita hanya menggunakan prosedur tersimpan. Namun, masalah ini tidak ada di PostgreSQL.

Apakah implementasi prosedur tersimpan dalam inti PostgreSQL mencegah serangan injeksi SQL atau itu sesuatu yang lain? Atau apakah PostgreSQL juga rentan terhadap injeksi SQL walaupun kita hanya menggunakan prosedur tersimpan? Jika demikian, tolong tunjukkan saya contoh (mis. Buku, situs, kertas, dll).

84
Am1rr3zA

Tidak, prosedur tersimpan tidak mencegah injeksi SQL. Berikut adalah contoh aktual (dari aplikasi in-house yang dibuat oleh seseorang tempat saya bekerja) dari prosedur tersimpan yang sayangnya mengizinkan injeksi SQL:

Kode server sql ini:

CREATE PROCEDURE [dbo].[sp_colunmName2]   
    @columnName as nvarchar(30),
    @type as nvarchar(30), 
    @searchText as nvarchar(30)           
AS
BEGIN
    DECLARE @SQLStatement NVARCHAR(4000)
    BEGIN
        SELECT @SQLStatement = 'select * from Stations where ' 
            + @columnName + ' ' + @type + ' ' + '''' + @searchText + '''' 
        EXEC(@SQLStatement)
    END      
END
GO

kira-kira sama dengan postgres:

CREATE or replace FUNCTION public.sp_colunmName2 (
    columnName  varchar(30),
    type varchar(30), 
    searchText  varchar(30) ) RETURNS SETOF stations LANGUAGE plpgsql            
AS
$$
DECLARE SQLStatement VARCHAR(4000);
BEGIN
    SQLStatement = 'select * from Stations where ' 
            || columnName || ' ' || type || ' ' || ''''|| searchText || '''';
    RETURN QUERY EXECUTE  SQLStatement;
END
$$;

Gagasan pengembang adalah membuat prosedur pencarian yang serba guna, tetapi hasilnya adalah klausa WHERE dapat berisi apa pun yang diinginkan pengguna, memungkinkan kunjungan dari Tabel Bobby kecil .

Apakah Anda menggunakan pernyataan SQL atau prosedur tersimpan tidak masalah. Yang penting adalah apakah SQL Anda menggunakan parameter atau string gabungan. Parameter mencegah injeksi SQL; string bersambung memungkinkan injeksi SQL.

71
Kyralessa

Serangan SQL-Injection adalah mereka yang inputnya tidak dipercaya langsung ditambahkan pertanyaan, yang memungkinkan pengguna untuk secara efektif mengeksekusi kode arbitrer, seperti yang diilustrasikan dalam komik XKCD kanonik ini.

Dengan demikian, kita mendapatkan situasi:

 userInput = getFromHTML # "Robert ') Drop table student; -" 
 
 Query = "Pilih * dari siswa di mana studentName =" + userInput 

Prosedur Tersimpan, secara umum, pertahanan yang baik terhadap serangan injeksi SQL karena parameter yang masuk tidak pernah diuraikan.

Dalam prosedur tersimpan, di sebagian besar DB (dan program, jangan lupa bahwa kueri yang dikompilasi dihitung sebagai prosedur tersimpan) terlihat seperti berikut:

 
 
 membuat foo fureure Tersimpan (
 pilih * dari siswa di mana studentName =: 1 
); 
 

Kemudian, ketika program menginginkan akses, ia memanggil foo(userInput) dan dengan senang hati mengambil hasilnya.

Prosedur tersimpan bukanlah pertahanan ajaib terhadap SQL-Injection, karena orang cukup mampu menulis prosedur tersimpan yang buruk . Namun, kueri yang dikompilasi sebelumnya, baik yang disimpan dalam database atau dalam program, jauh lebih sulit untuk membuka celah keamanan di jika Anda memahami cara kerja SQL-Injection.

Anda dapat membaca lebih lanjut tentang SQL-Injection:

46

Ya, sampai batas tertentu.
Prosedur Tersimpan saja tidak akan mencegah SQL Injection.

Ijinkan saya mengutip tentang SQL Injection dari OWASP

Serangan injeksi SQL terdiri dari penyisipan atau "injeksi" dari permintaan SQL melalui input data dari klien ke aplikasi. Eksploit injeksi SQL yang berhasil dapat membaca data sensitif dari basis data, memodifikasi data basis data (Masukkan/Perbarui/Hapus), jalankan operasi administrasi pada basis data (seperti mematikan DBMS), memulihkan konten file yang diberikan saat ini pada file DBMS sistem dan dalam beberapa kasus mengeluarkan perintah ke sistem operasi. Serangan injeksi SQL adalah jenis serangan injeksi, di mana perintah SQL disuntikkan ke input data-pesawat untuk mempengaruhi pelaksanaan perintah SQL yang telah ditetapkan.

Anda harus membersihkan input pengguna dan tidak menggabungkan pernyataan SQL, bahkan jika Anda menggunakan prosedur tersimpan.

Jeff Attwood menjelaskan konsekuensi menggabungkan sql di " Beri saya parameterisasi SQL, atau beri saya kematian "

Berikut ini adalah kartun menarik yang muncul di benak saya setiap kali saya mendengar SQL Injection alt text Saya pikir Anda mengerti intinya :-)

Lihat Lembar Pencegahan Injeksi SQL , metode pencegahan dijelaskan dengan rapi ...

29
CoderHawk

Rangkaian string adalah penyebab dari SQL Injection. Ini dihindari menggunakan parametrisation.

Prosedur yang tersimpan menambahkan lapisan keamanan tambahan dengan memberlakukan sintaksis tidak valid ketika Anda menggabungkan, tetapi tidak "lebih aman" jika Anda menggunakan, katakanlah, SQL dinamis di dalamnya.

Jadi, kode Anda di atas disebabkan oleh gabungan dari string ini

  • exec sp_GetUser '
  • x' AND 1=(SELECT COUNT(*) FROM Client); --
  • ' , '
  • monkey
  • '

Ini memberikan sintaks yang tidak valid, untungnya

Parametrising itu akan memberikan

exec sp_GetUser 'x'' AND 1=(SELECT COUNT(*) FROM Client); --' , 'monkey'

Ini berarti

  • @UserName = x' AND 1=(SELECT COUNT(*) FROM Client); --
  • @Password = monkey

Sekarang, dalam kode di atas Anda tidak akan mendapatkan baris karena saya menganggap Anda tidak memiliki pengguna x' AND 1=(SELECT COUNT(*) FROM Client); --

Jika proc tersimpan tampak seperti ini (menggunakan concatenated dynamic SQL ), maka panggilan proc tersimpan parametris Anda masih akan memungkinkan SQL Injection

...
SET @sql = 'SELECT userName from users where userName = ''' + 
               @UserName + 
               ''' and userPass = ''' +
               @Password +
               ''''
EXEC (@sql)
....

Jadi, seperti yang ditunjukkan, rangkaian string adalah musuh utama untuk injeksi SQL

Prosedur yang tersimpan memang menambahkan enkapsulasi, penanganan transaksi, pengurangan izin, dll, tetapi masih dapat disalahgunakan untuk injeksi SQL.

Anda dapat melihat Stack Overflow untuk informasi lebih lanjut tentang parametrisation

12
gbn

"Serangan injeksi SQL terjadi ketika input pengguna dikodekan dengan tidak benar. Biasanya, input pengguna adalah beberapa data yang dikirimkan pengguna dengan kueri, mis. Nilai dalam $_GET, $_POST, $_COOKIE, $_REQUEST, atau $_SERVER array. Namun, input pengguna juga dapat berasal dari berbagai sumber lain, seperti soket, situs web jarak jauh, file, dll. Oleh karena itu, Anda harus benar-benar memperlakukan semuanya kecuali konstanta (Suka 'foobar') sebagai input pengguna . "

Saya telah menyelidiki secara menyeluruh tentang hal ini baru-baru ini dan ingin berbagi dengan orang lain materi yang cukup menarik, sehingga menjadikan pos ini lebih lengkap dan instruktif untuk semua orang.



Dari YouTube


Dari Wikipedia


Dari OWASP


Dari PHP Manual


Dari Microsoft dan Oracle


Stack Overflow


Pemindai injeksi SQL

10
Ilia Rostovtsev

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 berikut (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 penggabungan string (yaitu SQL dinamis), dan bahkan dalam kasus-kasus itu 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 salah melakukannya. (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. Misalnya, 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 (mudah-mudahan 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 pada subjek SQL Injection, untuk mengarahkan titik rumah: Linky

2
MWDB