diff --git a/deepce.sh b/deepce.sh index 99eae3e..393b4e6 100755 --- a/deepce.sh +++ b/deepce.sh @@ -57,14 +57,14 @@ Usage: ${0##*/} [OPTIONS...] --install Install useful packages before running script, this will maximise enumeration and exploitation potential - -doc, --delete-on-complete Script will delete itself on completion + -doc, --delete Script will delete itself on completion ${DG}[Exploits]$NC -e, --exploit Use one of the following exploits (eg. -e SOCK) - DOCKER use docker command to create new contains and mount root partition to priv esc - PRIVILEGED exploit a container with privileged mode to run commands on the host - SOCK use an exposed docker sock to create a new container and mount root partition to priv esc + DOCKER use docker command to create new contains and mount root partition to priv esc + PRIVILEGED exploit a container with privileged mode to run commands on the host + SOCK use an exposed docker sock to create a new container and mount root partition to priv esc CVE-2019-5746 CVE-2019-5021 @@ -119,12 +119,14 @@ See ${UNDERLINED}https://stealthcopter.github.io/deepce/guides/docker-group.md${ TIP_DOCKER_CMD="If we have permission to create new docker containers we can mount the host's root partition and chroot into it and execute commands on the host OS." TIP_PRIVILEGED_MODE="The container appears to be running in privilege mode, we should be able to access the raw disks and mount the hosts root partition in order to gain code execution. See ${UNDERLINED}https://stealthcopter.github.io/deepce/guides/docker-privileged.md${NC}" +TIP_DOCKER_ROOTLESS="In rootless mode privilege escalation to root will not be possible." TIP_CVE_2019_5021="Alpine linux version 3.3.x-3.5.x accidentally allow users to login as root with a blank password, if we have command execution in the container we can become root using su root" TIP_CVE_2019_13139="Docker versions before 18.09.4 are vulnerable to a command execution vulnerability when parsing URLs" TIP_CVE_2019_5736="Docker versions before 18.09.2 are vulnerable to a container escape by overwriting the runC binary" DANGEROUS_GROUPS="docker\|lxd\|root\|sudo\|wheel" +DANGEROUS_CAPABILITIES="cap_sys_admin\|cap_sys_ptrace\|cap_sys_module\|dac_read_search\|dac_override" CONTAINER_CMDS="docker lxc rkt kubectl podman" USEFUL_CMDS="curl wget gcc nc netcat ncat jq nslookup host hostname dig python python2 python3 nmap" @@ -136,7 +138,7 @@ USEFUL_CMDS="curl wget gcc nc netcat ncat jq nslookup host hostname dig python p # Convert version numbers into a regular number so we can do simple comparisons (use floats because sh can interpret 0 prefix numbers incorrectly otherwise). # shellcheck disable=SC2046 # shellcheck disable=SC2183 # word splitting here is on purpose -ver() { printf "%03.0f%03.0f%03.0f" $(echo "$1" | tr '.' ' '); } +ver() { printf "%03.0f%03.0f%03.0f" $(echo "$1" | tr '.' ' ' | cut -d '-' -f1); } ########################################### #--------------) Printing (---------------# @@ -272,7 +274,7 @@ installPackages() { return fi - if apt install --no-install-recommends --force-yes -y dnsutils curl nmap iputils-ping >/dev/null 2>&1; then + if apt install --no-install-recommends --force-yes -y dnsutils curl nmap iputils-ping libcap2-bin >/dev/null 2>&1; then printSuccess "Success" else printError "Failed" @@ -280,13 +282,13 @@ installPackages() { elif [ -x "$(command -v apk)" ]; then # Alpine - apk add bind-tools curl nmap + apk add bind-tools curl nmap libcap elif [ -x "$(command -v yum)" ]; then # CentOS / Fedora - yum install bind-utils curl nmap + yum install bind-utils curl nmap libcap elif [ -x "$(command -v apt-get)" ]; then # Old Debian - apt-get install -y dnsutils curl nmap + apt-get install -y dnsutils curl nmap inetutils-ping libcap2-bin fi } @@ -389,40 +391,38 @@ dockerSockCheck() { if [ "$dockerSockPath" ]; then printInfo "$(ls -lah $dockerSockPath)" - nl # Is docker sock writable printQuestion "Sock is writable ........" if test -r "$dockerSockPath"; then printYesEx printTip "$TIP_WRITABLE_SOCK" + if [ -x "$(command -v curl)" ]; then + sockInfoCmd="curl -s --unix-socket $dockerSockPath http://localhost/info" + sockInfoRepsonse="$($sockInfoCmd)" + + printTip "To see full info from the docker sock output run the following" + printStatus "$sockInfoCmd" + nl + + # Docker version unknown lets get it from the sock + if [ -z "$dockerVersion" ]; then + # IF jq... + #dockerVersion=`$sockInfoCmd | jq -r '.ServerVersion'` + dockerVersion=$(echo "$sockInfoRepsonse" | tr ',' '\n' | grep 'ServerVersion' | cut -d'"' -f 4) + fi + + # Get info from sock + info=$(echo "$sockInfoRepsonse" | tr ',' '\n' | grep "$GREP_SOCK_INFOS" | grep -v "$GREP_SOCK_INFOS_IGNORE" | tr -d '"') + + printInfo "$info" + else + printError "Could not interact with the docker sock, as curl is not installed" + printInstallAdvice "curl" + fi else printNo fi - - if [ -x "$(command -v curl)" ]; then - sockInfoCmd="curl -s --unix-socket $dockerSockPath http://localhost/info" - sockInfoRepsonse="$($sockInfoCmd)" - - printTip "To see full info from the docker sock output run the following" - printStatus "$sockInfoCmd" - nl - - # Docker version unknown lets get it from the sock - if [ -z "$dockerVersion" ]; then - # IF jq... - #dockerVersion=`$sockInfoCmd | jq -r '.ServerVersion'` - dockerVersion=$(echo "$sockInfoRepsonse" | tr ',' '\n' | grep 'ServerVersion' | cut -d'"' -f 4) - fi - - # Get info from sock - info=$(echo "$sockInfoRepsonse" | tr ',' '\n' | grep "$GREP_SOCK_INFOS" | grep -v "$GREP_SOCK_INFOS_IGNORE" | tr -d '"') - - printInfo "$info" - else - printError "Could not interact with the docker sock, as curl is not installed" - printInstallAdvice "curl" - fi fi } @@ -432,6 +432,7 @@ enumerateContainer() { containerName containerIPs getContainerInformation + containerCapabilities containerServices containerPrivileges containerExploits @@ -546,6 +547,21 @@ getContainerInformation() { printResultLong "Useful tools installed .." "$(echo $tools | tr ' ' '\n')" } +containerCapabilities() { + printQuestion "Dangerous Capabilities .." + if [ -x "$(command -v capsh)" ]; then + if capsh --print| grep -q "$DANGEROUS_CAPABILITIES"; then + caps=$(capsh --print |grep 'cap_' | sed "s/\($DANGEROUS_CAPABILITIES\)/${LG}${EX}&${NC}${DG}/g") + printYes + printStatus "$caps" + else + printNo + fi + else + printError "Unknown (capsh not installed)" + fi +} + containerServices() { # SSHD @@ -572,7 +588,6 @@ containerServices() { } containerPrivileges() { - printQuestion "Privileged Mode ........." if [ -x "$(command -v fdisk)" ]; then if [ "$(fdisk -l 2>/dev/null | wc -l)" -gt 0 ]; then @@ -584,7 +599,6 @@ containerPrivileges() { else printError "Unknown" fi - } containerExploits() { @@ -756,7 +770,7 @@ findInterestingFiles() { printStatus "$boringVars" # Any common entrypoint files etc? - entrypoint=$(ls -lah /entrypoint.sh /deploy 2>/dev/null) + entrypoint=$(ls -lah /*.sh /*entrypoint* /**/entrypoint* /**/*.sh /deploy* 2>/dev/null) printResultLong "Any common entrypoint files ........." "$entrypoint" # Any files in root dir @@ -791,7 +805,7 @@ findInterestingFiles() { printStatus "$hashes" elif test -r /etc/shadow; then # Cannot check... - printFail "No permission" + printFail "No permissions" else printNo fi @@ -809,15 +823,28 @@ findInterestingFiles() { } +checkDockerRootless() { + printQuestion "Rootless ................" + if docker info 2>/dev/null|grep -q rootless; then + printYes + printTip "$TIP_DOCKER_ROOTLESS" + else + printNo + fi +} + getDockerVersion() { printQuestion "Docker Executable ......." if [ "$(command -v docker)" ]; then dockerCommand="$(command -v docker)" dockerVersion="$(docker -v | cut -d',' -f1 | cut -d' ' -f3)" + printSuccess "$dockerCommand" printQuestion "Docker version .........." printSuccess "$dockerVersion" + checkDockerRootless + printQuestion "User in Docker group ...." if groups | grep -q '\bdocker\b'; then printYesEx @@ -832,7 +859,7 @@ getDockerVersion() { checkDockerVersionExploits() { # Check version for known exploits - printResult "Docker Exploits ........." "$dockerVersion" "Version Unknown" + printResult "Docker Version .........." "$dockerVersion" "Version Unknown" if ! [ "$dockerVersion" ]; then return fi @@ -950,6 +977,8 @@ exploitDocker() { exit fi + checkDockerRootless + prepareExploit printQuestion "Exploiting" nl diff --git a/fileserver.py b/fileserver.py index b19e542..d95a2ab 100755 --- a/fileserver.py +++ b/fileserver.py @@ -2,12 +2,13 @@ from hackingscripts import util from http.server import BaseHTTPRequestHandler, HTTPServer +from . import xss_handler import threading import requests import sys import os import ssl -import xss_handler +# import xss_handler class FileServerRequestHandler(BaseHTTPRequestHandler): diff --git a/genRevShell.py b/genRevShell.py index 1681b79..bd6799c 100755 --- a/genRevShell.py +++ b/genRevShell.py @@ -2,7 +2,7 @@ import socket import sys -import util +from . import util import pty def generatePayload(type, local_address, port): diff --git a/web_service_finder.py b/web_service_finder.py index 3e80b74..0e59da9 100755 --- a/web_service_finder.py +++ b/web_service_finder.py @@ -153,7 +153,6 @@ class WebServiceFinder: if generator.has_attr("version"): print("[+] Found XML Generator version:", generator["version"]) - def analyseHtml(self, res): soup = BeautifulSoup(res.text, "html.parser") @@ -177,6 +176,14 @@ class WebServiceFinder: self.printMatch("Gogs", gogs_pattern.search(content), 2) self.printMatch("Go", go_pattern.search(content), 2) + versionInfo = soup.find("div", {"class": "versionInfo"}) + if versionInfo: + content = versionInfo.text.strip() + + cacti_pattern = re.compile(r"Version ([0-9.]*) .* The Cacti Group") + self.printMatch("Cacti", cacti_pattern.search(content), 1) + + moodle_pattern_1 = re.compile(r"^https://download.moodle.org/mobile\?version=(\d+)(&|$)") moodle_pattern_2 = re.compile(r"^https://docs.moodle.org/(\d+)/") litecart_pattern = re.compile(r"^https://www.litecart.net")