Compare commits

...

14 Commits

Author SHA1 Message Date
Daniel Sagi
947e710320 fixed bug in import loop 2022-01-28 18:34:46 +02:00
Daniel Sagi
1db0985c53 changed old name class-names to raw-hunter-names 2022-01-28 18:30:59 +02:00
Daniel Sagi
d05c174d9d added Collector, StartedInfo and SendFullReport to the core_hunters 2022-01-28 18:19:29 +02:00
Daniel Sagi
51b893c7db added documentation in readme for Custom hunting and made Advanced Usage a higher level topic 2022-01-28 18:00:00 +02:00
Daniel Sagi
d6e849544d flake8 formatting 2022-01-27 21:39:08 +02:00
Daniel Sagi
a5e805564d ran black to format 2022-01-27 21:36:41 +02:00
Daniel Sagi
c33c1c2440 changed name from partial to custom 2022-01-27 20:52:43 +02:00
Daniel Sagi
b518429fc4 added partial and partial-names flag. mechanism for whitelisting hunter subscrption for custom hunts 2022-01-27 20:48:46 +02:00
Juvenile
c17aa17096 ignore https certificate verification (#484) 2022-01-22 16:06:39 +02:00
testn
4204879251 Update README.md (#487)
Fix typo
2022-01-22 16:05:20 +02:00
danielsagi
a746bd0eb1 Added correct exception handling for discovery of Metadata apis (#488)
* Added correct exception handling for discovery of Metadata apis

* fixed linting issues
2022-01-22 15:56:04 +02:00
danielsagi
b379e64314 Added MITRE documentation in README (#485)
* Added documentation about differences between vulnerabilities and the attack matrix techniques

* moved docs to start of README, also created MITRE image, showing covered areas of kube-hunter

* fixed link in readme
2022-01-14 00:00:29 +02:00
danielsagi
00eb0dfa87 Switched CVE Hunting to optional & Minor core feature (#482)
* Removed automatic registration of the k8s CVE hunter

* Made CVE hunting optional, default set to not run
2021-10-16 17:49:00 +03:00
danielsagi
8d045fb1a8 Fix all of github action workflows (#481)
* fixed all of workflows
2021-10-16 17:23:41 +03:00
15 changed files with 184 additions and 45 deletions

View File

@@ -77,9 +77,10 @@ jobs:
python-version: '3.9' python-version: '3.9'
- name: Install dependencies - name: Install dependencies
shell: bash
run: | run: |
python -m pip install -U pip pip install -U pip
python -m pip install -r requirements-dev.txt make deps
- name: Build project - name: Build project
shell: bash shell: bash

View File

@@ -10,7 +10,7 @@ name: Release
jobs: jobs:
build: build:
name: Upload Release Asset name: Upload Release Asset
runs-on: ubuntu-16.04 runs-on: ubuntu-18.04
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -18,12 +18,14 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v2 uses: actions/setup-python@v2
with: with:
python-version: '3.9' python-version: '3.8'
- name: Install dependencies - name: Install dependencies
shell: bash
run: | run: |
python -m pip install -U pip pip install -U pip
python -m pip install -r requirements-dev.txt pip install pyinstaller
make deps
- name: Build project - name: Build project
shell: bash shell: bash

View File

@@ -13,7 +13,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["3.6", "3.7", "3.8", "3.9"] python-version: ["3.6", "3.7", "3.8", "3.9"]
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04] os: [ubuntu-20.04, ubuntu-18.04]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -38,11 +38,11 @@ jobs:
${{ matrix.os }}-${{ matrix.python-version }}- ${{ matrix.os }}-${{ matrix.python-version }}-
- name: Install dependencies - name: Install dependencies
shell: bash
run: | run: |
python -m pip install -U pip pip install -U pip
python -m pip install -U wheel make dev-deps
python -m pip install -r requirements.txt make install
python -m pip install -r requirements-dev.txt
- name: Test - name: Test
shell: bash shell: bash

BIN
MITRE.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@@ -31,7 +31,7 @@ lint-check:
.PHONY: test .PHONY: test
test: test:
pytest python -m pytest
.PHONY: build .PHONY: build
build: build:

View File

@@ -18,7 +18,8 @@ kube-hunter hunts for security weaknesses in Kubernetes clusters. The tool was d
**Run kube-hunter**: kube-hunter is available as a container (aquasec/kube-hunter), and we also offer a web site at [kube-hunter.aquasec.com](https://kube-hunter.aquasec.com) where you can register online to receive a token allowing you to see and share the results online. You can also run the Python code yourself as described below. **Run kube-hunter**: kube-hunter is available as a container (aquasec/kube-hunter), and we also offer a web site at [kube-hunter.aquasec.com](https://kube-hunter.aquasec.com) where you can register online to receive a token allowing you to see and share the results online. You can also run the Python code yourself as described below.
**Explore vulnerabilities**: The kube-hunter knowledge base includes articles about discoverable vulnerabilities and issues. When kube-hunter reports an issue, it will show its VID (Vulnerability ID) so you can look it up in the KB at https://aquasecurity.github.io/kube-hunter/ **Explore vulnerabilities**: The kube-hunter knowledge base includes articles about discoverable vulnerabilities and issues. When kube-hunter reports an issue, it will show its VID (Vulnerability ID) so you can look it up in the KB at https://aquasecurity.github.io/kube-hunter/
_If you're interested in kube-hunter's integration with the Kubernetes ATT&CK Matrix [Continue Reading](#kuberentes-attck-matrix)_
**Contribute**: We welcome contributions, especially new hunter modules that perform additional tests. If you would like to develop your modules please read [Guidelines For Developing Your First kube-hunter Module](https://github.com/aquasecurity/kube-hunter/blob/main/CONTRIBUTING.md). **Contribute**: We welcome contributions, especially new hunter modules that perform additional tests. If you would like to develop your modules please read [Guidelines For Developing Your First kube-hunter Module](https://github.com/aquasecurity/kube-hunter/blob/main/CONTRIBUTING.md).
@@ -28,6 +29,7 @@ Table of Contents
================= =================
- [Table of Contents](#table-of-contents) - [Table of Contents](#table-of-contents)
- [Kubernetes ATT&CK Matrix](#kubernetes-attck-matrix)
- [Hunting](#hunting) - [Hunting](#hunting)
- [Where should I run kube-hunter?](#where-should-i-run-kube-hunter) - [Where should I run kube-hunter?](#where-should-i-run-kube-hunter)
- [Scanning options](#scanning-options) - [Scanning options](#scanning-options)
@@ -37,8 +39,9 @@ Table of Contents
- [Nodes Mapping](#nodes-mapping) - [Nodes Mapping](#nodes-mapping)
- [Output](#output) - [Output](#output)
- [Dispatching](#dispatching) - [Dispatching](#dispatching)
- [Advanced Usage](#advanced-usage) - [Advanced Usage](#advanced-usage)
- [Azure Quick Scanning](#azure-quick-scanning) - [Azure Quick Scanning](#azure-quick-scanning)
- [Custom Hunting](#custom-hunting)
- [Deployment](#deployment) - [Deployment](#deployment)
- [On Machine](#on-machine) - [On Machine](#on-machine)
- [Prerequisites](#prerequisites) - [Prerequisites](#prerequisites)
@@ -48,9 +51,21 @@ Table of Contents
- [Pod](#pod) - [Pod](#pod)
- [Contribution](#contribution) - [Contribution](#contribution)
- [License](#license) - [License](#license)
## Hunting
---
## Kubernetes ATT&CK Matrix
kube-hunter now supports the new format of the Kubernetes ATT&CK matrix.
While kube-hunter's vulnerabilities are a collection of creative techniques designed to mimic an attacker in the cluster (or outside it)
The Mitre's ATT&CK defines a more general standardised categories of techniques to do so.
You can think of kube-hunter vulnerabilities as small steps for an attacker, which follows the track of a more general technique he would aim for.
Most of kube-hunter's hunters and vulnerabilities can closly fall under those techniques, That's why we moved to follow the Matrix standard.
_Some kube-hunter vulnerabities which we could not map to Mitre technique, are prefixed with the `General` keyword_
![kube-hunter](./MITRE.png)
## Hunting
### Where should I run kube-hunter? ### Where should I run kube-hunter?
There are three different ways to run kube-hunter, each providing a different approach to detecting weaknesses in your cluster: There are three different ways to run kube-hunter, each providing a different approach to detecting weaknesses in your cluster:
@@ -61,6 +76,7 @@ You can run kube-hunter directly on a machine in the cluster, and select the opt
You can also run kube-hunter in a pod within the cluster. This indicates how exposed your cluster would be if one of your application pods is compromised (through a software vulnerability, for example). (_`--pod` flag_) You can also run kube-hunter in a pod within the cluster. This indicates how exposed your cluster would be if one of your application pods is compromised (through a software vulnerability, for example). (_`--pod` flag_)
### Scanning options ### Scanning options
First check for these **[pre-requisites](#prerequisites)**. First check for these **[pre-requisites](#prerequisites)**.
@@ -141,11 +157,49 @@ Available dispatch methods are:
* KUBEHUNTER_HTTP_DISPATCH_URL (defaults to: https://localhost) * KUBEHUNTER_HTTP_DISPATCH_URL (defaults to: https://localhost)
* KUBEHUNTER_HTTP_DISPATCH_METHOD (defaults to: POST) * KUBEHUNTER_HTTP_DISPATCH_METHOD (defaults to: POST)
### Advanced Usage
#### Azure Quick Scanning ## Advanced Usage
### Azure Quick Scanning
When running **as a Pod in an Azure or AWS environment**, kube-hunter will fetch subnets from the Instance Metadata Service. Naturally this makes the discovery process take longer. When running **as a Pod in an Azure or AWS environment**, kube-hunter will fetch subnets from the Instance Metadata Service. Naturally this makes the discovery process take longer.
To hardlimit subnet scanning to a `/24` CIDR, use the `--quick` option. To hardlimit subnet scanning to a `/24` CIDR, use the `--quick` option.
### Custom Hunting
Custom hunting enables advanced users to have control over what hunters gets registered at the start of a hunt.
**If you know what you are doing**, this can help if you want to adjust kube-hunter's hunting and discovery process for your needs.
Example:
```
kube-hunter --custom <HunterName1> <HunterName2>
```
Enabling Custom hunting removes all hunters from the hunting process, except the given whitelisted hunters.
The `--custom` flag reads a list of hunters class names, in order to view all of kube-hunter's class names, you can combine the flag `--raw-hunter-names` with the `--list` flag.
Example:
```
kube-hunter --active --list --raw-hunter-names
```
**Notice**: Due to kube-huner's architectural design, the following "Core Hunters/Classes" will always register (even when using custom hunting):
* HostDiscovery
* _Generates ip addresses for the hunt by given configurations_
* _Automatically discovers subnets using cloud Metadata APIs_
* FromPodHostDiscovery
* _Auto discover attack surface ip addresses for the hunt by using Pod based environment techniques_
* _Automatically discovers subnets using cloud Metadata APIs_
* PortDiscovery
* _Port scanning given ip addresses for known kubernetes services ports_
* Collector
* _Collects discovered vulnerabilities and open services for future report_
* StartedInfo
* _Prints the start message_
* SendFullReport
* _Dispatching the report based on given configurations_
## Deployment ## Deployment
There are three methods for deploying kube-hunter: There are three methods for deploying kube-hunter:

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# flake8: noqa: E402 # flake8: noqa: E402
from functools import partial
import logging import logging
import threading import threading
@@ -28,6 +29,8 @@ config = Config(
k8s_auto_discover_nodes=args.k8s_auto_discover_nodes, k8s_auto_discover_nodes=args.k8s_auto_discover_nodes,
service_account_token=args.service_account_token, service_account_token=args.service_account_token,
kubeconfig=args.kubeconfig, kubeconfig=args.kubeconfig,
enable_cve_hunting=args.enable_cve_hunting,
custom=args.custom,
) )
setup_logger(args.log, args.log_file) setup_logger(args.log, args.log_file)
set_config(config) set_config(config)
@@ -72,16 +75,20 @@ def interactive_set_config():
return True return True
def list_hunters(): def list_hunters(class_names=False):
print("\nPassive Hunters:\n----------------") print("\nPassive Hunters:\n----------------")
for hunter, docs in handler.passive_hunters.items(): for hunter, docs in handler.passive_hunters.items():
name, doc = hunter.parse_docs(docs) name, doc = hunter.parse_docs(docs)
if class_names:
name = hunter.__name__
print(f"* {name}\n {doc}\n") print(f"* {name}\n {doc}\n")
if config.active: if config.active:
print("\n\nActive Hunters:\n---------------") print("\n\nActive Hunters:\n---------------")
for hunter, docs in handler.active_hunters.items(): for hunter, docs in handler.active_hunters.items():
name, doc = hunter.parse_docs(docs) name, doc = hunter.parse_docs(docs)
if class_names:
name = hunter.__name__
print(f"* {name}\n {doc}\n") print(f"* {name}\n {doc}\n")
@@ -94,7 +101,10 @@ def main():
scan_options = [config.pod, config.cidr, config.remote, config.interface, config.k8s_auto_discover_nodes] scan_options = [config.pod, config.cidr, config.remote, config.interface, config.k8s_auto_discover_nodes]
try: try:
if args.list: if args.list:
list_hunters() if args.raw_hunter_names:
list_hunters(class_names=True)
else:
list_hunters()
return return
if not any(scan_options): if not any(scan_options):

View File

@@ -1,7 +1,11 @@
from dataclasses import dataclass from dataclasses import dataclass, field
from typing import Any, Optional from typing import Any, Optional
def get_default_core_hunters():
return ["FromPodHostDiscovery", "HostDiscovery", "PortDiscovery", "SendFullReport", "Collector", "StartedInfo"]
@dataclass @dataclass
class Config: class Config:
"""Config is a configuration container. """Config is a configuration container.
@@ -21,6 +25,7 @@ class Config:
- remote: Hosts to scan - remote: Hosts to scan
- report: Output format - report: Output format
- statistics: Include hunters statistics - statistics: Include hunters statistics
- enable_cve_hunting: enables cve hunting, shows cve results
""" """
active: bool = False active: bool = False
@@ -39,6 +44,10 @@ class Config:
k8s_auto_discover_nodes: bool = False k8s_auto_discover_nodes: bool = False
service_account_token: Optional[str] = None service_account_token: Optional[str] = None
kubeconfig: Optional[str] = None kubeconfig: Optional[str] = None
enable_cve_hunting: bool = False
custom: Optional[list] = None
raw_hunter_names: bool = False
core_hunters: list = field(default_factory=get_default_core_hunters)
_config: Optional[Config] = None _config: Optional[Config] = None

View File

@@ -46,6 +46,22 @@ def parser_add_arguments(parser):
help="One or more remote ip/dns to hunt", help="One or more remote ip/dns to hunt",
) )
parser.add_argument(
"-c",
"--custom",
nargs="+",
metavar="HUNTERS",
default=list(),
help="Custom hunting. Only given hunter names will register in the hunt."
"for a list of options run `--list --raw-hunter-names`",
)
parser.add_argument(
"--raw-hunter-names",
action="store_true",
help="Use in combination with `--list` to display hunter class names to pass for custom hunting flag",
)
parser.add_argument( parser.add_argument(
"--k8s-auto-discover-nodes", "--k8s-auto-discover-nodes",
action="store_true", action="store_true",
@@ -76,6 +92,12 @@ def parser_add_arguments(parser):
parser.add_argument("--active", action="store_true", help="Enables active hunting") parser.add_argument("--active", action="store_true", help="Enables active hunting")
parser.add_argument(
"--enable-cve-hunting",
action="store_true",
help="Show cluster CVEs based on discovered version (Depending on different vendors, may result in False Positives)",
)
parser.add_argument( parser.add_argument(
"--log", "--log",
type=str, type=str,

View File

@@ -62,7 +62,7 @@ class EventQueue(Queue):
###################################################### ######################################################
""" """
def subscribe(self, event, hook=None, predicate=None): def subscribe(self, event, hook=None, predicate=None, is_register=True):
""" """
The Subscribe Decorator - For Regular Registration The Subscribe Decorator - For Regular Registration
Use this to register for one event only. Your hunter will execute each time this event is published Use this to register for one event only. Your hunter will execute each time this event is published
@@ -74,12 +74,12 @@ class EventQueue(Queue):
""" """
def wrapper(hook): def wrapper(hook):
self.subscribe_event(event, hook=hook, predicate=predicate) self.subscribe_event(event, hook=hook, predicate=predicate, is_register=is_register)
return hook return hook
return wrapper return wrapper
def subscribe_many(self, events, hook=None, predicates=None): def subscribe_many(self, events, hook=None, predicates=None, is_register=True):
""" """
The Subscribe Many Decorator - For Multiple Registration, The Subscribe Many Decorator - For Multiple Registration,
When your attack needs several prerequisites to exist in the cluster, You need to register for multiple events. When your attack needs several prerequisites to exist in the cluster, You need to register for multiple events.
@@ -99,12 +99,12 @@ class EventQueue(Queue):
""" """
def wrapper(hook): def wrapper(hook):
self.subscribe_events(events, hook=hook, predicates=predicates) self.subscribe_events(events, hook=hook, predicates=predicates, is_register=is_register)
return hook return hook
return wrapper return wrapper
def subscribe_once(self, event, hook=None, predicate=None): def subscribe_once(self, event, hook=None, predicate=None, is_register=True):
""" """
The Subscribe Once Decorator - For Single Trigger Registration, The Subscribe Once Decorator - For Single Trigger Registration,
Use this when you want your hunter to execute only in your entire program run Use this when you want your hunter to execute only in your entire program run
@@ -125,7 +125,8 @@ class EventQueue(Queue):
hook.__new__ = __new__unsubscribe_self hook.__new__ = __new__unsubscribe_self
self.subscribe_event(event, hook=hook, predicate=predicate) self.subscribe_event(event, hook=hook, predicate=predicate, is_register=is_register)
return hook return hook
return wrapper return wrapper
@@ -256,7 +257,33 @@ class EventQueue(Queue):
self.hooks[event].append((hook, predicate)) self.hooks[event].append((hook, predicate))
logging.debug("{} subscribed to {}".format(hook, event)) logging.debug("{} subscribed to {}".format(hook, event))
def subscribe_event(self, event, hook=None, predicate=None): def allowed_for_custom_registration(self, target_hunter):
"""
Check if the partial input list contains the hunter we are about to register for events
If hunter is considered a Core hunter as specified in `config.core_hunters` we allow it anyway
Returns true if:
1. partial hunt is disabled
2. partial hunt is enabled and hunter is in core hunter class
3. partial hunt is enabled and hunter is specified in config.partial
@param target_hunter: hunter class for registration check
"""
config = get_config()
if not config.custom:
return True
hunter_class_name = target_hunter.__name__
if hunter_class_name in config.core_hunters or hunter_class_name in config.custom:
return True
return False
def subscribe_event(self, event, hook=None, predicate=None, is_register=True):
if not is_register:
return
if not self.allowed_for_custom_registration(hook):
return
if not self._register_hunters(hook): if not self._register_hunters(hook):
return return
@@ -267,9 +294,13 @@ class EventQueue(Queue):
else: else:
self._register_hook(event, hook, predicate) self._register_hook(event, hook, predicate)
def subscribe_events(self, events, hook=None, predicates=None): def subscribe_events(self, events, hook=None, predicates=None, is_register=True):
if not is_register:
return
if not self.allowed_for_custom_registration(hook):
return
if not self._register_hunters(hook): if not self._register_hunters(hook):
return False return
if predicates is None: if predicates is None:
predicates = [None] * len(events) predicates = [None] * len(events)

View File

@@ -166,7 +166,9 @@ class FromPodHostDiscovery(Discovery):
return True return True
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
logger.debug("Failed to connect AWS metadata server v1") logger.debug("Failed to connect AWS metadata server v1")
return False except Exception:
logger.debug("Unknown error when trying to connect to AWS metadata v1 API")
return False
def is_aws_pod_v2(self): def is_aws_pod_v2(self):
config = get_config() config = get_config()
@@ -189,7 +191,9 @@ class FromPodHostDiscovery(Discovery):
return True return True
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
logger.debug("Failed to connect AWS metadata server v2") logger.debug("Failed to connect AWS metadata server v2")
return False except Exception:
logger.debug("Unknown error when trying to connect to AWS metadata v2 API")
return False
def is_azure_pod(self): def is_azure_pod(self):
config = get_config() config = get_config()
@@ -206,7 +210,9 @@ class FromPodHostDiscovery(Discovery):
return True return True
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
logger.debug("Failed to connect Azure metadata server") logger.debug("Failed to connect Azure metadata server")
return False except Exception:
logger.debug("Unknown error when trying to connect to Azure metadata server")
return False
# for pod scanning # for pod scanning
def gateway_discovery(self): def gateway_discovery(self):

View File

@@ -3,7 +3,8 @@ from packaging import version
from kube_hunter.conf import get_config from kube_hunter.conf import get_config
from kube_hunter.core.events import handler from kube_hunter.core.events import handler
from kube_hunter.core.events.types import Vulnerability, Event, K8sVersionDisclosure
from kube_hunter.core.events.types import K8sVersionDisclosure, Vulnerability, Event
from kube_hunter.core.types import ( from kube_hunter.core.types import (
Hunter, Hunter,
KubectlClient, KubectlClient,
@@ -15,6 +16,7 @@ from kube_hunter.core.types import (
from kube_hunter.modules.discovery.kubectl import KubectlClientEvent from kube_hunter.modules.discovery.kubectl import KubectlClientEvent
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
config = get_config()
class ServerApiVersionEndPointAccessPE(Vulnerability, Event): class ServerApiVersionEndPointAccessPE(Vulnerability, Event):
@@ -199,7 +201,7 @@ class CveUtils:
return vulnerable return vulnerable
@handler.subscribe_once(K8sVersionDisclosure) @handler.subscribe_once(K8sVersionDisclosure, is_register=config.enable_cve_hunting)
class K8sClusterCveHunter(Hunter): class K8sClusterCveHunter(Hunter):
"""K8s CVE Hunter """K8s CVE Hunter
Checks if Node is running a Kubernetes version vulnerable to Checks if Node is running a Kubernetes version vulnerable to
@@ -224,6 +226,7 @@ class K8sClusterCveHunter(Hunter):
self.publish_event(vulnerability(self.event.version)) self.publish_event(vulnerability(self.event.version))
# Removed due to incomplete implementation for multiple vendors revisions of kubernetes
@handler.subscribe(KubectlClientEvent) @handler.subscribe(KubectlClientEvent)
class KubectlCVEHunter(Hunter): class KubectlCVEHunter(Hunter):
"""Kubectl CVE Hunter """Kubectl CVE Hunter

View File

@@ -12,10 +12,7 @@ class HTTPDispatcher:
dispatch_url = os.environ.get("KUBEHUNTER_HTTP_DISPATCH_URL", "https://localhost/") dispatch_url = os.environ.get("KUBEHUNTER_HTTP_DISPATCH_URL", "https://localhost/")
try: try:
r = requests.request( r = requests.request(
dispatch_method, dispatch_method, dispatch_url, json=report, headers={"Content-Type": "application/json"}, verify=False
dispatch_url,
json=report,
headers={"Content-Type": "application/json"},
) )
r.raise_for_status() r.raise_for_status()
logger.info(f"Report was dispatched to: {dispatch_url}") logger.info(f"Report was dispatched to: {dispatch_url}")

View File

@@ -1,5 +1,3 @@
-r requirements.txt
flake8 flake8
pytest >= 2.9.1 pytest >= 2.9.1
requests-mock >= 1.8 requests-mock >= 1.8

View File

@@ -1,6 +1,6 @@
# flake8: noqa: E402 # flake8: noqa: E402
from kube_hunter.conf import Config, set_config from kube_hunter.conf import Config, set_config, get_config
set_config(Config(active=True)) set_config(Config(active=True))
@@ -23,7 +23,9 @@ from kube_hunter.modules.hunting.apiserver import (
from kube_hunter.modules.hunting.arp import ArpSpoofHunter from kube_hunter.modules.hunting.arp import ArpSpoofHunter
from kube_hunter.modules.hunting.capabilities import PodCapabilitiesHunter from kube_hunter.modules.hunting.capabilities import PodCapabilitiesHunter
from kube_hunter.modules.hunting.certificates import CertificateDiscovery from kube_hunter.modules.hunting.certificates import CertificateDiscovery
from kube_hunter.modules.hunting.cves import K8sClusterCveHunter, KubectlCVEHunter
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.dashboard import KubeDashboard
from kube_hunter.modules.hunting.dns import DnsSpoofHunter from kube_hunter.modules.hunting.dns import DnsSpoofHunter
from kube_hunter.modules.hunting.etcd import EtcdRemoteAccess, EtcdRemoteAccessActive from kube_hunter.modules.hunting.etcd import EtcdRemoteAccess, EtcdRemoteAccessActive
@@ -40,6 +42,8 @@ from kube_hunter.modules.hunting.mounts import VarLogMountHunter, ProveVarLogMou
from kube_hunter.modules.hunting.proxy import KubeProxy, ProveProxyExposed, K8sVersionDisclosureProve from kube_hunter.modules.hunting.proxy import KubeProxy, ProveProxyExposed, K8sVersionDisclosureProve
from kube_hunter.modules.hunting.secrets import AccessSecrets from kube_hunter.modules.hunting.secrets import AccessSecrets
config = get_config()
PASSIVE_HUNTERS = { PASSIVE_HUNTERS = {
ApiServiceDiscovery, ApiServiceDiscovery,
KubeDashboardDiscovery, KubeDashboardDiscovery,
@@ -56,7 +60,6 @@ PASSIVE_HUNTERS = {
ApiVersionHunter, ApiVersionHunter,
PodCapabilitiesHunter, PodCapabilitiesHunter,
CertificateDiscovery, CertificateDiscovery,
K8sClusterCveHunter,
KubectlCVEHunter, KubectlCVEHunter,
KubeDashboard, KubeDashboard,
EtcdRemoteAccess, EtcdRemoteAccess,
@@ -67,6 +70,9 @@ PASSIVE_HUNTERS = {
AccessSecrets, AccessSecrets,
} }
# if config.enable_cve_hunting:
# PASSIVE_HUNTERS.append(K8sClusterCveHunter)
ACTIVE_HUNTERS = { ACTIVE_HUNTERS = {
ProveAzureSpnExposure, ProveAzureSpnExposure,
AccessApiServerActive, AccessApiServerActive,