Apakah ada cara untuk keluar dari string dan menyuntikkan SQL tanpa menggunakan kutipan tunggal di oracle?

12

Saya sedang menguji aplikasi berbasis oracle dan saya telah menemukan kode berikut:

Kueri = "PILIH nama DARI karyawan DI MANA id = '" + PKID + "';"

yaitu string kueri berisi tanda kutip di sekitar nilai PKID yang diperoleh langsung dari URL.

Jelas, ini adalah injeksi SQL klasik yang menunggu untuk terjadi ... kecuali aplikasi di belakang CA SiteMinder yang memblokir URL apa pun dengan kutipan tunggal (dalam bentuk apa pun) agar tidak diteruskan ke aplikasi.

Apakah ada cara untuk keluar dari string dan menyuntikkan SQL tanpa menggunakan kutipan tunggal?

Sunting: Maaf, saya seharusnya lebih jelas - Saya mengerti bagaimana seharusnya ditulis, tetapi saya harus meyakinkan orang bahwa ini adalah masalah yang dapat dieksploitasi. Saat ini karena berada di belakang siteminder yang memblokir tanda kutip tunggal sehingga akan menjadi perbaikan prioritas rendah.

jdsnape
sumber
1
sudahkah Anda mencoba menggunakan variabel bind?
JHFB
Apa yang dikatakan @JHFB. Binding variabel adalah praktik standar.
Philᵀᴹ

Jawaban:

9

Ya, adalah mungkin untuk melakukan serangan injeksi SQL tanpa memberikan tanda kutip pada parameter.

Cara untuk melakukan ini adalah dengan eksploit untuk dilakukan dengan bagaimana angka dan / atau tanggal diproses. Anda dapat menentukan di tingkat sesi apa format tanggal atau angka. Dengan memanipulasi ini, Anda kemudian dapat menyuntikkan dengan karakter apa pun.

Secara default di Inggris dan AS, koma digunakan untuk menunjukkan pemisah ribuan dalam angka, dan berhenti penuh untuk titik desimal. Anda dapat mengubah default ini dengan menjalankan:

alter session set nls_numeric_characters = 'PZ';

Ini berarti bahwa "P" sekarang adalah titik desimal dan "Z" adalah pemisah ribuan. Begitu:

0P01

Apakah angka 0,01. Namun, jika Anda membuat fungsi P01, referensi objek akan diambil sebelum konversi angka. Ini memungkinkan Anda untuk menjalankan fungsi-fungsi pada basis data yang memberi Anda peningkatan kekuatan, sebagai berikut:

Buat fungsi dasar "dapatkan oleh id":

create procedure get_obj ( i in number ) as
begin
  execute immediate 'select object_name from all_objects where object_id = ' || i;
end;
/

Juga buat fungsi P01 yang melakukan sesuatu yang tidak diinginkan (dalam hal ini hanya membuat tabel, tetapi Anda mendapatkan ide):

create function p01 return number as
  pragma autonomous_transaction;
begin
  execute immediate 'create table t (x integer)';
  return 1;
end;
/

Dan kami siap untuk:

alter session set nls_numeric_characters = 'PZ';

SELECT * FROM t;

SQL Error: ORA-00942: table or view does not exist

exec get_obj(p01);

anonymous block completed

SELECT * FROM t;

no rows selected

Tidak ada kutipan di mana pun, tetapi kami masih berhasil menjalankan fungsi "tersembunyi" P01 dan membuat tabel t!

Walaupun ini mungkin sulit dilakukan dalam praktek (dan mungkin memerlukan pengetahuan / bantuan internal), ini menunjukkan bahwa Anda dapat menyuntikkan SQL tanpa harus memiliki tanda kutip. Mengubah nls_date_formatdapat memungkinkan hal serupa dilakukan.

Temuan asli untuk angka adalah oleh David Litchfield dan Anda dapat membaca makalahnya di sini . Anda dapat menemukan diskusi Tom Kyte tentang bagaimana kencan dapat dieksploitasi di sini .

Chris Saxon
sumber
4

Anda mungkin bisa membebani tipe data yang Anda gunakan, menyebabkan pernyataan itu gagal. Lalu apa yang terjadi setelahnya berpotensi dijalankan.

Mungkin mengirimkannya sebagai array byte Unicode akan melakukan trik dan membuat Anda keluar dari pernyataan itu ke yang lain.

Jika ada lubang terbuka, itu akan disalahgunakan. Dan memblokir semua string dengan satu kutipan bukanlah ide yang baik karena orang dengan nama belakang "O'Brian" tidak dapat menjadi pelanggan Anda (antara lain).

mrdenny
sumber
Saya kira maksud Anda "lubang" dan bukan "keseluruhan".
ypercubeᵀᴹ
1

Coba gunakan variabel bind. Anda dapat mendeklarasikannya sebagai angka dan yang seharusnya mencegah injeksi SQL yang merusak.

TAMBAHAN: variabel mengikat juga meningkatkan kinerja dan skalabilitas karena rencana kueri dikompilasi dan disimpan untuk digunakan kembali. Hanya sesuatu yang lain untuk ditambahkan ke argumen Anda. :)

JHFB
sumber
1
Dia tidak bertanya tentang cara untuk mencegah suntikan tetapi tentang cara untuk menyalahgunakannya .
Jeff
1
@jeff OP juga meminta alasan untuk tidak menggunakan kode semacam ini. Tidak menggunakan variabel mengikat menghancurkan kinerja jadi ini adalah alasan yang bagus untuk selalu menggunakannya.
Vincent Malgrat
@Vincent Malgrat: "Tidak menggunakan variabel bind menghancurkan kinerja" salah. Memang benar bahwa kompilasi ulang pernyataan dapat dihindari dengan menggunakan variabel bind. Juga kumpulan bersama akan dibanjiri oleh banyak pernyataan serupa jika Anda tidak menggunakan variabel bind. Namun demikian, pengoptimal memiliki informasi yang lebih sedikit untuk membangun rencana jika seseorang menggunakan variabel pengikat alih-alih nilai literal. Ada situasi di mana harus dipilih rencana yang berbeda tergantung pada nilai-nilai dari variabel mengikat (atau nilai literal).
miracle173
@ miracle173 Tentu saja akan ada pengecualian, tetapi tidak untuk pencarian kunci primer seperti yang diberikan oleh OP, tidak pernah =)
Vincent Malgrat