mirror of
https://github.com/aquasecurity/kube-hunter.git
synced 2026-05-10 19:26:49 +00:00
Fixed the PR comments :-)
This commit is contained in:
@@ -50,7 +50,7 @@ class EventQueue(Queue, object):
|
||||
else:
|
||||
self.active_hunters[hook] = hook.__doc__
|
||||
elif Hunter in hook.__mro__:
|
||||
self.passive_hunters[hook] = hook.__doc__
|
||||
self.passive_hunters[hook] = hook.__doc__
|
||||
|
||||
if hook not in self.hooks[event]:
|
||||
self.hooks[event].append((hook, predicate))
|
||||
@@ -92,4 +92,4 @@ class EventQueue(Queue, object):
|
||||
with self.mutex:
|
||||
self.queue.clear()
|
||||
|
||||
handler = EventQueue(800)
|
||||
handler = EventQueue(800)
|
||||
|
||||
@@ -7,11 +7,9 @@ from ...core.events import handler
|
||||
from ...core.events.types import Event, OpenPortEvent, Service
|
||||
from ...core.types import Hunter
|
||||
|
||||
"""Etcd is a DB that stores cluster's data,
|
||||
it contains configuration and current state information, and might contain secrets"""
|
||||
#services:
|
||||
# Service:
|
||||
|
||||
class etcdAccessEvent(Service, Event):
|
||||
class EtcdAccessEvent(Service, Event):
|
||||
"""Etcd is a DB that stores cluster's data, it contains configuration and current state information, and might contain secrets"""
|
||||
def __init__(self):
|
||||
Service.__init__(self, name="Etcd")
|
||||
@@ -19,7 +17,7 @@ class etcdAccessEvent(Service, Event):
|
||||
|
||||
|
||||
@handler.subscribe(OpenPortEvent, predicate= lambda p: p.port == 2379)
|
||||
class etcdRemoteAccess(Hunter):
|
||||
class EtcdRemoteAccess(Hunter):
|
||||
"""Etcd Remote Access
|
||||
Checks for remote availability of etcd, version, read access, write access
|
||||
"""
|
||||
@@ -28,7 +26,7 @@ class etcdRemoteAccess(Hunter):
|
||||
|
||||
def execute(self):
|
||||
try:
|
||||
self.publish_event(etcdAccessEvent())
|
||||
self.publish_event(EtcdAccessEvent())
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
@@ -39,61 +39,63 @@ def helperDoRequest(req, is_verify, data=None, req_type="get"):
|
||||
|
||||
|
||||
""" Vulnerabilities """
|
||||
class etcdRemoteWriteAccessEvent(Vulnerability, Event):
|
||||
class EtcdRemoteWriteAccessEvent(Vulnerability, Event):
|
||||
"""Remote write access might grant an attacker full control over the kubernetes cluster"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, write_res):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote Write Access Event", category=RemoteCodeExec)
|
||||
self.evidence = write_res
|
||||
|
||||
class etcdRemoteReadAccessEvent(Vulnerability, Event):
|
||||
class EtcdRemoteReadAccessEvent(Vulnerability, Event):
|
||||
"""Remote read access might expose to an attacker cluster's possible exploits, secrets and more."""
|
||||
|
||||
def __init__(self, keys):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote Read Access Event", category=AccessRisk)
|
||||
self.evidence = keys
|
||||
|
||||
class etcdRemoteVersionDisclosureEvent(Vulnerability, Event):
|
||||
class EtcdRemoteVersionDisclosureEvent(Vulnerability, Event):
|
||||
"""Remote version disclosure might give an attacker a valuable data to attack a cluster"""
|
||||
|
||||
def __init__(self, version):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote version disclosure", category=AccessRisk)
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd Remote version disclosure", category=InformationDisclosure)
|
||||
self.evidence = version
|
||||
|
||||
class etcdAccessEnabledWithoutAuthEvent(Vulnerability, Event):
|
||||
class EtcdAccessEnabledWithoutAuthEvent(Vulnerability, Event):
|
||||
"""Etcd is accessible without authorization, it would allow a potential attacker to gain access to the etcd"""
|
||||
|
||||
def __init__(self, version):
|
||||
Vulnerability.__init__(self, KubernetesCluster, name="Etcd is accessible without authorization", category=UnauthenticatedAccess)
|
||||
self.evidence = version
|
||||
|
||||
|
||||
@handler.subscribe(OpenPortEvent, predicate= lambda p: p.port == 2379)
|
||||
class etcdRemoteAccessActive(ActiveHunter):
|
||||
# Active Hunter
|
||||
@handler.subscribe(OpenPortEvent, predicate=lambda p: p.port == 2379)
|
||||
class EtcdRemoteAccessActive(ActiveHunter):
|
||||
"""Checks for remote write access to etcd"""
|
||||
|
||||
def __init__(self, event):
|
||||
self.event = event
|
||||
self.write_evidence = ''
|
||||
|
||||
def db_keys_write_access(self):
|
||||
logging.debug(self.event.host)
|
||||
logging.debug("Active hunter is attempting to write keys remotely")
|
||||
logging.debug("Active hunter is attempting to write keys remotely on host " + self.event.host)
|
||||
data = {
|
||||
'value': 'remote write access penetration'
|
||||
'value': 'remotely written data'
|
||||
}
|
||||
r_secure = "https://{host}:{port}/v2/keys/message".format(host=self.event.host, port=2379)
|
||||
r_not_secure = "https://{host}:{port}/v2/keys/message".format(host=self.event.host, port=2379)
|
||||
|
||||
r_not_secure = "http://{host}:{port}/v2/keys/message".format(host=self.event.host, port=2379)
|
||||
res = helperFuncDo2Requests(r_secure, r_not_secure)
|
||||
if res:
|
||||
self.publish_event(etcdRemoteWriteAccessEvent())
|
||||
self.write_evidence = res.content
|
||||
return True
|
||||
return False
|
||||
|
||||
def execute(self):
|
||||
self.db_keys_write_access()
|
||||
if self.db_keys_write_access():
|
||||
self.publish_event(EtcdRemoteWriteAccessEvent(self.write_evidence))
|
||||
|
||||
# Passive Hunter
|
||||
@handler.subscribe(OpenPortEvent, predicate=lambda p: p.port == 2379)
|
||||
class etcdRemoteAccess(Hunter):
|
||||
class EtcdRemoteAccess(Hunter):
|
||||
"""Etcd Remote Access
|
||||
Checks for remote availability of etcd, version, read access, write access
|
||||
"""
|
||||
@@ -101,6 +103,8 @@ class etcdRemoteAccess(Hunter):
|
||||
# Check the etcd hunter on a remote cluster! (currently everything was checked only at 127.0.0.1:2379)
|
||||
def __init__(self, event):
|
||||
self.event = event
|
||||
self.version_evidence = ''
|
||||
self.keys_evidence = ''
|
||||
|
||||
def db_keys_disclosure(self):
|
||||
logging.debug(self.event.host)
|
||||
@@ -109,7 +113,7 @@ class etcdRemoteAccess(Hunter):
|
||||
r_not_secure = "http://{host}:{port}/v2/keys".format(host=self.event.host, port=2379)
|
||||
res = helperFuncDo2Requests(r_secure, r_not_secure)
|
||||
if res:
|
||||
self.publish_event(etcdRemoteReadAccessEvent(res.content))
|
||||
self.keys_evidence = res.content
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -120,8 +124,7 @@ class etcdRemoteAccess(Hunter):
|
||||
r_not_secure = "http://{host}:{port}/version".format(host=self.event.host, port=2379)
|
||||
res = helperFuncDo2Requests(r_secure, r_not_secure)
|
||||
if res:
|
||||
self.no_auth_evidence = res.content
|
||||
self.publish_event(etcdRemoteVersionDisclosureEvent(res.content))
|
||||
self.version_evidence = res.content
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -129,14 +132,15 @@ class etcdRemoteAccess(Hunter):
|
||||
logging.debug(self.event.host)
|
||||
logging.debug("Passive hunter is attempting to access etcd without authorization")
|
||||
r_not_secure = "http://{host}:{port}/version".format(host=self.event.host, port=2379)
|
||||
res = helperFuncDo2Requests(r_not_secure, r_not_secure)# We dont have to do 2 requests this time
|
||||
res = helperFuncDo2Requests(r_not_secure, r_not_secure) # We don't have to do 2 requests this time
|
||||
if res:
|
||||
self.publish_event(etcdAccessEnabledWithoutAuthEvent(res.content))
|
||||
return True
|
||||
return False
|
||||
|
||||
def execute(self):
|
||||
if self.version_disclosure():
|
||||
self.unauthorized_access()
|
||||
self.db_keys_disclosure()
|
||||
self.db_keys_write_access()
|
||||
self.publish_event(EtcdRemoteVersionDisclosureEvent(self.version_evidence))
|
||||
if self.unauthorized_access():
|
||||
self.publish_event(EtcdAccessEnabledWithoutAuthEvent(self.version_evidence))
|
||||
if self.db_keys_disclosure():
|
||||
self.publish_event(EtcdRemoteReadAccessEvent(self.keys_evidence))
|
||||
|
||||
Reference in New Issue
Block a user