Agar ilovada SQL ineksiya zaifligi bo‘lsa va query natijalari ilovaning response’ida ko‘rinsa, UNION kalit so‘zi yordamida bazadagi boshqa jadvallardan ham ma’lumot olish mumkin. Bu odatda UNION SQL ineksiya hujumi deb ataladi.
UNION kalit so‘zi bir yoki bir nechta qo‘shimcha SELECT query’ni bajarish va ularning natijalarini asl query natijasiga qo‘shish imkonini beradi. Masalan:
SELECT a, b FROM table1 UNION SELECT c, d FROM table2Bu SQL query ikkita ustundan iborat bitta umumiy natija qaytaradi. Unda table1 dagi a va b ustunlari hamda table2 dagi c va d ustunlari qiymatlari birga bo‘ladi.
UNION query ishlashi uchun ikkita muhim shart bajarilishi kerak:
SQL ineksiya UNION hujumini ishlatishda, yuborayotgan hujumingiz shu ikki shartga mos kelishiga ishonch hosil qilish kerak. Buning uchun odatda quyidagilar aniqlanadi:
UNION SQL ineksiya hujumini qilayotganda, original query nechta ustun qaytarayotganini aniqlashning ikkita samarali usuli bor.
Birinchi usul — ORDER BY larni ketma-ket yuborib, ustun raqamini asta-sekin oshirib borish. Xato chiqqan joydan nechta ustun borligini bilib olish mumkin. Masalan, agar ineksiya qilinayotgan joy original queryning WHERE qismidagi string ichida ichida bo‘lsa, quyidagilar yuboriladi:
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
...va hokazo.Bu payloadlar original query ni turli ustunlar bo‘yicha saralashga majbur qiladi. ORDER BY ichida ustunni nomi bilan emas, raqami bilan ham ko‘rsatish mumkin. Shu sabab ustunlarning nomini bilish shart emas. Agar ko‘rsatilgan ustun raqami aslida mavjud ustunlar sonidan oshib ketsa, database xato qaytaradi. Masalan:
The ORDER BY position number 3 is out of range of the number of items in the select list.Ilova bu database xatosini to‘g‘ridan-to‘g‘ri HTTP response da ko‘rsatishi mumkin. Ba’zan esa oddiy umumiy xato sahifasini qaytaradi. Yana ba’zi holatlarda esa umuman natija chiqarmasligi mumkin. Muhimi, response da qandaydir farq sezilsa, shundan query nechta ustun qaytarayotganini bilib olish mumkin.
Ikkinchi usul — bir nechta NULL lar bilan UNION SELECT payloadlarini yuborish:
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
... va hokazoAgar NULL lar soni original query qaytarayotgan ustunlar soniga mos kelmasa, database xato qaytaradi. Masalan:
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.Biz NULL ni ishlatamiz, chunki siz qo‘shgan SELECT query bilan original query dagi ustunlarning data type lari bir-biriga mos kelishi kerak. NULL esa ko‘plab data type larga mos tushadi. Shu sabab ustunlar soni to‘g‘ri topilgan holatda payload ishlash ehtimoli yuqori bo‘ladi.
ORDER BY usulidagi kabi, ilova database xatosini HTTP response da ochiq ko‘rsatishi ham mumkin, umumiy xato qaytarishi ham mumkin, yoki umuman natija chiqarmasligi ham mumkin. Agar NULL lar soni ustunlar soniga mos kelsa, database natijaga yana bitta qator qo‘shadi va o‘sha qatordagi barcha ustunlar NULL bo‘ladi. Bu holat HTTP response da qanday ko‘rinishi ilovaning kodiga bog‘liq. Omadingiz kelsa response ichida qo‘shimcha biror nima ko‘rishingiz mumkin, masalan HTML jadvalda yana bitta qator chiqadi. Ba’zan esa NULL lar boshqa xatoga sabab bo‘lishi mumkin, masalan NullPointerException. Eng yomon holatda esa response noto‘g‘ri NULL sonida qaytgan response bilan bir xil ko‘rinadi. Bunday vaziyatda bu usul foyda bermaydi.
Oracle’da har bir SELECT query FROM kalit so‘zini ishlatishi va to‘g‘ri jadval nomini ko‘rsatishi kerak. Oracle’da dual degan ichki jadval bor va bunday holatda undan foydalanish mumkin. Shuning uchun Oracle’da yuboriladigan ineksiya querylari odatda quyidagiga o‘xshaydi:
' UNION SELECT NULL FROM DUAL--Berilgan payloadlarda ineksiya kiritilgan joydan keyin original query ning qolgan qismini comment qilish uchun -- ishlatilgan. MySQL’da esa -- dan keyin albatta bo‘sh joy kelishi kerak. Yoki comment ko‘rsatish uchun # belgisidan ham foydalanish mumkin.
Ma’lumotlar bazalariga xos sintaksis haqida batafsil ma’lumot olish uchun SQL ineksiya cheat sheetni ko'ring.
UNION SQL ineksiya hujumi sizga o‘zingiz qo‘shgan query natijalarini ko‘rish imkonini beradi. Siz olmoqchi bo‘lgan muhim ma’lumotlar odatda string ko‘rinishida bo‘ladi. Shu sabab original query natijasidagi, data type'i string bo‘lgan yoki string bilan mos keladigan bir yoki bir nechta ustunni topish kerak bo‘ladi.
Kerakli ustunlar sonini aniqlab bo‘lgach, har bir ustunni alohida sinab ko‘rib, u string ma’lumotni qabul qila oladimi, tekshirish mumkin. Buning uchun UNION SELECT payloadlarini ketma-ket yuborib, string qiymatni har safar boshqa ustunga qo‘yib ko‘rasiz. Masalan, agar query 4 ta ustun qaytarsa, quyidagilar yuboriladi:
' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--Agar ustunning data type'i string ma’lumot bilan mos kelmasa, qo‘shilgan query database xatosiga sabab bo‘ladi. Masalan:
Conversion failed when converting the varchar value 'a' to data type int.Agar xato chiqmasa va ilovaning response ida siz yuborgan string qiymat bilan birga qo‘shimcha ma’lumot ham ko‘rinsa, demak o‘sha ustun string ma’lumotni olish uchun mos keladi.
Original query nechta ustun qaytarishini aniqlab bo‘lgach va qaysi ustunlar string ma’lumotni qabul qilishini topgach, endi kerakli ma’lumotlarni olish mumkin bo‘ladi.
Faraz qilaylik:
WHERE qismidagi string ichidausers degan jadval bor va unda username hamda password ustunlari mavjudBunday holatda users jadvalidagi ma’lumotlarni olish uchun quyidagi input yuborish mumkin:
' UNION SELECT username, password FROM users--Bu hujumni amalga oshirish uchun users degan jadval borligini va unda username hamda password degan 2 ta ustun borligini bilishingiz kerak bo‘ladi. Agar bu ma’lumotni bilmasangiz, jadval va ustun nomlarini taxmin qilib topishga to‘g‘ri keladi. Hozirgi zamonaviy ma’lumotlar bazalarining barchasida baza tuzilishini ko‘rish va unda qaysi jadvallar hamda ustunlar borligini aniqlash usullari mavjud.
Ba’zi holatlarda oldingi misoldagi query faqat bitta ustun qaytarishi mumkin.
Bunday vaziyatda bir nechta qiymatni shu bitta ustun ichida, ularni bir-biriga qo‘shib olish mumkin. Birlashtirilgan qiymatlarni bir-biridan ajratish uchun orasiga ajratuvchi belgi qo‘shiladi. Masalan, Oracle’da quyidagi input yuborilishi mumkin:
' UNION SELECT username || '~' || password FROM users--Bu yerda || Oracle’dagi matnlarni bir-biriga qo‘shish operatori. Qo‘shilgan query username va password qiymatlarini bir-biriga qo‘shadi va ularning orasiga ~ belgisini qo‘yadi.
Query natijasida barcha username va password lar quyidagiga o‘xshash ko‘rinishda chiqadi:
...
administrator~s3cure
wiener~peter
carlos~montoya
...Turli ma’lumotlar bazalarida matnlarni bir-biriga qo‘shish sintaksisi har xil bo‘ladi. Batafsil ma’lumot uchun SQL ineksiya cheat sheet ga qarang.