SQL Injection

"SQL Injection" adalah subset dari sebuah kerentanan diverifikasi / pengguna unsanitized input ("buffer overflows" adalah subset yang berbeda), dan gagasan itu adalah untuk meyakinkan aplikasi untuk menjalankan kode SQL yang tidak dimaksudkan. Jika aplikasi menciptakan string SQL naif dengan cepat dan kemudian berjalan mereka, itu mudah untuk membuat beberapa kejutan nyata.

Kami akan mencatat bahwa ini adalah jalan agak berliku-liku dengan lebih dari satu giliran salah, dan lain-lain dengan pengalaman lebih pasti akan berbeda - dan lebih baik - pendekatan. Tapi kenyataan bahwa kami tidak berhasil menunjukkan bahwa kita tidak sepenuhnya salah arah.

Ada tulisan lain di injeksi SQL, termasuk beberapa yang lebih rinci, tapi yang satu ini menunjukkan alasan penemuan sebanyak proses eksploitasi.
Intranet Target

Ini muncul menjadi aplikasi sepenuhnya kustom, dan kami tidak memiliki pengetahuan sebelumnya tentang aplikasi atau akses ke kode sumber: ini adalah "buta" menyerang. Sedikit menyembul menunjukkan bahwa server ini berlari Microsoft IIS 6 bersama dengan ASP.NET, dan ini dapat disimpulkan bahwa database adalah Microsoft SQL server: kami percaya bahwa teknik ini dapat diterapkan pada hampir semua aplikasi web yang didukung oleh SQL server.

Halaman login memiliki bentuk username-dan-sandi tradisional, tapi juga link email-saya-saya-sandi, yang terakhir terbukti jatuhnya keseluruhan sistem.

Ketika memasukkan alamat email, sistem mungkin tampak dalam database pengguna untuk itu alamat email, dan mengirimkan sesuatu ke alamat tersebut. Sejak alamat email saya tidak ditemukan, itu tidak akan mengirim apa-apa.

Jadi, tes pertama dalam bentuk apapun SQL-ish adalah memasukkan tanda kutip tunggal sebagai bagian dari data: dimaksudkan untuk melihat apakah mereka membangun sebuah string SQL harfiah tanpa pembersih. Ketika mengirimkan formulir dengan kutipan dalam alamat email, kita mendapatkan error 500 (kegagalan server), dan ini menunjukkan bahwa "rusak" input sebenarnya sedang dipecah harfiah. Bingo.

Kami berspekulasi bahwa kode SQL yang mendasari terlihat seperti ini:

SELECT fieldlist
FROM table
WHERE field = '$EMAIL';

Di sini, $ EMAIL adalah alamat kirimkan pada formulir oleh pengguna, dan permintaan yang lebih besar memberikan tanda kutip yang ditetapkan ini sebagai string literal. Kita tidak tahu nama-nama tertentu dari ladang atau meja yang terlibat, tetapi kita tahu sifat mereka, dan kami akan membuat beberapa tebakan yang baik kemudian.

Ketika kita memasuki steve@unixwiz.net '- tanda kutipan catatan penutup - ini dibangun hasil SQL:
SELECT fieldlist
FROM table
WHERE field = 'steve@unixwiz.net'';

saat ini dijalankan, parser SQL menemukan tanda kutipan ekstra dan dibatalkan dengan kesalahan sintaks. Bagaimana ini memanifestasikan dirinya untuk pengguna tergantung pada prosedur internal aplikasi error-recovery, tapi biasanya berbeda dari "alamat email ini" tidak diketahui. Respon kesalahan adalah giveaway mati bahwa masukan pengguna tidak sedang dibersihkan dengan benar dan bahwa aplikasi sudah masak untuk eksploitasi.

Karena data kita mengisi tampaknya pada klausa WHERE, mari kita mengubah sifat klausul bahwa dengan cara SQL hukum dan lihat apa yang terjadi. Dengan memasukkan sesuatu 'OR' x '=' x, yang dihasilkan SQL adalah:
SELECT fieldlist
FROM table
WHERE field = 'anything' OR 'x'='x';

Karena aplikasi tersebut tidak benar-benar berpikir tentang query - hanya membangun sebuah string - penggunaan tanda kutip kami telah berubah klausa WHERE satu komponen ke komponen dua-satu, dan 'x' = 'x' klausa dijamin benar tidak peduli apa klausa pertama (ada pendekatan yang lebih baik untuk bagian "selalu benar" bahwa kita akan menyentuh kemudian).

