Asosiy kontentga o‘tish

Maqolalar 9 daqiqa o‘qish 1 soat 30 daqiqa amaliyot 40 ko‘rish

OS command injection: kiritilgan matn serverda buyruq bo'lganda

Server foydalanuvchi kiritgan qiymatni operatsion tizim buyrug'iga qo'shsa — o'sha qiymat buyruqni o'zgartira oladi va serverda o'z buyruqlaringizni bajartira oladi. To'rtta labda buni ishga tushiramiz (natija ko'rinadigan va ko'rinmaydigan holatlarda), keyin nega tashqi buyruqning o'zidan qochish kerakligini ko'ramiz.

security backend linux

Mundarija

Bu kursning eng xavfli zaifligi. Oldingi darslarda hujum ma'lumotni o'qidi yoki o'zgartirdi. Bu yerda esa hujumchi serverda o'z buyrug'ini bajaradi — bu ma'lumot o'g'irlashdan bir pog'ona yuqori: butun serverni egallash.

Sabab o'sha tanish naqsh: server foydalanuvchi kiritgan qiymatni tizim buyrug'iga qo'shadi. Qiymat ichida maxsus belgi (;, |, &) bo'lsa, u birinchi buyruqni tugatib, o'zinikini boshlaydi. Ma'lumot yana buyruq maydoniga tozalanmasdan tushdi — bu safar oqibati eng og'ir.

Bu darsdan keyin siz command injection'ni topa olasiz, uni natija ko'rinmaydigan (blind) holatlarda ham aniqlay olasiz va nega tashqi buyruq chaqirishning o'zidan qochish kerakligini tushunasiz.

Bu dars kimga

1-dars (Burp) tugagan bo'lsin. Shell buyruqlari — whoami, ping, ; va | nima ekani — bilan tanish bo'lsangiz osonroq.

Buzilgan taxmin#

Command injection bitta qulaylikdan tug'iladi:

"Bu vazifani tizim buyrug'i tez bajaradi — kiritilgan qiymatni buyruqqa qo'shaman."

Dasturchi zaxira sonini tekshirish yoki fikr-mulohaza yuborish uchun tizim buyrug'ini chaqiradi va foydalanuvchi qiymatini uning ichiga qo'yadi. Uning tasavvurida qiymat — bitta so'z. Lekin shell tili ; va | ni "buyruqlar chegarasi" deb o'qiydi. Qiymat ichida shu belgilar bo'lsa, foydalanuvchi bitta emas, ikkita buyruq yuborgan bo'ladi.

Kiritilgan qiymat — matn emas, shellga beriladigan buyruq: argument bo'lib qoladimi yoki yangi buyruqqa aylanadimi, uni yozish usuli hal qiladi.

Atamalar#

Atama Ma'nosi
OS command injection kiritilgan matn tizim buyrug'ini o'zgartirishi
shell buyruqlarni bajaruvchi dastur (bash, sh)
whoami joriy foydalanuvchi nomini chiqaruvchi buyruq
; && va quvur belgisi buyruqlarni bog'lovchi/ajratuvchi shell metabelgilari
blind injection buyruq bajariladi, lekin natija javobda ko'rinmaydi
time delay natija ko'rinmasa, sleep bilan vaqt orqali tasdiqlash
output redirection natijani web'dan o'qiladigan faylga yozish (> file)
out-of-band (OAST) natijani tashqi kanal (DNS/HTTP) orqali chiqarish
Burp Collaborator tashqi kanalni ushlab beruvchi PortSwigger vositasi

Nazariya: qiymat buyruqqa aylanadi#

Zaif qolip — buyruqni satr qo'shib yasash:

Python
# Zaif: storeID buyruq satriga qo'shiladi, shell=True xavfni ochadi
import subprocess


def stock(request):
    product = request.POST["productID"]
    store = request.POST["storeID"]
    output = subprocess.check_output(
        f"stockreport.sh {product} {store}",
        shell=True,  # <-- xavf shu yerda
    )
    return HttpResponse(output)

Skript ikki argument oladi va storeID — oxirgisi (PortSwigger labida ham shunday). storeID ga 1; whoami yozilsa, shell buni ikki buyruq deb o'qiydi:

Fayl tuzilishi
stockreport.sh 14 1  ← birinchi buyruq (product va store)
whoami               ← ikkinchi buyruq (; dan keyin, toza)

storeID oxirgi bo'lgani muhim: agar inject qilinadigan joydan keyin yana argument qolsa, u whoami ga yopishib, whoami: extra operand xatosini beradi (buni ; ham, | whoami ham hal qilmaydi — trailing argument baribir qoladi). Ikki ishonchli yo'l bor: inject qilinadigan joy buyruqning oxirida bo'lsin, yoki qolgan qismini # bilan izohga aylantiring — 1; whoami #.

