Compare commits

...

7 Commits

Author SHA1 Message Date
Daniel Sagi
b08a86b104 Merge branch 'remove_scapy_usage' of https://github.com/aquasecurity/kube-hunter into remove_scapy_usage 2022-05-07 09:06:34 +03:00
Daniel Sagi
5bed4ca722 ignore B020 flake8 2022-05-07 09:05:42 +03:00
danielsagi
915d2bff8a added explicit new version to plugins in dockerfile installation 2022-05-06 22:47:01 -07:00
Daniel Sagi
8146810d44 added installation of default plugins to Dockerfile 2022-05-07 06:49:25 +03:00
Daniel Sagi
c54859ec37 removed arp and dns hunters usage due to it's violations of the scapy GPL2 license 2022-04-01 19:12:01 +03:00
Owen Rumney
e1896f3983 docs: lowercase the severities for AVD (#495)
Signed-off-by: Owen Rumney <owen@owenrumney.co.uk>
2022-03-25 09:03:43 +00:00
jerbia
fc7fbbf1fc Added severity to the kube-hunter found issues (#492) 2022-03-22 11:03:05 +02:00
46 changed files with 44 additions and 174 deletions

View File

@@ -1,5 +1,5 @@
[flake8]
ignore = E203, E266, E501, W503, B903, T499
ignore = E203, E266, E501, W503, B903, T499, B020
max-line-length = 120
max-complexity = 18
select = B,C,E,F,W,B9,T4

View File

@@ -26,4 +26,7 @@ RUN apk add --no-cache \
COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
COPY --from=builder /usr/local/bin/kube-hunter /usr/local/bin/kube-hunter
# Add default plugins: https://github.com/aquasecurity/kube-hunter-plugins
RUN pip install kube-hunter-arp-spoof>=0.0.3 kube-hunter-dns-spoof>=0.0.3
ENTRYPOINT ["kube-hunter"]

View File

@@ -2,6 +2,7 @@
vid: KHV002
title: Kubernetes version disclosure
categories: [Information Disclosure]
severity: low
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV003
title: Azure Metadata Exposure
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV004
title: Azure SPN Exposure
categories: [Identity Theft]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV005
title: Access to Kubernetes API
categories: [Information Disclosure, Unauthenticated Access]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV006
title: Insecure (HTTP) access to Kubernetes API
categories: [Unauthenticated Access]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV007
title: Specific Access to Kubernetes API
categories: [Access Risk]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV020
title: Possible Arp Spoof
categories: [IdentityTheft]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV021
title: Certificate Includes Email Address
categories: [Information Disclosure]
severity: low
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV022
title: Critical Privilege Escalation CVE
categories: [Privilege Escalation]
severity: critical
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV023
title: Denial of Service to Kubernetes API Server
categories: [Denial Of Service]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV024
title: Possible Ping Flood Attack
categories: [Denial Of Service]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV025
title: Possible Reset Flood Attack
categories: [Denial Of Service]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV026
title: Arbitrary Access To Cluster Scoped Resources
categories: [PrivilegeEscalation]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV027
title: Kubectl Vulnerable To CVE-2019-11246
categories: [Remote Code Execution]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV028
title: Kubectl Vulnerable To CVE-2019-1002101
categories: [Remote Code Execution]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV029
title: Dashboard Exposed
categories: [Remote Code Execution]
severity: critical
---
# {{ page.vid }} - {{ page.title }}
@@ -12,4 +13,5 @@ An open Kubernetes Dashboard was detected. The Kubernetes Dashboard can be used
## Remediation
Do not leave the Dashboard insecured.
Do not leave the Dashboard insecured.

View File

@@ -2,6 +2,7 @@
vid: KHV030
title: Possible DNS Spoof
categories: [Identity Theft]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV031
title: Etcd Remote Write Access Event
categories: [Remote Code Execution]
severity: critical
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV032
title: Etcd Remote Read Access Event
categories: [Access Risk]
severity: critical
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV033
title: Etcd Remote version disclosure
categories: [Information Disclosure]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV034
title: Etcd is accessible using insecure connection (HTTP)
categories: [Unauthenticated Access]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV036
title: Anonymous Authentication
categories: [Remote Code Execution]
severity: critical
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV037
title: Exposed Container Logs
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV038
title: Exposed Running Pods
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV039
title: Exposed Exec On Container
categories: [Remote Code Execution]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV040
title: Exposed Run Inside Container
categories: [Remote Code Execution]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV041
title: Exposed Port Forward
categories: [Remote Code Execution]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV042
title: Exposed Attaching To Container
categories: [Remote Code Execution]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV043
title: Cluster Health Disclosure
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV044
title: Privileged Container
categories: [Access Risk]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV045
title: Exposed System Logs
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV046
title: Exposed Kubelet Cmdline
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV047
title: Pod With Mount To /var/log
categories: [Privilege Escalation]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV049
title: kubectl proxy Exposed
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV050
title: Read access to Pod service account token
categories: [Access Risk]
severity: medium
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV051
title: Exposed Existing Privileged Containers Via Secure Kubelet Port
categories: [Access Risk]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV052
title: Exposed Pods
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -2,6 +2,7 @@
vid: KHV053
title: AWS Metadata Exposure
categories: [Information Disclosure]
severity: high
---
# {{ page.vid }} - {{ page.title }}

View File

@@ -4,10 +4,6 @@ DEFAULT_LEVEL = logging.INFO
DEFAULT_LEVEL_NAME = logging.getLevelName(DEFAULT_LEVEL)
LOG_FORMAT = "%(asctime)s %(levelname)s %(name)s %(message)s"
# Suppress logging from scapy
logging.getLogger("scapy.runtime").setLevel(logging.CRITICAL)
logging.getLogger("scapy.loading").setLevel(logging.CRITICAL)
def setup_logger(level_name, logfile):
# Remove any existing handlers

View File

@@ -2,12 +2,10 @@
from . import (
aks,
apiserver,
arp,
capabilities,
certificates,
cves,
dashboard,
dns,
etcd,
kubelet,
mounts,

View File

@@ -1,71 +0,0 @@
import logging
from scapy.all import ARP, IP, ICMP, Ether, sr1, srp
from kube_hunter.conf import get_config
from kube_hunter.core.events import handler
from kube_hunter.core.events.types import Event, Vulnerability
from kube_hunter.core.types import ActiveHunter, KubernetesCluster, ARPPoisoningTechnique
from kube_hunter.modules.hunting.capabilities import CapNetRawEnabled
logger = logging.getLogger(__name__)
class PossibleArpSpoofing(Vulnerability, Event):
"""A malicious pod running on the cluster could potentially run an ARP Spoof attack
and perform a MITM between pods on the node."""
def __init__(self):
Vulnerability.__init__(
self,
KubernetesCluster,
"Possible Arp Spoof",
category=ARPPoisoningTechnique,
vid="KHV020",
)
@handler.subscribe(CapNetRawEnabled)
class ArpSpoofHunter(ActiveHunter):
"""Arp Spoof Hunter
Checks for the possibility of running an ARP spoof
attack from within a pod (results are based on the running node)
"""
def __init__(self, event):
self.event = event
def try_getting_mac(self, ip):
config = get_config()
ans = sr1(ARP(op=1, pdst=ip), timeout=config.network_timeout, verbose=0)
return ans[ARP].hwsrc if ans else None
def detect_l3_on_host(self, arp_responses):
"""returns True for an existence of an L3 network plugin"""
logger.debug("Attempting to detect L3 network plugin using ARP")
unique_macs = list({response[ARP].hwsrc for _, response in arp_responses})
# if LAN addresses not unique
if len(unique_macs) == 1:
# if an ip outside the subnets gets a mac address
outside_mac = self.try_getting_mac("1.1.1.1")
# outside mac is the same as lan macs
if outside_mac == unique_macs[0]:
return True
# only one mac address for whole LAN and outside
return False
def execute(self):
config = get_config()
self_ip = sr1(IP(dst="1.1.1.1", ttl=1) / ICMP(), verbose=0, timeout=config.network_timeout)[IP].dst
arp_responses, _ = srp(
Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op=1, pdst=f"{self_ip}/24"),
timeout=config.network_timeout,
verbose=0,
)
# arp enabled on cluster and more than one pod on node
if len(arp_responses) > 1:
# L3 plugin not installed
if not self.detect_l3_on_host(arp_responses):
self.publish_event(PossibleArpSpoofing())

View File

@@ -1,90 +0,0 @@
import re
import logging
from scapy.all import IP, ICMP, UDP, DNS, DNSQR, ARP, Ether, sr1, srp1, srp
from kube_hunter.conf import get_config
from kube_hunter.core.events import handler
from kube_hunter.core.events.types import Event, Vulnerability
from kube_hunter.core.types import ActiveHunter, KubernetesCluster, CoreDNSPoisoningTechnique
from kube_hunter.modules.hunting.arp import PossibleArpSpoofing
logger = logging.getLogger(__name__)
class PossibleDnsSpoofing(Vulnerability, Event):
"""A malicious pod running on the cluster could potentially run a DNS Spoof attack
and perform a MITM attack on applications running in the cluster."""
def __init__(self, kubedns_pod_ip):
Vulnerability.__init__(
self,
KubernetesCluster,
"Possible DNS Spoof",
category=CoreDNSPoisoningTechnique,
vid="KHV030",
)
self.kubedns_pod_ip = kubedns_pod_ip
self.evidence = f"kube-dns at: {self.kubedns_pod_ip}"
# Only triggered with RunningAsPod base event
@handler.subscribe(PossibleArpSpoofing)
class DnsSpoofHunter(ActiveHunter):
"""DNS Spoof Hunter
Checks for the possibility for a malicious pod to compromise DNS requests of the cluster
(results are based on the running node)
"""
def __init__(self, event):
self.event = event
def get_cbr0_ip_mac(self):
config = get_config()
res = srp1(Ether() / IP(dst="1.1.1.1", ttl=1) / ICMP(), verbose=0, timeout=config.network_timeout)
return res[IP].src, res.src
def extract_nameserver_ip(self):
with open("/etc/resolv.conf") as f:
# finds first nameserver in /etc/resolv.conf
match = re.search(r"nameserver (\d+.\d+.\d+.\d+)", f.read())
if match:
return match.group(1)
def get_kube_dns_ip_mac(self):
config = get_config()
kubedns_svc_ip = self.extract_nameserver_ip()
# getting actual pod ip of kube-dns service, by comparing the src mac of a dns response and arp scanning.
dns_info_res = srp1(
Ether() / IP(dst=kubedns_svc_ip) / UDP(dport=53) / DNS(rd=1, qd=DNSQR()),
verbose=0,
timeout=config.network_timeout,
)
kubedns_pod_mac = dns_info_res.src
self_ip = dns_info_res[IP].dst
arp_responses, _ = srp(
Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op=1, pdst=f"{self_ip}/24"),
timeout=config.network_timeout,
verbose=0,
)
for _, response in arp_responses:
if response[Ether].src == kubedns_pod_mac:
return response[ARP].psrc, response.src
def execute(self):
config = get_config()
logger.debug("Attempting to get kube-dns pod ip")
self_ip = sr1(IP(dst="1.1.1.1", ttl=1) / ICMP(), verbose=0, timeout=config.network_timeout)[IP].dst
cbr0_ip, cbr0_mac = self.get_cbr0_ip_mac()
kubedns = self.get_kube_dns_ip_mac()
if kubedns:
kubedns_ip, kubedns_mac = kubedns
logger.debug(f"ip={self_ip} kubednsip={kubedns_ip} cbr0ip={cbr0_ip}")
if kubedns_mac != cbr0_mac:
# if self pod in the same subnet as kube-dns pod
self.publish_event(PossibleDnsSpoofing(kubedns_pod_ip=kubedns_ip))
else:
logger.debug("Could not get kubedns identity")

View File

@@ -32,7 +32,6 @@ packages = find:
install_requires =
netaddr
netifaces
scapy>=2.4.3
requests
PrettyTable
urllib3>=1.24.3

View File

@@ -20,14 +20,12 @@ from kube_hunter.modules.hunting.apiserver import (
AccessApiServerActive,
AccessApiServerWithToken,
)
from kube_hunter.modules.hunting.arp import ArpSpoofHunter
from kube_hunter.modules.hunting.capabilities import PodCapabilitiesHunter
from kube_hunter.modules.hunting.certificates import CertificateDiscovery
from kube_hunter.modules.hunting.cves import K8sClusterCveHunter
from kube_hunter.modules.hunting.cves import KubectlCVEHunter
from kube_hunter.modules.hunting.dashboard import KubeDashboard
from kube_hunter.modules.hunting.dns import DnsSpoofHunter
from kube_hunter.modules.hunting.etcd import EtcdRemoteAccess, EtcdRemoteAccessActive
from kube_hunter.modules.hunting.kubelet import (
ProveAnonymousAuth,
@@ -76,8 +74,6 @@ PASSIVE_HUNTERS = {
ACTIVE_HUNTERS = {
ProveAzureSpnExposure,
AccessApiServerActive,
ArpSpoofHunter,
DnsSpoofHunter,
EtcdRemoteAccessActive,
ProveRunHandler,
ProveContainerLogsHandler,