From 3e2af030d47920f4c7d4f8794a77a6633e560d21 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 12 Feb 2026 20:02:37 +0100 Subject: [PATCH] f --- .../2_container/3_Container_details.sh | 8 +++ .../2_container/5_Container_breakout.sh | 37 ++++++++-- .../functions/enumerateDockerSockets.sh | 67 ++++++++++++------- 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/linPEAS/builder/linpeas_parts/2_container/3_Container_details.sh b/linPEAS/builder/linpeas_parts/2_container/3_Container_details.sh index 56537d9..d6bad98 100644 --- a/linPEAS/builder/linpeas_parts/2_container/3_Container_details.sh +++ b/linPEAS/builder/linpeas_parts/2_container/3_Container_details.sh @@ -36,6 +36,14 @@ print_2title "Container details" print_list "Is this a container? ...........$NC $containerType" +if [ -e "/proc/vz" ] && ! [ -e "/proc/bc" ]; then + print_list "Container Runtime ..............$NC OpenVZ" +fi + +if [ -f "/run/systemd/container" ]; then + print_list "Systemd Container ..............$NC $(cat /run/systemd/container)" +fi + # Get container runtime info if [ "$(command -v docker || echo -n '')" ]; then print_list "Docker version ...............$NC " diff --git a/linPEAS/builder/linpeas_parts/2_container/5_Container_breakout.sh b/linPEAS/builder/linpeas_parts/2_container/5_Container_breakout.sh index f0d13cb..e46f70e 100644 --- a/linPEAS/builder/linpeas_parts/2_container/5_Container_breakout.sh +++ b/linPEAS/builder/linpeas_parts/2_container/5_Container_breakout.sh @@ -37,10 +37,10 @@ # - Container escape tool execution # License: GNU GPL # Version: 1.0 -# Functions Used: checkContainerExploits, checkProcSysBreakouts, containerCheck, print_2title, print_3title, print_info, print_list, warn_exec +# Functions Used: checkContainerExploits, checkProcSysBreakouts, containerCheck, enumerateDockerSockets, print_2title, print_3title, print_info, print_list, warn_exec # Global Variables: $binfmt_misc_breakout, $containercapsB, $containerType, $core_pattern_breakout, $dev_mounted, $efi_efivars_writable, $efi_vars_writable, $GREP_IGNORE_MOUNTS, $inContainer, $kallsyms_readable, $kcore_readable, $kmem_readable, $kmem_writable, $kmsg_readable, $mem_readable, $mem_writable, $modprobe_present, $mountinfo_readable, $panic_on_oom_dos, $panic_sys_fs_dos, $proc_configgz_readable, $proc_mounted, $run_unshare, $release_agent_breakout1, $release_agent_breakout2, $release_agent_breakout3, $sched_debug_readable, $security_present, $security_writable, $sysreq_trigger_dos, $uevent_helper_breakout, $vmcoreinfo_readable, $VULN_CVE_2019_5021, $self_mem_readable # Initial Functions: containerCheck -# Generated Global Variables: $defautl_docker_caps, $containerd_version, $runc_version, $containerd_version +# Generated Global Variables: $defautl_docker_caps, $containerd_version, $runc_version, $seccomp_mode_num, $seccomp_mode_desc # Fat linpeas: 0 # Small linpeas: 0 @@ -57,14 +57,34 @@ if [ "$inContainer" ]; then # Security mechanisms print_3title "Security Mechanisms" - print_list "Seccomp enabled? ............... "$NC - ([ "$(grep Seccomp /proc/self/status | grep -v 0)" ] && echo "enabled" || echo "disabled") | sed "s,disabled,${SED_RED}," | sed "s,enabled,${SED_GREEN}," + seccomp_mode_num="$(awk '/^Seccomp:/{print $2}' /proc/self/status 2>/dev/null)" + seccomp_mode_desc="unknown" + case "$seccomp_mode_num" in + 0) seccomp_mode_desc="disabled" ;; + 1) seccomp_mode_desc="strict" ;; + 2) seccomp_mode_desc="filtering" ;; + esac + + print_list "Seccomp mode ................... "$NC + (printf "%s (%s)\n" "$seccomp_mode_desc" "${seccomp_mode_num:-?}") | sed "s,disabled,${SED_RED}," | sed "s,strict,${SED_RED_YELLOW}," | sed "s,filtering,${SED_GREEN}," + + if grep -q "^Seccomp_filters:" /proc/self/status 2>/dev/null; then + print_list "Seccomp filters ............... "$NC + awk '/^Seccomp_filters:/{print $2}' /proc/self/status 2>/dev/null | sed -${E} "s,^[0-9]+$,${SED_GREEN}&," + fi print_list "AppArmor profile? .............. "$NC (cat /proc/self/attr/current 2>/dev/null || echo "disabled") | sed "s,disabled,${SED_RED}," | sed "s,kernel,${SED_GREEN}," print_list "User proc namespace? ........... "$NC - if [ "$(cat /proc/self/uid_map 2>/dev/null)" ]; then (printf "enabled"; cat /proc/self/uid_map) | sed "s,enabled,${SED_GREEN},"; else echo "disabled" | sed "s,disabled,${SED_RED},"; fi + if [ "$(cat /proc/self/uid_map 2>/dev/null)" ]; then + (printf "enabled"; cat /proc/self/uid_map) | sed "s,enabled,${SED_GREEN},"; + echo "" + echo " Mappings (Container -> Host -> Range):" + cat /proc/self/uid_map | awk '{print " " $1 " -> " $2 " -> " $3}' + else + echo "disabled" | sed "s,disabled,${SED_RED},"; + fi # Known vulnerabilities print_3title "Known Vulnerabilities" @@ -155,6 +175,9 @@ if [ "$inContainer" ]; then cat /proc/self/status | tr '\t' ' ' | grep Cap | sed -${E} "s, .*,${SED_RED},g" | sed -${E} "s/00000000a80425fb/$defautl_docker_caps/g" | sed -${E} "s,0000000000000000|00000000a80425fb,${SED_GREEN},g" echo $ITALIC"Run capsh --decode= to decode the capabilities"$NC fi + + print_list "Ambient capabilities ........... "$NC + (grep "CapAmb:" /proc/self/status 2>/dev/null | grep -v "0000000000000000" | sed "s,CapAmb:.,," || echo "No") | sed -${E} "s,No,${SED_GREEN}," | sed -${E} "s,[0-9a-fA-F]\+,${SED_RED}&," # Additional capability checks print_list "Dangerous syscalls allowed ... "$NC @@ -200,6 +223,10 @@ if [ "$inContainer" ]; then echo "No" fi + + print_list "Looking and enumerating Docker Sockets (if any):\n"$NC + enumerateDockerSockets + # Additional breakout vectors print_3title "Additional Breakout Vectors" diff --git a/linPEAS/builder/linpeas_parts/functions/enumerateDockerSockets.sh b/linPEAS/builder/linpeas_parts/functions/enumerateDockerSockets.sh index 74091e8..8b41440 100644 --- a/linPEAS/builder/linpeas_parts/functions/enumerateDockerSockets.sh +++ b/linPEAS/builder/linpeas_parts/functions/enumerateDockerSockets.sh @@ -6,9 +6,9 @@ # License: GNU GPL # Version: 1.0 # Functions Used: echo_not_found -# Global Variables: $GREP_DOCKER_SOCK_INFOS, $GREP_DOCKER_SOCK_INFOS_IGNORE, $IAMROOT +# Global Variables: $GREP_DOCKER_SOCK_INFOS, $GREP_DOCKER_SOCK_INFOS_IGNORE # Initial Functions: -# Generated Global Variables: $SEARCHED_DOCKER_SOCKETS, $dock_sock, $docker_enumerated, $dockerVersion, $int_sock, $sockInfoResponse +# Generated Global Variables: $SEARCHED_DOCKER_SOCKETS, $docker_enumerated, $dockerVersion, $int_sock, $sockInfoResponse # Fat linpeas: 0 # Small linpeas: 1 @@ -17,34 +17,55 @@ enumerateDockerSockets() { dockerVersion="$(echo_not_found)" if ! [ "$SEARCHED_DOCKER_SOCKETS" ]; then SEARCHED_DOCKER_SOCKETS="1" - for int_sock in $(find / ! -path "/sys/*" -type s -name "docker.sock" -o -name "docker.socket" -o -name "dockershim.sock" -o -name "containerd.sock" -o -name "crio.sock" -o -name "frakti.sock" -o -name "rktlet.sock" 2>/dev/null); do - if ! [ "$IAMROOT" ] && [ -w "$int_sock" ]; then + # NOTE: This is intentionally "lightweight" (checks common runtime socket names) and avoids + # pseudo filesystems (/sys, /proc) to reduce noise and latency. + for int_sock in $(find / \ + -path "/sys" -prune -o \ + -path "/proc" -prune -o \ + -type s \( \ + -name "docker.sock" -o \ + -name "docker.socket" -o \ + -name "dockershim.sock" -o \ + -name "containerd.sock" -o \ + -name "crio.sock" -o \ + -name "frakti.sock" -o \ + -name "rktlet.sock" \ + \) -print 2>/dev/null); do + + # Basic permissions hint (you generally need write perms to connect to a unix socket). + if [ -w "$int_sock" ]; then if echo "$int_sock" | grep -Eq "docker"; then - dock_sock="$int_sock" - echo "You have write permissions over Docker socket $dock_sock" | sed -${E} "s,$dock_sock,${SED_RED_YELLOW},g" - echo "Docker enummeration:" - docker_enumerated="" - - if [ "$(command -v curl || echo -n '')" ]; then - sockInfoResponse="$(curl -s --unix-socket $dock_sock http://localhost/info)" - dockerVersion=$(echo "$sockInfoResponse" | tr ',' '\n' | grep 'ServerVersion' | cut -d'"' -f 4) - echo $sockInfoResponse | tr ',' '\n' | grep -E "$GREP_DOCKER_SOCK_INFOS" | grep -v "$GREP_DOCKER_SOCK_INFOS_IGNORE" | tr -d '"' - if [ "$sockInfoResponse" ]; then docker_enumerated="1"; fi - fi - - if [ "$(command -v docker || echo -n '')" ] && ! [ "$docker_enumerated" ]; then - sockInfoResponse="$(docker info)" - dockerVersion=$(echo "$sockInfoResponse" | tr ',' '\n' | grep 'Server Version' | cut -d' ' -f 4) - printf "$sockInfoResponse" | tr ',' '\n' | grep -E "$GREP_DOCKER_SOCK_INFOS" | grep -v "$GREP_DOCKER_SOCK_INFOS_IGNORE" | tr -d '"' - fi - + echo "You have write permissions over Docker socket $int_sock" | sed -${E} "s,$int_sock,${SED_RED_YELLOW},g" else echo "You have write permissions over interesting socket $int_sock" | sed -${E} "s,$int_sock,${SED_RED},g" fi - else echo "You don't have write permissions over interesting socket $int_sock" | sed -${E} "s,$int_sock,${SED_GREEN},g" fi + + # Validate whether this looks like a Docker Engine API socket (amicontained-style) when curl exists. + docker_enumerated="" + if [ "$(command -v curl 2>/dev/null || echo -n '')" ]; then + sockInfoResponse="$(curl -s --max-time 2 --unix-socket "$int_sock" http://localhost/info 2>/dev/null)" + if echo "$sockInfoResponse" | grep -q "ServerVersion"; then + echo "Valid Docker API socket: $int_sock" | sed -${E} "s,$int_sock,${SED_RED_YELLOW},g" + dockerVersion=$(echo "$sockInfoResponse" | tr ',' '\n' | grep 'ServerVersion' | cut -d'"' -f 4) + echo "$sockInfoResponse" | tr ',' '\n' | grep -E "$GREP_DOCKER_SOCK_INFOS" | grep -v "$GREP_DOCKER_SOCK_INFOS_IGNORE" | tr -d '"' + docker_enumerated="1" + fi + fi + + # Fallback to docker CLI if curl is missing or the /info request didn't work. + # Use DOCKER_HOST so we can target non-default socket paths when possible. + if [ "$(command -v docker 2>/dev/null || echo -n '')" ] && ! [ "$docker_enumerated" ]; then + if [ -w "$int_sock" ] && echo "$int_sock" | grep -Eq "docker"; then + sockInfoResponse="$(DOCKER_HOST="unix://$int_sock" docker info 2>/dev/null)" + if [ "$sockInfoResponse" ]; then + dockerVersion=$(echo "$sockInfoResponse" | grep -i "^ Server Version:" | awk '{print $4}' | head -n 1) + printf "%s\n" "$sockInfoResponse" | grep -E "$GREP_DOCKER_SOCK_INFOS" | grep -v "$GREP_DOCKER_SOCK_INFOS_IGNORE" | tr -d '"' + fi + fi + fi done fi }