15-bo‘lim

Konteyner xavfsizligi

Konteynerdagi root nima degani, rootless rejim, USER, imkoniyatlarni tashlash, Docker soketi xavfi va obrazni skanerlash.

🕑 17 daqiqa o‘qish 📄 972 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Konteynerda kim bo'lasiz?
  2. Rootless rejim - javob shu yerda
  3. USER - konteynerda ham root bo'lmang
  4. Imkoniyatlarni tashlash
  5. Docker soketi - eng katta xavf
  6. Boshqa qat'iylashtirish choralari
  7. Obrazni skanerlash
  8. Tekshiruv ro'yxati
  9. Xulosa

Konteyner - virtual mashina emas. U hostning o'sha yadrosida ishlaydi. Demak ajratish devor emas, balki yadro qo'yadigan chegaralar to'plami.

Bu bob shu chegaralar haqida.

Konteynerda kim bo'lasiz? #

Terminal
docker run --rm alpine:3.21 id -u
docker run --rm alpine:3.21 id -un
Natija
0
root

root. Boshqa hech narsa aytmasangiz, har bir konteyner root sifatida ishlaydi.

Savol: bu hostdagi root bilan bir xilmi?

Rootless rejim - javob shu yerda #

Konteynerdagi root hostdagi papkaga fayl yozsin:

Terminal
docker run --rm -v /tmp/xavf:/tashqi alpine:3.21 \
    sh -c 'echo salom > /tashqi/fayl'
stat -c 'fayl egasi: %u (%U)' /tmp/xavf/fayl
echo "host foydalanuvchisi: $(id -u) ($(id -un))"
Natija
fayl egasi: 1000 (husanboy)
host foydalanuvchisi: 1000 (husanboy)

Konteyner ichida uid=0, lekin hostda fayl oddiy foydalanuvchi nomidan yaratildi.

Sabab - rootless rejim va foydalanuvchi namespace lari: konteynerdagi 0 hostdagi 1000 ga xaritalanadi.

Konteynerdagi root hostda kim? Oddiy (rootful) Docker konteyner: uid 0 (root) to'g'ridan-to'g'ri host: uid 0 (ROOT) Konteynerdan chiqish - butun serverni egallash Rootless Docker konteyner: uid 0 (root) xaritalanadi host: uid 1000 (husanboy) Konteynerdan chiqish - oddiy foydalanuvchi huquqi Bu darslikdagi barcha misollar rootless rejimda bajarilgan. Server o'rnatishlarining ko'pchiligi esa hali ham rootful - buni tekshiring.
Bir xil "root", butunlay boshqa oqibat

Rejimni tekshirish oson:

Terminal
docker info --format '{{range .SecurityOptions}}{{println .}}{{end}}'
Natija
name=seccomp,profile=builtin
name=rootless
name=cgroupns

name=rootless bor - demak biz himoyalangan rejimdamiz.

Rootful rejimda -v /:/host - bu tugatilgan o'yin

Oddiy Docker da quyidagi buyruq butun serverni beradi:

Natija
docker run -v /:/host alpine chroot /host sh

Konteyner root hostda ham root, demak /etc/shadow ni o'qish, SSH kalit qo'shish, xizmat o'rnatish - hammasi mumkin.

Shuning uchun docker guruhiga qo'shish = root berish. Bu 7-bobdagi Linux huquqlari qoidasining to'g'ridan-to'g'ri natijasi.

Rootless rejimda esa xuddi shu buyruq faqat sizning fayllaringizni beradi - bu ham yoqimsiz, lekin server egallanmaydi.

USER - konteynerda ham root bo'lmang #

Rootless yordam beradi, lekin ilova baribir konteyner ichida root bo'lmasligi kerak.

DOCKERFILE
FROM alpine:3.21
RUN adduser -D -u 10001 dokon
USER dokon
CMD ["id"]
Terminal
docker run --rm norut:1
Natija
uid=10001(dokon) gid=10001(dokon) groups=10001(dokon)

Endi ilova tizim fayllarini o'zgartira olmaydi:

Terminal
docker run --rm norut:1 sh -c 'touch /etc/yangi' 2>&1 | head -1
Natija
touch: /etc/yangi: Permission denied

Hujumchi kod bajarishga erishsa ham, u obrazni o'zgartira olmaydi va paket o'rnata olmaydi.

UID ni aniq raqam bilan bering

adduser -D dokon deb yozsangiz, UID distributivga qarab turlicha bo'ladi.

