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).
postgresql
security
sql-injection
Am1rr3zA
sumber
sumber
Jawaban:
Tidak, prosedur tersimpan tidak mencegah injeksi SQL. Berikut ini 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:
kira-kira sama dengan postgres:
Gagasan pengembang adalah membuat prosedur pencarian serbaguna, tetapi hasilnya adalah klausa WHERE dapat berisi apa pun yang diinginkan pengguna, memungkinkan kunjungan dari Bobby Tables yang 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.
sumber
Serangan SQL-Injection adalah serangan di mana input yang tidak dipercaya secara langsung ditambahkan, memungkinkan pengguna untuk secara efektif mengeksekusi kode arbitrer, seperti yang diilustrasikan dalam komik XKCD kanonik ini.
Dengan demikian, kita dapat situasi:
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:
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 telah dikompilasi sebelumnya, baik yang disimpan dalam database atau dalam program, jauh lebih sulit untuk membuka celah keamanan jika Anda memahami cara kerja SQL-Injection.
Anda dapat membaca lebih lanjut tentang SQL-Injection:
sumber
Ya, sampai batas tertentu.
Prosedur Tersimpan saja tidak akan mencegah SQL Injection.
Ijinkan saya mengutip tentang SQL Injection dari OWASP
Anda harus membersihkan input pengguna dan tidak menggabungkan pernyataan SQL, bahkan jika Anda menggunakan prosedur tersimpan.
Jeff Attwood menjelaskan konsekuensi menggabungkan sql di " Beri aku parameterisasi SQL, atau beri aku kematian "
Berikut ini adalah kartun menarik yang muncul di benak saya setiap kali saya mendengar SQL Injection, saya pikir Anda mengerti :-)
Lihat pada Cheat Sheet Pencegahan Injeksi SQL , metode pencegahan dijelaskan dengan rapi ...
sumber
Rangkaian string adalah penyebab SQL Injection. Ini dihindari menggunakan parametrisation.
Prosedur yang tersimpan menambahkan lapisan keamanan tambahan dengan memberlakukan sintaksis yang tidak valid ketika Anda menggabungkan, tetapi tidak "aman" jika Anda menggunakan, katakanlah, SQL dinamis di dalamnya.
Jadi, kode Anda di atas disebabkan oleh rangkaian string ini
exec sp_GetUser '
x' AND 1=(SELECT COUNT(*) FROM Client); --
' , '
monkey
'
Untungnya , ini memberikan sintaks yang tidak valid
Parametrising itu akan memberi
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 yang disimpan tampak seperti ini (menggunakan SQL dinamis gabungan ), maka panggilan proc tersimpan parametris Anda akan tetap mengizinkan SQL Injection
Jadi, seperti yang diperagakan, rangkaian string adalah musuh utama untuk injeksi SQL
Prosedur yang tersimpan memang menambahkan enkapsulasi, penanganan transaksi, pengurangan izin, dll., Tetapi masih bisa disalahgunakan untuk injeksi SQL.
Anda dapat melihat Stack Overflow untuk informasi lebih lanjut tentang parametrisation
sumber
"Serangan injeksi SQL terjadi ketika masukan pengguna secara tidak benar dikodekan. Biasanya, masukan pengguna beberapa data pengguna mengirimkan dengan permintaan dia, nilai-nilai yaitu di
$_GET
,$_POST
,$_COOKIE
,$_REQUEST
, atau$_SERVER
array. Namun, input pengguna dapat juga datang dari berbagai lainnya sumber, seperti soket, situs web jarak jauh, file, dll. Oleh karena itu, Anda harus benar-benar memperlakukan semuanya kecuali konstanta (seperti'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 membuat pos ini lebih lengkap dan instruktif untuk semua orang.
Dari YouTube
Dari Wikipedia
Dari OWASP
Dari Manual PHP
Dari Microsoft dan Oracle
Stack Overflow
Pemindai injeksi SQL
sumber
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):
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):
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:
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:
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
sumber
quote_ident()
- tetapi secara umum cara termudah untuk menulis SQL dinamis tahan injeksi adalah dengan menggunakanformat()
dan menggunakan placeholder%I
untuk pengidentifikasi dan%L
untuk literal. Dengan begitu SQL jauh lebih mudah dibaca daripada versi yang setara menggunakan||
danquote_....()
fungsinya