mirror of
https://github.com/aquasecurity/kube-hunter.git
synced 2026-03-01 17:20:30 +00:00
Compare commits
2 Commits
fixed-kube
...
lizrice-pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2882af39a6 | ||
|
|
3c59dd486f |
@@ -118,13 +118,15 @@ You can run kube-hunter directly on your machine.
|
||||
|
||||
You will need the following installed:
|
||||
* python 3.x
|
||||
* pip
|
||||
* pip3
|
||||
|
||||
Note: These instructions assume `pip3` - please substitute with `pip` if that is the executable name on your system.
|
||||
|
||||
##### Install with pip
|
||||
|
||||
Install:
|
||||
~~~
|
||||
pip install kube-hunter
|
||||
pip3 install kube-hunter
|
||||
~~~
|
||||
|
||||
Run:
|
||||
@@ -141,7 +143,7 @@ git clone https://github.com/aquasecurity/kube-hunter.git
|
||||
Install module dependencies. (You may prefer to do this within a [Virtual Environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/))
|
||||
~~~
|
||||
cd ./kube-hunter
|
||||
pip install -r requirements.txt
|
||||
pip3 install -r requirements.txt
|
||||
~~~
|
||||
|
||||
Run:
|
||||
|
||||
@@ -8,11 +8,7 @@ from kube_hunter.conf import Config, set_config
|
||||
from kube_hunter.conf.parser import parse_args
|
||||
from kube_hunter.conf.logging import setup_logger
|
||||
|
||||
from kube_hunter.plugins import initialize_plugin_manager
|
||||
|
||||
pm = initialize_plugin_manager()
|
||||
# Using a plugin hook for adding arguments before parsing
|
||||
args = parse_args(add_args_hook=pm.hook.parser_add_arguments)
|
||||
args = parse_args()
|
||||
config = Config(
|
||||
active=args.active,
|
||||
cidr=args.cidr,
|
||||
@@ -28,9 +24,6 @@ config = Config(
|
||||
setup_logger(args.log)
|
||||
set_config(config)
|
||||
|
||||
# Running all other registered plugins before execution
|
||||
pm.hook.load_plugin(args=args)
|
||||
|
||||
from kube_hunter.core.events import handler
|
||||
from kube_hunter.core.events.types import HuntFinished, HuntStarted
|
||||
from kube_hunter.modules.discovery.hosts import RunningAsPodEvent, HostScanEvent
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
from argparse import ArgumentParser
|
||||
from kube_hunter.plugins import hookimpl
|
||||
|
||||
|
||||
@hookimpl
|
||||
def parser_add_arguments(parser):
|
||||
"""
|
||||
This is the default hook implementation for parse_add_argument
|
||||
Contains initialization for all default arguments
|
||||
"""
|
||||
def parse_args():
|
||||
parser = ArgumentParser(description="kube-hunter - hunt for security weaknesses in Kubernetes clusters")
|
||||
|
||||
parser.add_argument(
|
||||
"--list", action="store_true", help="Displays all tests in kubehunter (add --active flag to see active tests)",
|
||||
)
|
||||
@@ -63,18 +59,6 @@ def parser_add_arguments(parser):
|
||||
|
||||
parser.add_argument("--network-timeout", type=float, default=5.0, help="network operations timeout")
|
||||
|
||||
|
||||
def parse_args(add_args_hook):
|
||||
"""
|
||||
Function handles all argument parsing
|
||||
|
||||
@param add_arguments: hook for adding arguments to it's given ArgumentParser parameter
|
||||
@return: parsed arguments dict
|
||||
"""
|
||||
parser = ArgumentParser(description="kube-hunter - hunt for security weaknesses in Kubernetes clusters")
|
||||
# adding all arguments to the parser
|
||||
add_args_hook(parser=parser)
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.cidr:
|
||||
args.cidr = args.cidr.replace(" ", "").split(",")
|
||||
|
||||
@@ -148,7 +148,7 @@ class NewHostEvent(Event):
|
||||
).json()
|
||||
return result["cloud"] or "NoCloud"
|
||||
except requests.ConnectionError:
|
||||
logger.info("Failed to connect cloud type service", exc_info=True)
|
||||
logger.info(f"Failed to connect cloud type service", exc_info=True)
|
||||
except Exception:
|
||||
logger.warning(f"Unable to check cloud of {self.host}", exc_info=True)
|
||||
return "NoCloud"
|
||||
|
||||
@@ -55,7 +55,7 @@ class ArpSpoofHunter(ActiveHunter):
|
||||
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,
|
||||
Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op=1, pdst=f"{self_ip}/24"), timeout=config.netork_timeout, verbose=0,
|
||||
)
|
||||
|
||||
# arp enabled on cluster and more than one pod on node
|
||||
|
||||
@@ -8,7 +8,7 @@ from kube_hunter.core.events import handler
|
||||
from kube_hunter.core.events.types import Vulnerability, Event, Service
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
email_pattern = re.compile(rb"([a-z0-9]+@[a-z0-9]+\.[a-z0-9]+)")
|
||||
email_pattern = re.compile(r"([a-z0-9]+@[a-z0-9]+\.[a-z0-9]+)")
|
||||
|
||||
|
||||
class CertificateEmail(Vulnerability, Event):
|
||||
@@ -39,11 +39,8 @@ class CertificateDiscovery(Hunter):
|
||||
except ssl.SSLError:
|
||||
# If the server doesn't offer SSL on this port we won't get a certificate
|
||||
return
|
||||
self.examine_certificate(cert)
|
||||
|
||||
def examine_certificate(self, cert):
|
||||
c = cert.strip(ssl.PEM_HEADER).strip(ssl.PEM_FOOTER)
|
||||
certdata = base64.b64decode(c)
|
||||
certdata = base64.decodebytes(c)
|
||||
emails = re.findall(email_pattern, certdata)
|
||||
for email in emails:
|
||||
self.publish_event(CertificateEmail(email=email))
|
||||
|
||||
@@ -244,7 +244,7 @@ class SecureKubeletPortHunter(Hunter):
|
||||
""" all methods will return the handler name if successful """
|
||||
|
||||
def __init__(self, path, pod, session=None):
|
||||
self.path = path + '/' if not path.endswith('/') else ''
|
||||
self.path = path
|
||||
self.session = session if session else requests.Session()
|
||||
self.pod = pod
|
||||
|
||||
@@ -349,7 +349,7 @@ class SecureKubeletPortHunter(Hunter):
|
||||
# self.session.cert = self.event.client_cert
|
||||
# copy session to event
|
||||
self.event.session = self.session
|
||||
self.path = f"https://{self.event.host}:10250"
|
||||
self.path = "https://{self.event.host}:10250"
|
||||
self.kubehunter_pod = {
|
||||
"name": "kube-hunter",
|
||||
"namespace": "default",
|
||||
@@ -425,7 +425,7 @@ class SecureKubeletPortHunter(Hunter):
|
||||
pod_data = next(filter(is_kubesystem_pod, pods_data), None)
|
||||
|
||||
if pod_data:
|
||||
container_data = pod_data["spec"]["containers"][0]
|
||||
container_data = next(pod_data["spec"]["containers"], None)
|
||||
if container_data:
|
||||
return {
|
||||
"name": pod_data["metadata"]["name"],
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import pluggy
|
||||
|
||||
from kube_hunter.plugins import hookspecs
|
||||
|
||||
hookimpl = pluggy.HookimplMarker("kube-hunter")
|
||||
|
||||
|
||||
def initialize_plugin_manager():
|
||||
"""
|
||||
Initializes and loads all default and setup implementations for registered plugins
|
||||
|
||||
@return: initialized plugin manager
|
||||
"""
|
||||
pm = pluggy.PluginManager("kube-hunter")
|
||||
pm.add_hookspecs(hookspecs)
|
||||
pm.load_setuptools_entrypoints("kube_hunter")
|
||||
|
||||
# default registration of builtin implemented plugins
|
||||
from kube_hunter.conf import parser
|
||||
|
||||
pm.register(parser)
|
||||
|
||||
return pm
|
||||
@@ -1,24 +0,0 @@
|
||||
import pluggy
|
||||
from argparse import ArgumentParser
|
||||
|
||||
hookspec = pluggy.HookspecMarker("kube-hunter")
|
||||
|
||||
|
||||
@hookspec
|
||||
def parser_add_arguments(parser: ArgumentParser):
|
||||
"""Add arguments to the ArgumentParser.
|
||||
|
||||
If a plugin requires an aditional argument, it should implement this hook
|
||||
and add the argument to the Argument Parser
|
||||
|
||||
@param parser: an ArgumentParser, calls parser.add_argument on it
|
||||
"""
|
||||
|
||||
|
||||
@hookspec
|
||||
def load_plugin(args):
|
||||
"""Plugins that wish to execute code after the argument parsing
|
||||
should implement this hook.
|
||||
|
||||
@param args: all parsed arguments passed to kube-hunter
|
||||
"""
|
||||
@@ -14,4 +14,3 @@ black
|
||||
pre-commit
|
||||
flake8-bugbear
|
||||
flake8-mypy
|
||||
pluggy
|
||||
|
||||
@@ -38,7 +38,6 @@ install_requires =
|
||||
future
|
||||
packaging
|
||||
dataclasses
|
||||
pluggy
|
||||
setup_requires =
|
||||
setuptools>=30.3.0
|
||||
setuptools_scm
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# flake8: noqa: E402
|
||||
from kube_hunter.conf import Config, set_config
|
||||
|
||||
set_config(Config())
|
||||
|
||||
from kube_hunter.core.events.types import Event
|
||||
from kube_hunter.modules.hunting.certificates import CertificateDiscovery, CertificateEmail
|
||||
from kube_hunter.core.events import handler
|
||||
|
||||
|
||||
def test_CertificateDiscovery():
|
||||
cert = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDZDCCAkwCCQCAzfCLqrJvuTANBgkqhkiG9w0BAQsFADB0MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECAwCQ0ExEDAOBgNVBAoMB05vZGUuanMxETAPBgNVBAsMCG5vZGUt
|
||||
Z3lwMRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEGJ1aWxkQG5v
|
||||
ZGVqcy5vcmcwHhcNMTkwNjIyMDYyMjMzWhcNMjIwNDExMDYyMjMzWjB0MQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECAwCQ0ExEDAOBgNVBAoMB05vZGUuanMxETAPBgNVBAsM
|
||||
CG5vZGUtZ3lwMRIwEAYDVQQDDAlsb2NhbGhvc3QxHzAdBgkqhkiG9w0BCQEWEGJ1
|
||||
aWxkQG5vZGVqcy5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS
|
||||
CHjvtVW4HdbbUwZ/ZV9s6U4x0KSoyNQrsCZjB8kRpFPe50DS5mfmu2SNBGYKRgzk
|
||||
4QEEwFB9N2o8YTWsCefSRl6ti4ToPZqulU4hhRKYrEGtMJcRzi3IN7s200JaO3UH
|
||||
01Su8ruO0NESb5zEU1Ykfh8Lub8TGEAINmgI61d/5d5Aq3kDjUHQJt1Ekw03Ylnu
|
||||
juQyCGZxLxnngu0mIvwzyL/UeeUgsfQLzvppUk6In7tC1zzMjSPWo0c8qu6KvrW4
|
||||
bKYnkZkzdQifzbpO5ERMEsh5HWq0uHa6+dgcVHFvlhdqF4Uat87ygNplVf0txsZB
|
||||
MNVqbz1k6xkZYMnzDoydAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADspZGtKpWxy
|
||||
J1W3FA1aeQhMvequQTcMRz4avkm4K4HfTdV1iVD4CbvdezBphouBlyLVLDFJP7RZ
|
||||
m7dBJVgBwnxufoFLne8cR2MGqDRoySbFT1AtDJdxabE6Fg+QGUpgOQfeBJ6ANlSB
|
||||
+qJ+HG4QA+Ouh5hxz9mgYwkIsMUABHiwENdZ/kT8Edw4xKgd3uH0YP4iiePMD66c
|
||||
rzW3uXH5J1jnKgBlpxtog4P6dHCcoq+PZJ17W5bdXNyqC1LPzQqniZ2BNcEZ4ix3
|
||||
slAZAOWD1zLLGJhBPMV1fa0sHNBWc6oicr3YK/IDb0cp9kiLvnUu1pHy+LWQGqtC
|
||||
rceJuGsnJEQ=
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
||||
c = CertificateDiscovery(Event())
|
||||
c.examine_certificate(cert)
|
||||
|
||||
|
||||
@handler.subscribe(CertificateEmail)
|
||||
class test_CertificateEmail(object):
|
||||
def __init__(self, event):
|
||||
assert event.email == b"build@nodejs.org0"
|
||||
@@ -1,13 +0,0 @@
|
||||
from kube_hunter.plugins import hookimpl
|
||||
|
||||
return_string = "return_string"
|
||||
|
||||
|
||||
@hookimpl
|
||||
def parser_add_arguments(parser):
|
||||
return return_string
|
||||
|
||||
|
||||
@hookimpl
|
||||
def load_plugin(args):
|
||||
return return_string
|
||||
@@ -1,17 +0,0 @@
|
||||
from argparse import ArgumentParser
|
||||
from tests.plugins import test_hooks
|
||||
from kube_hunter.plugins import initialize_plugin_manager
|
||||
|
||||
|
||||
def test_all_plugin_hooks():
|
||||
pm = initialize_plugin_manager()
|
||||
pm.register(test_hooks)
|
||||
|
||||
# Testing parser_add_arguments
|
||||
parser = ArgumentParser("Test Argument Parser")
|
||||
results = pm.hook.parser_add_arguments(parser=parser)
|
||||
assert test_hooks.return_string in results
|
||||
|
||||
# Testing load_plugin
|
||||
results = pm.hook.load_plugin(args=[])
|
||||
assert test_hooks.return_string in results
|
||||
Reference in New Issue
Block a user