whoami natijasi javobga qaytadi — hujumchi serverda kim ekanini biladi, va shu yo'l bilan istalgan buyruqni bajaradi. shell=True — bu yerda eng xavfli qism: u qiymatni shellga beradi, shell esa ; ni tushunadi.

Kuzating

command injection izlaganda ;, | whoami, & whoami, `whoami`, $(whoami) variantlarini sinang. Javobda begona natija (foydalanuvchi nomi, sana) chiqsa — buyruq bajarildi.

Amaliyot#

1-labNatija ko'rinadi#

Lab: OS command injection, simple case · APPRENTICE

Vazifa: whoami bajarib, joriy foydalanuvchi nomini bilish.

Nimani ko'rasiz: "Check stock" tugmasi — server zaxira sonini tizim buyrug'i bilan tekshiradi va natijani ko'rsatadi.

Savol: storeID buyruqqa qo'shiladi. Unga ; whoami qo'shsangiz, shell nechta buyruq ko'radi?

Eng oddiy tekshiruv: storeID=1;whoami.

Bu eng toza holat: natija to'g'ridan-to'g'ri javobda ko'rinadi. ; birinchi buyruqni tugatadi, whoami yangisini boshlaydi, uning natijasi sahifaga qaytadi. Endi whoami o'rniga istalgan buyruq — fayllarni ko'rish, o'qish, o'chirish — hammasi mumkin.

2-labVaqt orqali (blind)#

Lab: Blind OS command injection with time delays · PRACTITIONER

Vazifa: 10 soniyalik kechikish yuzaga keltirish.

Nimani ko'rasiz: fikr-mulohaza formasi. Buyruq bajariladi, lekin natija javobda ko'rinmaydi.

Savol: natijani ko'rmasangiz, buyruq bajarilganini qanday bilasiz? Serverni kutishga majbur qila olasizmi?

Eng oddiy tekshiruv: email=x@x.com; sleep 10 — javob 10 soniya kechiksa, buyruq bajarildi.

Natija ko'rinmasa ham, buyruq bajarilishini isbotlash mumkin. sleep 10 serverni 10 soniya kutishga majbur qiladi; javob kechiksa — buyruq ishladi. Bu blind injection'ning kaliti: natijani ko'rmasangiz, uni sezilarli qiling — vaqt, fayl yoki tashqi so'rov orqali.

3-labFaylga yozib o'qish#

Lab: Blind OS command injection with output redirection · PRACTITIONER

Vazifa: whoami natijasini olish — javobda ko'rinmasa ham.

Nimani ko'rasiz: yana natija javobda yo'q, lekin serverda web'dan o'qiladigan papka bor.

Savol: natija javobga qaytmasa, uni boshqa joyga yozib, keyin o'sha joyni o'qiy olasizmi?

Eng oddiy tekshiruv: whoami > /var/www/images/out.txt, keyin out.txt ni brauzerda oching.

Natija javobda ko'rinmasa, uni web'dan o'qiladigan faylga yo'naltirasiz (>), keyin o'sha faylni to'g'ridan ochasiz. Ikki qadam, lekin natijani qo'lga olasiz. Blind bo'lgani "ko'rinmaydi" degani, "chiqarib bo'lmaydi" degani emas.

4-labTashqi kanal orqali#

Lab: Blind OS command injection with out-of-band interaction · PRACTITIONER

Vazifa: serverdan Burp Collaborator'ga DNS so'rovi yubortirish.

Nimani ko'rasiz: buyruq bajariladi, lekin natija ham ko'rinmaydi, faylga ham yozib bo'lmaydi.

Savol: server tashqariga chiqa oladimi? Buyruq tashqi manzilga so'rov yuborsa, o'sha so'rovni ushlab, buyruq bajarilganini tasdiqlay olasizmi?

Eng oddiy tekshiruv: email=x@x.com; nslookup <collaborator-domen> — Collaborator DNS so'rovni ushlaydi.

Eng nozik holat: natija ko'rinmaydi, fayl ham yozib bo'lmaydi. Lekin buyruq serverni tashqi manzilga so'rov yuborishga majbur qilsa (DNS, HTTP), o'sha so'rovning kelishi — buyruq bajarilganining isboti. Bu out-of-band (OAST): javob bir kanaldan kutilmaydi, boshqasidan keladi. Server tashqariga hech qanday signal chiqarmasligi kerak.

Nima ishlamaydi va nega#

"; belgisini bloklasam yetadi." Shell'da buyruq bog'lashning o'nlab usuli bor: |, &, &&, ||, ` `, $(), yangi qator. Bittasini bloklasangiz, boshqasi qoladi. Denylist shell metabelgilarini hech qachon to'liq qamramaydi.

"Natijani yashirsam, injection foydasiz." 2, 3, 4-lab: natija ko'rinmasa ham, buyruq vaqt, fayl yoki tashqi so'rov orqali o'zini oshkor qiladi. Blind — sekinroq, lekin to'xtatmaydi.

