Ushbu bo'limda PHP, Ruby va Java deserializatsiyasi misollarida ba'zi keng tarqalgan stsenariylarni ekspluatatsiya qilishni o'rgatamiz. Ko'p misollar PHP'ga asoslangan bo'lsa-da, aksariyat ekspluatatsiya usullari boshqa tillar uchun ham amal qiladi.
Auditda saytga uzatiladigan barcha ma'lumotni ko'rib chiqing va serializatsiya qilingan ma'lumotga o'xshagan narsani aniqlashga urining. Har xil tillar ishlatadigan formatni bilsangiz, serializatsiya qilingan ma'lumotni nisbatan oson aniqlash mumkin.
PHP asosan inson o'qiy oladigan satr formatidan foydalanadi — harflar ma'lumot turini, raqamlar esa har bir yozuvning uzunligini bildiradi. Masalan, quyidagi atributlarga ega User obyekti:
$user->name = "carlos";
$user->isLoggedIn = true;Serializatsiya qilinganda quyidagicha ko'rinishi mumkin:
O:4:"User":2:{s:4:"name":s:6:"carlos";s:10:"isLoggedIn":b:1;}Bu quyidagicha talqin qilinadi: O:4:"User" — 4 belgili "User" klass nomli obyekt; 2 — obyektda 2 atribut; s:4:"name" — birinchi atribut kaliti 4 belgili "name"; b:1 — ikkinchi atribut qiymati boolean true. PHP'ning tabiiy metodlari — serialize() va unserialize(). Manba kodga kirish bo'lsa, unserialize() ni qidiring.
Java kabi ba'zi tillar binar serializatsiya formatlaridan foydalanadi. Bu o'qish qiyinroq, lekin ayrim belgilarni tanib bilish mumkin — masalan serializatsiya qilingan Java obyektlari doim bir xil baytlardan boshlanadi (heksda ac ed, Base64'da rO0). java.io.Serializable interfeysini implement qilgan har qanday klass serializatsiya qilinishi mumkin. Manba kodda readObject() metodini qidiring.
Ba'zi deserializatsiya zaifliklarini ekspluatatsiya qilish serializatsiya qilingan obyektdagi atributni o'zgartirish kabi oson bo'lishi mumkin. Obyekt holati saqlangan bo'lgani uchun, siz serializatsiya qilingan ma'lumotni o'rganib, qiziq atribut qiymatlarini tahrirlashingiz mumkin. Ikki yondashuv bor: obyektni to'g'ridan-to'g'ri bayt oqimi ko'rinishida tahrirlash yoki tegishli tilda qisqa skript yozib, yangi obyektni o'zingiz yaratib serializatsiya qilish.
Ma'lumotni buzganda, hujumchi yaroqli serializatsiya qilingan obyektni saqlab qolsa, deserializatsiya jarayoni o'zgartirilgan atribut qiymatlari bilan server tomonida obyekt yaratadi. Masalan, foydalanuvchi sessiyasi haqida ma'lumotni cookie'da saqlaydigan sayt:
O:4:"User":2:{s:8:"username";s:6:"carlos";s:7:"isAdmin";b:0;}isAdmin atributi aniq qiziqish nuqtasi. Hujumchi uning boolean qiymatini 1 (true) ga o'zgartirib, obyektni qayta kodlab, cookie'ni almashtirishi mumkin. Agar sayt bu cookie orqali joriy foydalanuvchi admin ekanini tekshirsa, bu oson imtiyoz oshirishga olib keladi:
$user = unserialize($_COOKIE);
if ($user->isAdmin === true) {
// admin interfeysga ruxsat
}Atribut qiymatlarini o'zgartirishdan tashqari, kutilmagan ma'lumot turlarini ham berish mumkin. PHP logikasi, ayniqsa, uning bo'sh (loose) taqqoslash operatori (==) tufayli bunga zaif. Masalan 5 == "5" true qaytaradi. PHP 7.x va undan oldinda 0 == "Example string" ham true qaytaradi. Deserializatsiya ma'lumot turini saqlagan holda, agar hujumchi password atributini string o'rniga integer 0 qilsa va saqlangan parol raqamdan boshlanmasa, shart doim true qaytaradi — autentifikatsiya chetlab o'tiladi:
$login = unserialize($_COOKIE);
if ($login['password'] == $password) {
// muvaffaqiyatli login
}PHP 8 va undan keyingi versiyalarda 0 == "Example string" false qaytaradi (stringlar endi 0 ga aylantirilmaydi), shuning uchun bu ekspluatatsiya u versiyalarda ishlamaydi. Serializatsiya formatida ma'lumot turini o'zgartirganda tur yorliqlari va uzunlik ko'rsatkichlarini ham yangilashni unutmang.
Sayt funksiyasi deserializatsiya qilingan obyekt ma'lumoti ustida xavfli amallar bajarishi mumkin. Masalan "Foydalanuvchini o'chirish" funksiyasi $user->image_location atributidagi fayl yo'liga kirib profil rasmini o'chiradi. Agar $user serializatsiya qilingan obyektdan yaratilgan bo'lsa, hujumchi image_location ni ixtiyoriy fayl yo'liga o'rnatib, o'z hisobini o'chirganda o'sha faylni ham o'chiradi.
Magic metodlar — siz aniq chaqirmaydigan, balki ma'lum hodisa yuz berganda avtomatik chaqiriladigan maxsus metodlar to'plami (ko'pincha nomi ikki tag chiziq bilan o'ralgan). Masalan PHP'dagi __construct() obyekt yaratilganda chaqiriladi. Muhimi: ba'zi tillar deserializatsiya jarayonida avtomatik chaqiriladigan magic metodlarga ega. PHP'ning unserialize() metodi obyektning __wakeup() magic metodini qidirib chaqiradi. Java'da ObjectInputStream.readObject() shunga o'xshash ishlaydi:
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
// implementatsiya
}Magic metodlar o'z-o'zidan zaiflik emas, lekin ular hujumchi boshqaradigan ma'lumot (masalan deserializatsiya qilingan obyektdan) ustida ishlaganda xavfli bo'ladi. Bu ilg'orroq ekspluatlar yaratishning boshlang'ich nuqtasi.
Obyektga mavjud metodlar uning klassi bilan belgilanadi. Shuning uchun hujumchi qaysi klass obyekti serializatsiya qilingan ma'lumot sifatida uzatilishini boshqarsa, deserializatsiyadan keyin (va hatto uning davomida) qanday kod bajarilishiga ta'sir qila oladi. Deserializatsiya metodlari odatda nimani deserializatsiya qilayotganini tekshirmaydi — shuning uchun saytga mavjud har qanday serializable klass obyektini uzatishingiz mumkin. Manba kodga kirish bo'lsa, deserializatsiya magic metodlarini o'z ichiga olgan klasslarni qidirib, ular boshqariladigan ma'lumot ustida xavfli amal bajarar-bajarmasligini tekshiring.
"Gadget" — ilovada mavjud bo'lgan va hujumchiga ma'lum maqsadga erishishga yordam beradigan kod bo'lakchasi. Alohida gadget o'zi to'g'ridan-to'g'ri zararli ish qilmasligi mumkin, lekin hujumchining maqsadi shunchaki kiritmani boshqa gadget'ga uzatadigan metodni chaqirish bo'lishi mumkin. Ko'p gadget'ni shu tarzda zanjirlab, hujumchi kiritmani maksimal zarar yetkazadigan "sink gadget"ga uzatishi mumkin. Muhimi: gadget chain — hujumchi tuzgan metodlar payloadi EMAS. Barcha kod allaqachon saytda mavjud; hujumchi faqat gadget chain'ga uzatiladigan ma'lumotni boshqaradi (odatda deserializatsiyada chaqiriladigan magic metod, "kick-off gadget" orqali).
Gadget chain'ni qo'lda aniqlash mashaqqatli va manba kodsiz deyarli imkonsiz. Baxtga qarshi, boshqa saytlarda muvaffaqiyatli ekspluatatsiya qilingan oldindan topilgan zanjirlarni beradigan vositalar bor. Java uchun bunday vosita — "ysoserial": siz nishon ilova ishlatayotgan kutubxona uchun zanjirni tanlab, bajarmoqchi bo'lgan buyruqni berasiz, u esa mos serializatsiya qilingan obyekt yaratadi.
Java 16 va undan yuqorida ysoserial'ni ishga tushirish uchun bir qator command-line argumentlar (--add-opens=...) berish kerak.
ysoserial'dagi barcha zanjirlar ixtiyoriy kod bajarmaydi — ba'zilari aniqlash uchun foydali. URLDNS zanjiri berilgan URL uchun DNS so'rovni keltiradi (har qanday Java versiyasida ishlaydi — aniqlash uchun eng universal). JRMPClient esa serverni berilgan IP'ga TCP ulanishga majbur qiladi. PHP saytlar uchun "PHP Generic Gadget Chains" (PHPGGC) bor.
Nishon ilova ishlatadigan freymvork uchun maxsus vosita bo'lmasligi mumkin. Bunday holatda onlayn hujjatlashtirilgan ekspluatlarni qidirib, ularni qo'lda moslash har doim arziydi. Kodni o'zgartirish til va freymvork haqida asosiy bilim talab qilishi mumkin.
Tayyor gadget chain va hujjatlashtirilgan ekspluatlar ishlamasa, o'z ekspluatingizni yaratishga to'g'ri keladi. Buning uchun deyarli doim manba kodga kirish kerak. Avval deserializatsiyada chaqiriladigan magic metodli klassni toping. Bu magic metod o'zi xavfli bo'lmasa, u "kick-off gadget" bo'lib xizmat qiladi — u chaqiradigan metodlarni o'rganib, boshqaradigan ma'lumot ustida xavfli sink gadget'ga yetguncha zanjirni kuzating. So'ng payloadingizni o'z ichiga olgan serializatsiya qilingan obyekt yarating.
PHP'da unserialize() aniq ishlatilmasa ham deserializatsiyani ekspluatatsiya qilish ba'zan mumkin. PHP phar:// wrapper'ini beradi — u PHP Archive (.phar) fayllariga kirish uchun stream interfeysi. PHAR manifest fayllari serializatsiya qilingan metama'lumotni o'z ichiga oladi va agar phar:// stream ustida istalgan fayl tizimi amalini (masalan file_exists()) bajarsangiz, bu metama'lumot yashirincha deserializatsiya qilinadi. Rasm yuklash funksiyasidan foydalanib, PHAR'ni oddiy JPG kabi ko'rsatgan polyglot fayl yaratsangiz, tekshiruvlarni chetlab o'tib, __wakeup() va __destruct() magic metodlarini ishga tushirish mumkin.
Gadget chain'siz ham insecure deserializationni ekspluatatsiya qilish mumkin. Ko'pincha ommaviy hujjatlashtirilgan memory corruption zaifliklari deserializatsiya orqali ekspluatatsiya qilinishi mumkin — bular odatda RCE'ga olib keladi. unserialize() kabi metodlar bunday hujumlarga kamdan-kam mustahkamlangan va katta hujum yuzasi ochadi.