deepce, web_service_finder: cacti, small fixes

This commit is contained in:
Roman Hergenreder 2021-05-03 13:00:48 +02:00
parent 7cd75f1022
commit c3212ad115
4 changed files with 79 additions and 42 deletions

107
deepce.sh

@ -57,14 +57,14 @@ Usage: ${0##*/} [OPTIONS...]
--install Install useful packages before running script, this will maximise enumeration and exploitation potential --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 ${DG}[Exploits]$NC
-e, --exploit Use one of the following exploits (eg. -e SOCK) -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 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 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 SOCK use an exposed docker sock to create a new container and mount root partition to priv esc
CVE-2019-5746 CVE-2019-5746
CVE-2019-5021 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_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. 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}" 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_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_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" 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_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" CONTAINER_CMDS="docker lxc rkt kubectl podman"
USEFUL_CMDS="curl wget gcc nc netcat ncat jq nslookup host hostname dig python python2 python3 nmap" 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). # 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=SC2046
# shellcheck disable=SC2183 # word splitting here is on purpose # 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 (---------------# #--------------) Printing (---------------#
@ -272,7 +274,7 @@ installPackages() {
return return
fi 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" printSuccess "Success"
else else
printError "Failed" printError "Failed"
@ -280,13 +282,13 @@ installPackages() {
elif [ -x "$(command -v apk)" ]; then elif [ -x "$(command -v apk)" ]; then
# Alpine # Alpine
apk add bind-tools curl nmap apk add bind-tools curl nmap libcap
elif [ -x "$(command -v yum)" ]; then elif [ -x "$(command -v yum)" ]; then
# CentOS / Fedora # CentOS / Fedora
yum install bind-utils curl nmap yum install bind-utils curl nmap libcap
elif [ -x "$(command -v apt-get)" ]; then elif [ -x "$(command -v apt-get)" ]; then
# Old Debian # Old Debian
apt-get install -y dnsutils curl nmap apt-get install -y dnsutils curl nmap inetutils-ping libcap2-bin
fi fi
} }
@ -389,40 +391,38 @@ dockerSockCheck() {
if [ "$dockerSockPath" ]; then if [ "$dockerSockPath" ]; then
printInfo "$(ls -lah $dockerSockPath)" printInfo "$(ls -lah $dockerSockPath)"
nl
# Is docker sock writable # Is docker sock writable
printQuestion "Sock is writable ........" printQuestion "Sock is writable ........"
if test -r "$dockerSockPath"; then if test -r "$dockerSockPath"; then
printYesEx printYesEx
printTip "$TIP_WRITABLE_SOCK" 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 else
printNo printNo
fi 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 fi
} }
@ -432,6 +432,7 @@ enumerateContainer() {
containerName containerName
containerIPs containerIPs
getContainerInformation getContainerInformation
containerCapabilities
containerServices containerServices
containerPrivileges containerPrivileges
containerExploits containerExploits
@ -546,6 +547,21 @@ getContainerInformation() {
printResultLong "Useful tools installed .." "$(echo $tools | tr ' ' '\n')" 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() { containerServices() {
# SSHD # SSHD
@ -572,7 +588,6 @@ containerServices() {
} }
containerPrivileges() { containerPrivileges() {
printQuestion "Privileged Mode ........." printQuestion "Privileged Mode ........."
if [ -x "$(command -v fdisk)" ]; then if [ -x "$(command -v fdisk)" ]; then
if [ "$(fdisk -l 2>/dev/null | wc -l)" -gt 0 ]; then if [ "$(fdisk -l 2>/dev/null | wc -l)" -gt 0 ]; then
@ -584,7 +599,6 @@ containerPrivileges() {
else else
printError "Unknown" printError "Unknown"
fi fi
} }
containerExploits() { containerExploits() {
@ -756,7 +770,7 @@ findInterestingFiles() {
printStatus "$boringVars" printStatus "$boringVars"
# Any common entrypoint files etc? # 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" printResultLong "Any common entrypoint files ........." "$entrypoint"
# Any files in root dir # Any files in root dir
@ -791,7 +805,7 @@ findInterestingFiles() {
printStatus "$hashes" printStatus "$hashes"
elif test -r /etc/shadow; then elif test -r /etc/shadow; then
# Cannot check... # Cannot check...
printFail "No permission" printFail "No permissions"
else else
printNo printNo
fi 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() { getDockerVersion() {
printQuestion "Docker Executable ......." printQuestion "Docker Executable ......."
if [ "$(command -v docker)" ]; then if [ "$(command -v docker)" ]; then
dockerCommand="$(command -v docker)" dockerCommand="$(command -v docker)"
dockerVersion="$(docker -v | cut -d',' -f1 | cut -d' ' -f3)" dockerVersion="$(docker -v | cut -d',' -f1 | cut -d' ' -f3)"
printSuccess "$dockerCommand" printSuccess "$dockerCommand"
printQuestion "Docker version .........." printQuestion "Docker version .........."
printSuccess "$dockerVersion" printSuccess "$dockerVersion"
checkDockerRootless
printQuestion "User in Docker group ...." printQuestion "User in Docker group ...."
if groups | grep -q '\bdocker\b'; then if groups | grep -q '\bdocker\b'; then
printYesEx printYesEx
@ -832,7 +859,7 @@ getDockerVersion() {
checkDockerVersionExploits() { checkDockerVersionExploits() {
# Check version for known exploits # Check version for known exploits
printResult "Docker Exploits ........." "$dockerVersion" "Version Unknown" printResult "Docker Version .........." "$dockerVersion" "Version Unknown"
if ! [ "$dockerVersion" ]; then if ! [ "$dockerVersion" ]; then
return return
fi fi
@ -950,6 +977,8 @@ exploitDocker() {
exit exit
fi fi
checkDockerRootless
prepareExploit prepareExploit
printQuestion "Exploiting" printQuestion "Exploiting"
nl nl

@ -2,12 +2,13 @@
from hackingscripts import util from hackingscripts import util
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from . import xss_handler
import threading import threading
import requests import requests
import sys import sys
import os import os
import ssl import ssl
import xss_handler # import xss_handler
class FileServerRequestHandler(BaseHTTPRequestHandler): class FileServerRequestHandler(BaseHTTPRequestHandler):

@ -2,7 +2,7 @@
import socket import socket
import sys import sys
import util from . import util
import pty import pty
def generatePayload(type, local_address, port): def generatePayload(type, local_address, port):

@ -153,7 +153,6 @@ class WebServiceFinder:
if generator.has_attr("version"): if generator.has_attr("version"):
print("[+] Found XML Generator version:", generator["version"]) print("[+] Found XML Generator version:", generator["version"])
def analyseHtml(self, res): def analyseHtml(self, res):
soup = BeautifulSoup(res.text, "html.parser") soup = BeautifulSoup(res.text, "html.parser")
@ -177,6 +176,14 @@ class WebServiceFinder:
self.printMatch("Gogs", gogs_pattern.search(content), 2) self.printMatch("Gogs", gogs_pattern.search(content), 2)
self.printMatch("Go", go_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_1 = re.compile(r"^https://download.moodle.org/mobile\?version=(\d+)(&|$)")
moodle_pattern_2 = re.compile(r"^https://docs.moodle.org/(\d+)/") moodle_pattern_2 = re.compile(r"^https://docs.moodle.org/(\d+)/")
litecart_pattern = re.compile(r"^https://www.litecart.net") litecart_pattern = re.compile(r"^https://www.litecart.net")