Tapi tidak seperti permintaan "nyata", yang harus kembali hanya suatu item tunggal setiap kali, versi ini pada dasarnya akan kembali setiap item dalam database anggota. Satu-satunya cara untuk mengetahui aplikasi apa yang akan dilakukan dalam keadaan ini adalah dengan mencobanya. Melakukan hal itu, kami disambut dengan:

informasi login Anda telah dikirim ke random.person @ example.com.

rasa terbaik kami adalah bahwa rekaman pertama dikembalikan oleh query, efektif entri diambil secara acak. Orang ini benar-benar mendapatkan link ini lupa-password melalui email, yang mungkin akan mengejutkan dia dan mungkin meningkatkan peringatan bendera di suatu tempat.

Kita sekarang tahu bahwa kami dapat memanipulasi query ke tujuan kita sendiri, meskipun kita masih belum tahu banyak tentang bagian-bagian itu kita tidak dapat melihat. Tapi kami telah mengamati tiga berbeda tanggapan atas berbagai masukan kami:

* "Informasi login Anda telah dikirim ke email"
* "Kami tidak mengenali alamat email Anda"
* Server error

Dua pertama tanggapan untuk SQL well-formed, sedangkan yang kedua adalah untuk SQL buruk: pembedaan ini akan sangat berguna ketika mencoba menebak struktur query.
Langkah pertama adalah untuk menebak beberapa nama field: kami cukup yakin bahwa permintaan termasuk "alamat email" dan "password", dan mungkin ada hal-hal seperti "alamat Mail US" atau "userid" atau "nomor telepon". Kami akan mahal senang melakukan SHOW TABLE, tapi di samping tidak mengetahui nama tabel, tidak ada kendaraan jelas untuk mendapatkan output dari perintah ini dialihkan kepada kami.

Jadi kami akan melakukannya di langkah. Dalam setiap kasus, kami akan menunjukkan permintaan keseluruhan seperti yang kita tahu, dengan kita sendiri ditampilkan potongan khusus. Kita tahu bahwa akhir ekor query adalah perbandingan dengan alamat email, jadi mari kita menebak email sebagai nama lapangan:

SELECT fieldlist
DARI meja
WHERE field = 'x' email DAN IS NULL; - ';

Tujuannya adalah untuk menggunakan nama field yang diusulkan (email) dalam permintaan dibangun dan mencari tahu apakah SQL sah atau tidak. Kami tidak peduli tentang pencocokan alamat email (itulah sebabnya kami menggunakan dummy 'x'), dan - menandai dimulainya suatu komentar SQL. Ini adalah cara yang efektif untuk "mengkonsumsi" kutipan akhir yang disediakan oleh aplikasi dan tidak khawatir tentang pencocokan mereka.

Jika kita mendapatkan kesalahan pada server, itu berarti SQL kita cacat dan kesalahan sintaks terlempar: kemungkinan besar karena nama lapangan yang buruk. Jika kita mendapatkan jenis respon yang valid, kami menduga namanya dengan benar. Ini adalah kasus apakah kita mendapatkan yang tidak dikenal "email" atau "password dikirim" respons.

Namun, perlu diketahui bahwa kita menggunakan kata sambung DAN bukan ATAU: hal ini disengaja. Pada tahap pemetaan skema SQL, kita tidak benar-benar prihatin dengan menebak semua alamat email tertentu, dan kami tidak ingin pengguna dibanjiri acak "di sini adalah password" email dari aplikasi - ini pasti akan meningkatkan kecurigaan untuk tidak ada tujuan yang baik. Dengan menggunakan kata sambung DAN dengan alamat email yang tidak pernah berlaku, kami yakin bahwa permintaan akan selalu kembali nol baris dan tidak pernah menghasilkan email pengingat sandi.

Mengirimkan potongan di atas memang memberi kami alamat "email tidak dikenal" respon, jadi sekarang kita tahu bahwa alamat email yang disimpan dalam bidang email. Jika ini tidak berhasil, kami telah mencoba EMAIL_ADDRESS atau surat atau sejenisnya. Proses ini akan melibatkan cukup banyak menebak.