"Faqat kutilgan qiymatni qabul qilaman deb tekshiraman." To'g'ri yo'nalish, lekin tekshiruv yetarlicha qattiq bo'lishi shart — raqam kutsangiz ^[0-9]+$, matn kutsangiz allowlist. Yumshoq tekshiruv har doim teshik qoldiradi.

Endi yopamiz#

Command injection'ning yechimi boshqa zaifliklardan qat'iyroq: tashqi buyruqni umuman chaqirmang. Deyarli har bir "buyruq" vazifasining kod ekvivalenti bor.

1. Eng yaxshi: shell'ga umuman chiqmang. Fayl o'qish, ping, arxivlash — hammasining kutubxonasi bor:

Python
# Zaif: tashqi buyruq + foydalanuvchi qiymati
subprocess.check_output(f"stockreport.sh {store}", shell=True)

# To'g'ri: vazifani kod ichida bajaring, buyruq umuman kerak emas
stock = StockReport.objects.get(store_id=store).count

2. Chaqirish shart bo'lsa — shell=False va argumentlar ro'yxati:

Python
# shell=False (default) + ro'yxat: qiymat ARGUMENT bo'lib qoladi, buyruq emas
# ; | & belgilari endi maxsus emas — ular shunchaki matn
subprocess.check_output(["stockreport.sh", store, product])

shell=True — command injection'ning ildizi. Argumentlar ro'yxati bilan (shell=False) qiymat hech qachon shellga bormaydi, ya'ni ; va | oddiy matn bo'lib qoladi. Bitta o'zgarish barcha labllarni yopadi.

3. Kirishni ham tekshiring (chuqurlik uchun): raqam kutsangiz, faqat raqam qabul qiling. Bu birlamchi himoya emas (shell=False birlamchi), lekin qatlam sifatida foydali.

Muhim

shell=True ni foydalanuvchi ma'lumoti bilan hech qachon ishlatmang. Kodni ko'rib chiqishda shell=True — birinchi qidiriladigan qizil bayroq. Agar uni ko'rsangiz, argumentlar ro'yxatiga o'tkazing.

Aniq misol: bu saytda grep -rn "shell=True\|os.system\|subprocess" apps/ hech nima topmaydi — ilova kodida bironta tashqi buyruq chaqiruvi yo'q. Bu tasodif emas, dizayn: kontent markdown fayllardan o'qiladi, tasvirlar Pillow kutubxonasi bilan (buyruqsiz) ishlanadi, hamma vazifa Python kodida bajariladi. "Buyruqni umuman chaqirmaslik" — eng ishonchli himoya, va u bu yerda amalda ko'rinadi.

Nazorat savollari#

  1. OS command injection nega eng xavfli zaifliklardan biri?
  2. 1; whoami da shell nechta buyruq ko'radi? ; nima qiladi?
  3. shell=True nega xavfli? U qiymatni kimga beradi?
  4. Blind injection nima? Natija ko'rinmasa, buyruqni qanday tasdiqlaysiz (2-lab)?
  5. 3-labda natijani qanday chiqardingiz? "Ko'rinmaydi ≠ chiqarib bo'lmaydi" nimani anglatadi?
  6. Out-of-band (4-lab) nima? Natija qaysi kanaldan keldi?
  7. Nega "; ni bloklash" command injection'ni yopmaydi?
  8. shell=False + argumentlar ro'yxati nega injection'ni to'xtatadi? ; unda nima bo'ladi?
  9. Eng ishonchli yechim nima — nega "buyruqni umuman chaqirmaslik"?
  10. Kod ko'rib chiqishda qaysi belgi birinchi qidiriladigan qizil bayroq?

Report uchun talablar#

  1. Skrinshot: 1-labda whoami natijasi ko'ringan holat.
  2. Blind: 2, 3 yoki 4-labda buyruq bajarilganini qaysi usul bilan tasdiqladingiz (vaqt / fayl / tashqi kanal)? Tushuntiring.
  3. Bir naqsh: command injection SQLi va path traversal bilan qaysi naqshni baham ko'radi? Uch darsda takrorlangan g'oyani ayting.
  4. Tuzatuvchi kod: yuqoridagi shell=True misolini oling (yoki o'z loyihangizdan) va uni shell=False + argumentlar ro'yxatiga, yoki buyruqsiz yechimga o'tkazing. Oldingi va keyingi holatni keltiring.

Faqat ruxsat berilgan joyda

Command injection butun serverni egallash imkonini beradi — bu eng og'ir zaifliklardan. Uni faqat PortSwigger laboratoriyasida yoki o'zingizga tegishli serverda sinang. Birovning serverida buyruq bajarish — og'ir jinoyat.


Keyingi dars: Business logic — hujum tool talab qilmaydi, faqat fikrlash bilan: tizim dizaynidagi mantiqiy bo'shliqlar va nega "jarayon faqat men o'ylagancha ketadi" degan taxmin xato.

9 daqiqa 40 marta o‘qildi