kube-hunter: Complete Guide to Kubernetes Security Assessment and Cluster Penetration Testing Using Kali Linux

kube-hunter: Complete Guide to Kubernetes Security Assessment and Cluster Penetration Testing Using Kali Linux

kube-hunter, developed by Aqua Security, is an active penetration-testing tool that hunts for security weaknesses in Kubernetes clusters the way a real attacker would. Rather than statically checking configuration files (like kube-bench does), kube-hunter actively probes network services, APIs, and exposed ports to discover exploitable vulnerabilities — things like an anonymously accessible Kubelet API, an exposed etcd port without authentication, a Dashboard exposed without RBAC, or a container that can access the cloud metadata API to steal IAM credentials.

kube-hunter can run in three main modes:

Findings are categorized by “hunter” modules (e.g. Access Kubelet API, Etcd Remote Access, Dashboard Exposed, Cloud metadata API) and severity, and each finding is mapped to a specific attack vector with a public vulnerability description (khv code) explaining the exploitation path.

Installation

Method 1 – pip (Python package, most common on Kali):

sudo apt-get update
sudo apt-get install python3-pip -y
pip3 install kube-hunter --break-system-packages

Method 2 – Docker container:

docker pull aquasec/kube-hunter
docker run --rm -it aquasec/kube-hunter --remote SOME_IP

Method 3 – Clone from source:

git clone https://github.com/aquasecurity/kube-hunter.git
cd kube-hunter
pip3 install -r requirements.txt --break-system-packages
python3 kube_hunter/__main__.py --help

Verify installation:

kube-hunter --help

Expected output:

usage: kube-hunter [-h] [--list] [--interface] [--pod] [--quick]
                    [--cidr CIDR] [--remote REMOTE [REMOTE ...]] ...
Kube-Hunter: hunts for security weaknesses in Kubernetes clusters

Syntax

kube-hunter [OPTIONS]

At least one scanning scope flag is required: --remote, --cidr, --interface, or --pod (internal/active scan).

Command-Line Options

FlagDescription
--remote REMOTE [REMOTE ...]Scan specific remote IP(s)/hostname(s)
--cidr CIDRScan a CIDR range (e.g. 10.0.0.0/24)
--interfaceAuto-scan all interfaces on the local machine
--podRun as if inside a pod, discovering cluster components from within
--activeEnable active hunters that attempt exploitation (not just discovery)
--quickScan only the main, most common ports, skipping less common ones
--include-patched-versionsDon’t skip vulnerabilities on patched-version software
--mappingOnly map cluster nodes/services, no vulnerability hunting
--report {plain,yaml,json}Set output report format
--dispatch {stdout,http}Where to send the report
--log LOG_LEVELLogging level: DEBUG, INFO, WARNING
--statisticsInclude hunter statistics in report
--network-timeoutSet network timeout for probes
-h, --helpShow help
--listList all available hunter modules and exit
-x, --exclude-namespacesExclude given namespaces during pod-scope hunts

Basic Usage

kube-hunter --remote 192.168.1.50

Expected output:

~ Started
~ Discovering Open Kubernetes Services...
+-------------------+------------------+-------------+
| SERVICE           | LOCATION         | DESCRIPTION |
+-------------------+------------------+-------------+
| Kubelet API       | 192.168.1.50:10250 | The Kubelet is the main... |
+-------------------+------------------+-------------+

~ Hunting for vulnerabilities...
+----------------------+-------------------+----------+-------------------------------+
| ID                   | LOCATION          | CATEGORY | VULNERABILITY                |
+----------------------+-------------------+----------+-------------------------------+
| KHV005               | 192.168.1.50:10250| Access Risk | Exposed Kubelet API allows anonymous access |
+----------------------+-------------------+----------+-------------------------------+

Nodes
+----------------+----------------+
| TYPE           | LOCATION       |
+----------------+----------------+
| Node/Master    | 192.168.1.50   |
+----------------+----------------+

Practical Examples with Output

Example 1 – Quick scan against a single node (common ports only):

kube-hunter --remote 192.168.1.50 --quick
~ Started (quick scan mode - common ports only)
~ Discovering Open Kubernetes Services...
+------------+---------------------+
| SERVICE    | LOCATION            |
+------------+---------------------+
| API Server | 192.168.1.50:6443   |
+------------+---------------------+

Example 2 – Scan an entire subnet for clusters:

kube-hunter --cidr 192.168.1.0/24
~ Started
~ Scanning CIDR 192.168.1.0/24 ...
+-------------------+---------------------+
| SERVICE           | LOCATION            |
+-------------------+---------------------+
| Kubernetes API    | 192.168.1.50:6443   |
| Kubelet API       | 192.168.1.51:10250  |
+-------------------+---------------------+

