15-bo‘lim
Konteyner xavfsizligi
Konteynerdagi root nima degani, rootless rejim, USER, imkoniyatlarni tashlash, Docker soketi xavfi va obrazni skanerlash.
Ushbu bo‘lim mundarijasi
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? #
docker run --rm alpine:3.21 id -u
docker run --rm alpine:3.21 id -un
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:
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))"
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.
Rejimni tekshirish oson:
docker info --format '{{range .SecurityOptions}}{{println .}}{{end}}'
name=seccomp,profile=builtin
name=rootless
name=cgroupns
name=rootless bor - demak biz himoyalangan rejimdamiz.
-v /:/host - bu tugatilgan o'yinOddiy Docker da quyidagi buyruq butun serverni beradi:
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.
FROM alpine:3.21
RUN adduser -D -u 10001 dokon
USER dokon
CMD ["id"]
docker run --rm norut:1
uid=10001(dokon) gid=10001(dokon) groups=10001(dokon)
Endi ilova tizim fayllarini o'zgartira olmaydi:
docker run --rm norut:1 sh -c 'touch /etc/yangi' 2>&1 | head -1
touch: /etc/yangi: Permission denied
Hujumchi kod bajarishga erishsa ham, u obrazni o'zgartira olmaydi va paket o'rnata olmaydi.
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:
docker run --rm alpine:3.21 sh -c \
'apk add -q libcap; capsh --print | grep -m1 "^Current:"' | tr ',' '\n'
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:
docker run --rm --cap-drop ALL alpine:3.21 sh -c \
'apk add -q libcap; capsh --print | grep -m1 "^Current:"'
Current: =
Ro'yxat bo'sh. Farqni ko'rish uchun chown ni sinaymiz - u
CAP_CHOWN talab qiladi:
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
chown ishladi
chown: /tmp: Operation not permitted
Kerakli bittasini qaytarib berish mumkin:
--cap-drop ALL --cap-add NET_BIND_SERVICE
| Imkoniyat | Qachon kerak |
|---|---|
NET_BIND_SERVICE | 1024 dan kichik portni tinglash |
CHOWN, FOWNER | Fayl egaligini o'zgartirish |
SETUID, SETGID | Foydalanuvchini almashtirish |
NET_RAW | Xom soket (ping, tcpdump) |
SYS_ADMIN | Deyarli root bilan teng - bermang |
ping va CAP_NET_RAW - kutilmagan natijaOdatda "--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 #
docker run --rm -v /run/user/1000/docker.sock:/var/run/docker.sock \
docker:cli docker ps -a --format '{{.Image}}' | head -3
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.
Ko'p qo'llanmada CI agenti yoki monitoring uchun shunday yoziladi:
-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 #
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
| Sozlama | Nimadan himoya qiladi |
|---|---|
user: | Konteyner ichida root bo'lishdan |
read_only | Veb qobiq va fayl almashtirishdan |
cap_drop: [ALL] | Ortiqcha yadro imkoniyatlaridan |
no-new-privileges | setuid orqali huquq oshirishdan |
pids_limit | Fork bombasidan |
| Alohida tarmoq | Yon 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:
docker run --rm -v trivy-kesh:/root/.cache aquasec/trivy:latest \
image --severity HIGH,CRITICAL alpine:3.21
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:
- Qurishda - CI da har bir obraz uchun
- Muntazam - haftada bir marta mavjud obrazlarni qayta
- Kritik topilma bo'lsa - qurishni to'xtatish
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 #
| Savol | Buyruq |
|---|---|
| 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
dockerguruhiga qo'shish root berish bilan teng. USERbilan konteyner ichida ham root bo'lmang; UID ni aniq raqam bilan bering.- Docker standart holatda 14 ta imkoniyat beradi;
--cap-drop ALLularni tozalaydi. - Imkoniyat kerakligini taxmin qilmang:
pingCAP_NET_RAWsiz ham ishladi, chunki yadro ICMP soketiga ruxsat bergan. - Docker soketini ulash - demon ustidan to'liq nazorat berish.
read_only,no-new-privileges,pids_limitva alohida tarmoq birga ishlaydi.- Obrazni muntazam skanerlang: baza yangilanadi, obraz esa o'zgarmaydi.
docker infodaname=rootlessbor-yo'qligini tekshiring.- Konteynerdan hostdagi papkaga fayl yozib, egasini aniqlang.
USERbilan norut obraz yarating vaidni tekshiring.- Norut foydalanuvchi bilan
/etcga yozishga urinib ko'ring. capsh --printni standart va--cap-drop ALLbilan solishtiring.chownorqali imkoniyat farqini ko'rsating.--read-onlyvano-new-privilegesni qo'shing.- Docker soketini ulab, konteynerdan
docker psqiling va xavfni tushuntiring. - Trivy bilan ikkita obrazni skanerlab, natijani solishtiring.
- O'z obrazingiz uchun tekshiruv ro'yxatini to'ldiring.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.