Selanjutnya kita akan menebak beberapa nama jelas lainnya: password, user ID, nama, dan sejenisnya. Ini semua dilakukan satu per satu, dan apa saja selain "kegagalan server" berarti kita menebak nama dengan benar.
SELECT fieldlist
DARI meja
WHERE email = 'x' userid DAN IS NULL; - ';

Sebagai hasil dari proses ini, kami menemukan beberapa nama lapangan yang valid:


Email *
* Passwd
* Login_id
* FULL_NAME

Tentu saja ada lebih (dan sumber baik petunjuk adalah nama kolom pada formulir), tapi sedikit menggali tidak menemukan apapun. Tapi kita masih tidak tahu nama tabel yang bidang ini ditemukan dalam - cara untuk mengetahui?
Mencari tabel nama

Aplikasi built-in permintaan sudah memiliki nama tabel dibangun ke dalamnya, tapi kita tidak tahu apa nama itu adalah: ada beberapa pendekatan untuk menemukan bahwa (dan lainnya) nama tabel. Yang kita ambil adalah mengandalkan sebuah subselect.

Sebuah query mandiri

SELECT COUNT (*) tabname DARI

Mengembalikan jumlah record dalam tabel itu, dan tentu saja gagal jika nama tabel tidak diketahui. Kami bisa membangun ini ke dalam string kita untuk probe untuk nama tabel:

SELECT email, passwd, login_id, FULL_NAME
DARI meja
WHERE email = 'x' DAN 1 = (SELECT COUNT (*) tabname DARI); - ';

Kami tidak peduli berapa banyak catatan yang ada, tentu saja, hanya apakah nama tabel sah atau tidak. Dengan iterasi selama beberapa tebakan, akhirnya kami memutuskan bahwa anggota adalah tabel yang valid dalam database. Tapi apakah tabel yang digunakan dalam query ini? Untuk itu kita perlu tes lain masih menggunakan notasi table.field: hanya bekerja untuk tabel yang sebetulnya merupakan bagian dari query ini, tidak hanya yang meja ada.

SELECT email, passwd, login_id, FULL_NAME
DARI anggota
WHERE email = 'x' members.email DAN IS NULL; - ';

Saat ini kembali "tidak diketahui Email", itu menegaskan bahwa SQL kami terbentuk dengan baik dan bahwa kita telah benar menebak nama tabel. Hal ini akan menjadi penting kemudian, tapi kami bukan mengambil pendekatan yang berbeda untuk sementara.
Mencari beberapa pengguna

Pada saat ini kami memiliki ide parsial dari struktur tabel anggota, tetapi kita hanya tahu satu nama pengguna: anggota acak yang mendapat awal kami "Ini adalah sandi Anda" email. Ingat bahwa kami tidak pernah menerima pesan itu sendiri, hanya alamat itu dikirim ke. Kami ingin mendapatkan beberapa nama lagi untuk bekerja dengan, terutama mereka yang cenderung memiliki akses ke data lebih banyak.

Tempat pertama untuk memulai, tentu saja, adalah website perusahaan untuk menemukan siapa yang: "Tentang kami" atau "Kontak" halaman yang sering daftar tempat itu berjalan. Banyak dari ini berisi alamat email, tapi bahkan mereka yang tidak daftar mereka dapat memberikan kita beberapa petunjuk yang memungkinkan kita untuk menemukan mereka dengan alat kami.

Idenya adalah untuk mengajukan permintaan yang menggunakan klausa LIKE, memungkinkan kita untuk melakukan pertandingan parsial nama atau alamat email di database, setiap kali memicu "Kami mengirim sandi Anda" pesan dan email. Peringatan: meskipun ini mengungkapkan alamat email setiap kali kita menjalankannya, itu juga sebenarnya yang mengirimkan email, yang dapat menimbulkan kecurigaan. Hal ini menunjukkan bahwa kita mudah.

Kita bisa melakukan query pada nama email atau nama lengkap (atau mungkin informasi lainnya), setiap kali meletakkan dalam wildcard% yang mendukung SEPERTI:
SELECT email, passwd, login_id, FULL_NAME
DARI anggota
WHERE email = 'x' FULL_NAME SEPERTI ATAU '%% Bob';

Perlu diketahui bahwa meskipun mungkin ada lebih dari satu "Bob", kita hanya bisa melihat salah satu dari mereka: ayat ini menunjukkan pemurnian SEPERTI kita sempit.

Pada akhirnya, kita hanya mungkin perlu satu alamat email yang valid untuk meningkatkan cara kami masuk