Aniq raqam (-u 10001) berilsa, hajmdagi fayl egaliklari oldindan bilinadi - Kubernetes runAsUser bilan ham mos tushadi.

1000 dan katta raqam tanlang: kichik raqamlar tizim foydalanuvchilariga tegishli.

Imkoniyatlarni tashlash #

Linux da root huquqi bo'linmas emas - u imkoniyatlarga (capabilities) bo'lingan. Docker standart holatda ularning bir qismini beradi:

Terminal
docker run --rm alpine:3.21 sh -c \
    'apk add -q libcap; capsh --print | grep -m1 "^Current:"' | tr ',' '\n'
Natija
Current: cap_chown
cap_dac_override
cap_fowner
cap_fsetid
cap_kill
cap_setgid
cap_setuid
cap_setpcap
cap_net_bind_service
cap_net_raw
cap_sys_chroot
cap_mknod
cap_audit_write
cap_setfcap=ep

(Ro'yxatni o'qish uchun vergullarni yangi qatorga bo'ldik.)

O'n to'rtta imkoniyat. Ilovangizga ularning deyarli hech biri kerak emas:

Terminal
docker run --rm --cap-drop ALL alpine:3.21 sh -c \
    'apk add -q libcap; capsh --print | grep -m1 "^Current:"'
Natija
Current: =

Ro'yxat bo'sh. Farqni ko'rish uchun chown ni sinaymiz - u CAP_CHOWN talab qiladi:

Terminal
docker run --rm alpine:3.21 sh -c \
    'chown nobody /tmp && echo "chown ishladi"' 2>&1 | head -1
docker run --rm --cap-drop ALL alpine:3.21 sh -c \
    'chown nobody /tmp && echo "chown ishladi"' 2>&1 | head -1
Natija
chown ishladi
chown: /tmp: Operation not permitted

Kerakli bittasini qaytarib berish mumkin:

Natija
--cap-drop ALL --cap-add NET_BIND_SERVICE
ImkoniyatQachon kerak
NET_BIND_SERVICE1024 dan kichik portni tinglash
CHOWN, FOWNERFayl egaligini o'zgartirish
SETUID, SETGIDFoydalanuvchini almashtirish
NET_RAWXom soket (ping, tcpdump)
SYS_ADMINDeyarli root bilan teng - bermang
ping va CAP_NET_RAW - kutilmagan natija

Odatda "--cap-drop ALL qilsangiz ping ishlamaydi" deyiladi. Men sinab ko'rdim - ishladi.

Sababi: zamonaviy yadrolarda ping xom soket o'rniga ICMP soketidan foydalanadi va unga net.ipv4.ping_group_range sozlamasi ruxsat beradi. Bu tizimda u 0 2147483647, ya'ni hamma guruhga ochiq.

Xulosa: imkoniyat kerakligini taxmin qilmang - o'z muhitingizda sinab ko'ring.

Docker soketi - eng katta xavf #

Terminal
docker run --rm -v /run/user/1000/docker.sock:/var/run/docker.sock \
    docker:cli docker ps -a --format '{{.Image}}' | head -3
Natija
docker:cli

Konteyner hostdagi Docker demonini ko'rdi va konteynerlar ro'yxatini oldi. U endi istalgan obrazni ishga tushira oladi, istalgan papkani ulay oladi va o'zi uchun imtiyozli konteyner yarata oladi.

Soketni ulash - demonni topshirish

Ko'p qo'llanmada CI agenti yoki monitoring uchun shunday yoziladi:

Natija
-v /var/run/docker.sock:/var/run/docker.sock

Bu konteynerga butun demon ustidan nazorat beradi. Rootful o'rnatishda bu to'g'ridan-to'g'ri root demakdir.

Muqobillari:

  • Soketni faqat o'qish uchun proksi orqali berish
  • CI uchun rootless yoki alohida quruvchi (buildkit) ishlatish
  • Kubernetes da esa umuman boshqa yondashuv

Boshqa qat'iylashtirish choralari #

YAML
services:
  ilova:
    image: dokon:1.0
    user: "10001:10001"
    read_only: true
    tmpfs: [/tmp]
    cap_drop: [ALL]
    security_opt:
      - no-new-privileges:true
    pids_limit: 200
SozlamaNimadan himoya qiladi
user:Konteyner ichida root bo'lishdan
read_onlyVeb qobiq va fayl almashtirishdan
cap_drop: [ALL]Ortiqcha yadro imkoniyatlaridan
no-new-privilegessetuid orqali huquq oshirishdan
pids_limitFork bombasidan
Alohida tarmoqYon tomonga siljishdan

Bu ro'yxat 14-bobdagi resurs chegaralari bilan birga ishlaydi - ikkalasi bitta maqsadga xizmat qiladi: buzilish bitta konteyner ichida qolsin.

Obrazni skanerlash #

Obrazingizdagi kutubxonalarda ma'lum zaifliklar bo'lishi mumkin. Trivy ularni topadi va uni alohida o'rnatish shart emas:

Natija
docker run --rm -v trivy-kesh:/root/.cache aquasec/trivy:latest \
    image --severity HIGH,CRITICAL alpine:3.21
Natija
Report Summary

┌─────────────────────────────┬────────┬─────────────────┬─────────┐
│           Target            │  Type  │ Vulnerabilities │ Secrets │
├─────────────────────────────┼────────┼─────────────────┼─────────┤
│ alpine:3.21 (alpine 3.21.7) │ alpine │        0        │    -    │
└─────────────────────────────┴────────┴─────────────────┴─────────┘

Toza. Lekin bu bugungi holat: Trivy ma'lumotlar bazasi har kuni yangilanadi, demak o'zgarmagan obraz ertaga zaif bo'lib qolishi mumkin.

Shuning uchun skanerlash bir martalik ish emas:

  1. Qurishda - CI da har bir obraz uchun
  2. Muntazam - haftada bir marta mavjud obrazlarni qayta
  3. Kritik topilma bo'lsa - qurishni to'xtatish
Eng yaxshi zaiflik - umuman bo'lmagani

Obraz qancha kichik bo'lsa, zaiflik ham shuncha kam. 7-bobdagi scratch obrazida skanerlash uchun hech narsa yo'q edi.

Tartib bo'yicha: scratch → distroless → alpine → debian-slim → to'liq distributiv.

Har bir qadam obrazga o'nlab paket va ular bilan birga o'nlab potensial zaiflik qo'shadi.

Tekshiruv ro'yxati #

SavolBuyruq
Rootless rejimdami?docker info da name=rootless
Konteyner root sifatida ishlayaptimi?docker run ... id
Imkoniyatlar tashlanganmi?.HostConfig.CapDrop
Fayl tizimi faqat o'qishmi?.HostConfig.ReadonlyRootfs
Soket ulanganmi?.Mounts da docker.sock
Obraz skanerlanganmi?CI jurnalida Trivy
Sir obraz tarixida bormi?docker history --no-trunc

Oxirgisi 10-bobdan - u eng ko'p unutiladigan tekshiruv.

Xulosa #

  • Konteyner host yadrosida ishlaydi; ajratish - yadro chegaralari, devor emas.
  • Standart holatda konteyner root sifatida ishlaydi.
  • Rootless rejimda konteynerdagi root hostdagi oddiy foydalanuvchiga xaritalanadi - buni fayl egaligi bilan ko'rsatdik.
  • Rootful o'rnatishda docker guruhiga qo'shish root berish bilan teng.
  • USER bilan konteyner ichida ham root bo'lmang; UID ni aniq raqam bilan bering.
  • Docker standart holatda 14 ta imkoniyat beradi; --cap-drop ALL ularni tozalaydi.
  • Imkoniyat kerakligini taxmin qilmang: ping CAP_NET_RAW siz ham ishladi, chunki yadro ICMP soketiga ruxsat bergan.
  • Docker soketini ulash - demon ustidan to'liq nazorat berish.
  • read_only, no-new-privileges, pids_limit va alohida tarmoq birga ishlaydi.
  • Obrazni muntazam skanerlang: baza yangilanadi, obraz esa o'zgarmaydi.
Amaliy topshiriq
  1. docker info da name=rootless bor-yo'qligini tekshiring.
  2. Konteynerdan hostdagi papkaga fayl yozib, egasini aniqlang.
  3. USER bilan norut obraz yarating va id ni tekshiring.
  4. Norut foydalanuvchi bilan /etc ga yozishga urinib ko'ring.
  5. capsh --print ni standart va --cap-drop ALL bilan solishtiring.
  6. chown orqali imkoniyat farqini ko'rsating.
  7. --read-only va no-new-privileges ni qo'shing.
  8. Docker soketini ulab, konteynerdan docker ps qiling va xavfni tushuntiring.
  9. Trivy bilan ikkita obrazni skanerlab, natijani solishtiring.
  10. O'z obrazingiz uchun tekshiruv ro'yxatini to'ldiring.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.