Skip to content

Commit

Permalink
Switched CVE Hunting to optional & Minor core feature (#482)
Browse files Browse the repository at this point in the history
* Removed automatic registration of the k8s CVE hunter

* Made CVE hunting optional, default set to not run
  • Loading branch information
danielsagi authored Oct 16, 2021
1 parent 8d045fb commit 00eb0df
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 13 deletions.
1 change: 1 addition & 0 deletions kube_hunter/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
k8s_auto_discover_nodes=args.k8s_auto_discover_nodes,
service_account_token=args.service_account_token,
kubeconfig=args.kubeconfig,
enable_cve_hunting=args.enable_cve_hunting,
)
setup_logger(args.log, args.log_file)
set_config(config)
Expand Down
2 changes: 2 additions & 0 deletions kube_hunter/conf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Config:
- remote: Hosts to scan
- report: Output format
- statistics: Include hunters statistics
- enable_cve_hunting: enables cve hunting, shows cve results
"""

active: bool = False
Expand All @@ -39,6 +40,7 @@ class Config:
k8s_auto_discover_nodes: bool = False
service_account_token: Optional[str] = None
kubeconfig: Optional[str] = None
enable_cve_hunting: bool = False


_config: Optional[Config] = None
Expand Down
6 changes: 6 additions & 0 deletions kube_hunter/conf/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ def parser_add_arguments(parser):

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(
"--log",
type=str,
Expand Down
21 changes: 13 additions & 8 deletions kube_hunter/core/events/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __init__(self, num_worker=10):
######################################################
"""

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
Use this to register for one event only. Your hunter will execute each time this event is published
Expand All @@ -74,12 +74,12 @@ def subscribe(self, event, hook=None, predicate=None):
"""

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 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,
When your attack needs several prerequisites to exist in the cluster, You need to register for multiple events.
Expand All @@ -99,12 +99,12 @@ def subscribe_many(self, events, hook=None, predicates=None):
"""

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 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,
Use this when you want your hunter to execute only in your entire program run
Expand All @@ -125,7 +125,8 @@ def __new__unsubscribe_self(self, cls):

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 wrapper
Expand Down Expand Up @@ -256,7 +257,9 @@ def _register_hook(self, event, hook=None, predicate=None):
self.hooks[event].append((hook, predicate))
logging.debug("{} subscribed to {}".format(hook, event))

def subscribe_event(self, event, hook=None, predicate=None):
def subscribe_event(self, event, hook=None, predicate=None, is_register=True):
if not is_register:
return
if not self._register_hunters(hook):
return

Expand All @@ -267,7 +270,9 @@ def subscribe_event(self, event, hook=None, predicate=None):
else:
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 False
if not self._register_hunters(hook):
return False

Expand Down
7 changes: 5 additions & 2 deletions kube_hunter/modules/hunting/cves.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

from kube_hunter.conf import get_config
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 (
Hunter,
KubectlClient,
Expand All @@ -15,6 +16,7 @@
from kube_hunter.modules.discovery.kubectl import KubectlClientEvent

logger = logging.getLogger(__name__)
config = get_config()


class ServerApiVersionEndPointAccessPE(Vulnerability, Event):
Expand Down Expand Up @@ -199,7 +201,7 @@ def is_vulnerable(fix_versions, check_version, ignore_downstream=False):
return vulnerable


@handler.subscribe_once(K8sVersionDisclosure)
@handler.subscribe_once(K8sVersionDisclosure, is_register=config.enable_cve_hunting)
class K8sClusterCveHunter(Hunter):
"""K8s CVE Hunter
Checks if Node is running a Kubernetes version vulnerable to
Expand All @@ -224,6 +226,7 @@ def execute(self):
self.publish_event(vulnerability(self.event.version))


# Removed due to incomplete implementation for multiple vendors revisions of kubernetes
@handler.subscribe(KubectlClientEvent)
class KubectlCVEHunter(Hunter):
"""Kubectl CVE Hunter
Expand Down
12 changes: 9 additions & 3 deletions tests/core/test_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 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))

Expand All @@ -23,7 +23,9 @@
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, 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.dns import DnsSpoofHunter
from kube_hunter.modules.hunting.etcd import EtcdRemoteAccess, EtcdRemoteAccessActive
Expand All @@ -40,6 +42,8 @@
from kube_hunter.modules.hunting.proxy import KubeProxy, ProveProxyExposed, K8sVersionDisclosureProve
from kube_hunter.modules.hunting.secrets import AccessSecrets

config = get_config()

PASSIVE_HUNTERS = {
ApiServiceDiscovery,
KubeDashboardDiscovery,
Expand All @@ -56,7 +60,6 @@
ApiVersionHunter,
PodCapabilitiesHunter,
CertificateDiscovery,
K8sClusterCveHunter,
KubectlCVEHunter,
KubeDashboard,
EtcdRemoteAccess,
Expand All @@ -67,6 +70,9 @@
AccessSecrets,
}

# if config.enable_cve_hunting:
# PASSIVE_HUNTERS.append(K8sClusterCveHunter)

ACTIVE_HUNTERS = {
ProveAzureSpnExposure,
AccessApiServerActive,
Expand Down

0 comments on commit 00eb0df

Please sign in to comment.