Example 3 – Internal pod-based scan with active exploitation attempts:

kubectl run kube-hunter --rm -ti --image=aquasec/kube-hunter -- --pod --active
~ Started in pod mode, discovering cluster from within
~ Found open service: Kubelet API 10.0.1.5:10250
~ Attempting active hunter: Kubelet Command Execution
+--------+-------------------+----------+---------------------------------------+
| ID     | LOCATION          | CATEGORY | VULNERABILITY                          |
+--------+-------------------+----------+---------------------------------------+
| KHV002 | 10.0.1.5:10250    | Remote Code Execution | Kubelet exposes execution API |
+--------+-------------------+----------+---------------------------------------+

Example 4 – Output findings as JSON:

kube-hunter --remote 192.168.1.50 --report json --dispatch stdout > findings.json
cat findings.json | python3 -m json.tool | head -20
{
    "nodes": [
        {"type": "Node/Master", "location": "192.168.1.50"}
    ],
    "services": [
        {"service": "Kubelet API", "location": "192.168.1.50:10250"}
    ],
    "vulnerabilities": [
        {
            "id": "KHV005",
            "location": "192.168.1.50:10250",
            "vid": "None",
            "category": "Access Risk",
            "severity": "medium",
            "vulnerability": "Anonymous authentication is enabled"
        }
    ]
}

Example 5 – List all available hunter modules:

kube-hunter --list
Discovery Hunters:
  - ApiServiceDiscovery
  - KubectlClientDiscovery
  - KubeletDiscovery
Hunting Hunters:
  - AccessApiServer
  - AccessKubeletApi
  - EtcdRemoteAccess
  - DashboardExposer
  - CloudMetadataApi
  - PrivilegeEscalation

Example 6 – YAML report to a file:

kube-hunter --remote 192.168.1.50 --report yaml --dispatch stdout > report.yaml
cat report.yaml
nodes:
- type: Node/Master
  location: 192.168.1.50
services:
- service: Kubelet API
  location: 192.168.1.50:10250
vulnerabilities:
- id: KHV005
  location: 192.168.1.50:10250
  category: Access Risk
  severity: medium
  vulnerability: Anonymous authentication is enabled

Example 7 – Scan the local network interface (attacker on the same LAN):

sudo kube-hunter --interface
~ Started, scanning all local network interfaces
~ Discovered network 192.168.1.0/24 on eth0
+-------------------+---------------------+
| SERVICE           | LOCATION            |
+-------------------+---------------------+
| Kubernetes API    | 192.168.1.50:6443   |
+-------------------+---------------------+

Example 8 – Enable debug logging for troubleshooting a scan:

kube-hunter --remote 192.168.1.50 --log DEBUG
[DEBUG] Sending probe to 192.168.1.50:443
[DEBUG] Sending probe to 192.168.1.50:6443
[DEBUG] Response received: HTTP 401 Unauthorized
~ Discovering Open Kubernetes Services...

Common Use Cases

Automation with Bash

#!/usr/bin/env bash
# kube-hunter-scan.sh - Automated remote scan with JSON archiving and alerting
set -euo pipefail

TARGET="$1"
OUTFILE="kube-hunter-$(date +%F-%H%M).json"

echo "[*] Running kube-hunter against $TARGET ..."
kube-hunter --remote "$TARGET" --report json --dispatch stdout --log WARNING > "$OUTFILE"

CRITICAL_COUNT=$(python3 -c "
import json
data = json.load(open('$OUTFILE'))
vulns = data.get('vulnerabilities', [])
print(sum(1 for v in vulns if v.get('severity') in ('high', 'critical')))
")

echo "[*] High/Critical findings: $CRITICAL_COUNT"

if [ "$CRITICAL_COUNT" -gt 0 ]; then
  echo "[!] Critical exposure detected! Review $OUTFILE immediately."
  exit 1
fi

echo "[+] No critical exposures found."

Run it:

chmod +x kube-hunter-scan.sh
./kube-hunter-scan.sh 192.168.1.50

Tips and Best Practices

Troubleshooting

ProblemCauseFix
No services discovered on a known clusterFirewall/NetworkPolicy blocking probesConfirm network path with nc/nmap first, or run in --pod mode from inside the cluster
ModuleNotFoundError on pip installMissing dependencyReinstall with pip3 install -r requirements.txt --break-system-packages
Scan is very slowFull port scan on large CIDRUse --quick or narrow the --cidr range
--active hunters don’t runActive hunters not enabled by defaultExplicitly pass --active
Permission denied on --interfaceRequires raw socket accessRun with sudo

References

Exit mobile version