mirror of
https://github.com/aquasecurity/kube-hunter.git
synced 2026-05-17 14:47:23 +00:00
Solved some exception bugs & did some refactoring to code & Added event & splited active & passive hunter
This commit is contained in:
@@ -24,7 +24,7 @@ class etcdRemoteVersionDisclosureEvent(Service, Event):
|
||||
def __init__(self):
|
||||
Service.__init__(self, name="Etcd Remote version disclosure")
|
||||
class etcdAccessEnabledWithoutAuthEvent(Service, Event):
|
||||
"""Remote version disclosure might give an attacker a valuable data to attack a cluster"""
|
||||
"""Etcd is accessible without authorization, it would allow a potential attacker to gain access to the etcd"""
|
||||
def __init__(self):
|
||||
Service.__init__(self, name="Etcd is accessible without authorization")
|
||||
|
||||
@@ -55,20 +55,6 @@ class etcdRemoteAccess(Hunter):
|
||||
return True
|
||||
return False
|
||||
|
||||
def db_keys_write_access(self):
|
||||
logging.debug(self.event.host)
|
||||
logging.debug("Active hunter* is attempting to write keys remotely")
|
||||
data = {
|
||||
'value': 'remote write access penetration'
|
||||
}
|
||||
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)
|
||||
|
||||
if self.helperFuncDo2Requests(r_secure, r_not_secure, data=data, reqType="put"):
|
||||
self.publish_event(etcdRemoteWriteAccessEvent())
|
||||
return True
|
||||
return False
|
||||
|
||||
def version_disclosure(self):
|
||||
logging.debug(self.event.host)
|
||||
logging.debug("Passive hunter is attempting to check etcd version remotely")
|
||||
@@ -85,15 +71,18 @@ class etcdRemoteAccess(Hunter):
|
||||
self.db_keys_disclosure()
|
||||
self.db_keys_write_access()
|
||||
|
||||
def helperFuncDo2Requests(self, req1, req2, isVerify=False, data=None, reqType="get"):
|
||||
# Will attempt to do request "req1" with the optional parameters.
|
||||
# If fails it will attempt to do "req2" with the optional parameters.
|
||||
# If once of the request success this method will return True, if both fail- False.
|
||||
def helperFuncDo2Requests(self, req1, req2, is_verify=False, data=None, req_type="get"):
|
||||
try:
|
||||
r = self.helperDoRequest(req1, isVerify, data, reqType)
|
||||
r = self.helperDoRequest(req1, is_verify, data, req_type)
|
||||
has_remote_access_gained = (r.status_code == 200 and r.content != "")
|
||||
if has_remote_access_gained:
|
||||
return True
|
||||
except Exception:
|
||||
try:
|
||||
r = self.helperDoRequest(req2, isVerify, data, reqType)
|
||||
r = self.helperDoRequest(req2, is_verify, data, req_type)
|
||||
has_remote_access_gained = (r.status_code == 200 and r.content != "")
|
||||
if has_remote_access_gained:
|
||||
return True
|
||||
@@ -101,10 +90,10 @@ class etcdRemoteAccess(Hunter):
|
||||
return False #None of the requests succeded..
|
||||
return False
|
||||
|
||||
def helperDoRequest(self, req, isVerify, data=None, reqType="get"):
|
||||
if reqType == "put":
|
||||
r = requests.put(req, verify=isVerify, timeout=3, data=data)
|
||||
def helperDoRequest(self, req, is_verify, data=None, req_type="get"):
|
||||
if req_type == "put":
|
||||
r = requests.put(req, verify=is_verify, timeout=3, data=data)
|
||||
return r
|
||||
elif reqType == "get":
|
||||
r = requests.get(req, verify=isVerify, timeout=3, data=data)
|
||||
elif req_type == "get":
|
||||
r = requests.get(req, verify=is_verify, timeout=3, data=data)
|
||||
return r
|
||||
65
src/modules/hunting/etcd.py
Normal file
65
src/modules/hunting/etcd.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
|
||||
from ...core.events import handler
|
||||
from ...core.events.types import Vulnerability, Event, Service, OpenPortEvent
|
||||
from ...core.types import ActiveHunter
|
||||
|
||||
"""Etcd is a DB that stores cluster's data,
|
||||
it contains configuration and current state information, and might contain secrets"""
|
||||
# Vulnerability:
|
||||
class etcdRemoteWriteAccessEvent(Vulnerability, Event):
|
||||
"""Remote write access might grant an attacker full control over the kubernetes cluster"""
|
||||
def __init__(self):
|
||||
Vulnerability.__init__(self, name="Etcd Remote Write Access Event")
|
||||
|
||||
@handler.subscribe(OpenPortEvent, predicate= lambda p: p.port == 2379)
|
||||
class etcdRemoteAccess(ActiveHunter):
|
||||
"""Etcd Remote Access
|
||||
Checks for remote write access to etcd
|
||||
"""
|
||||
def db_keys_write_access(self):
|
||||
logging.debug(self.event.host)
|
||||
logging.debug("Active hunter is attempting to write keys remotely")
|
||||
data = {
|
||||
'value': 'remote write access penetration'
|
||||
}
|
||||
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)
|
||||
|
||||
if self.helperFuncDo2Requests(r_secure, r_not_secure, data=data, req_type="put"):
|
||||
self.publish_event(etcdRemoteWriteAccessEvent())
|
||||
return True
|
||||
return False
|
||||
|
||||
def execute(self):
|
||||
self.db_keys_write_access()
|
||||
|
||||
# Will attempt to do request "req1" with the optional parameters.
|
||||
# If fails it will attempt to do "req2" with the optional parameters.
|
||||
# If once of the request success this method will return True, if both fail- False.
|
||||
def helperFuncDo2Requests(self, req1, req2, is_verify=False, data=None, req_type="get"):
|
||||
try:
|
||||
r = self.helperDoRequest(req1, is_verify, data, req_type)
|
||||
has_remote_access_gained = (r.status_code == 200 and r.content != "")
|
||||
if has_remote_access_gained:
|
||||
return True
|
||||
except Exception:
|
||||
try:
|
||||
r = self.helperDoRequest(req2, is_verify, data, req_type)
|
||||
has_remote_access_gained = (r.status_code == 200 and r.content != "")
|
||||
if has_remote_access_gained:
|
||||
return True
|
||||
except Exception:
|
||||
return False #None of the requests succeded..
|
||||
return False
|
||||
|
||||
def helperDoRequest(self, req, is_verify, data=None, req_type="get"):
|
||||
if req_type == "put":
|
||||
r = requests.put(req, verify=is_verify, timeout=3, data=data)
|
||||
return r
|
||||
elif req_type == "get":
|
||||
r = requests.get(req, verify=is_verify, timeout=3, data=data)
|
||||
return r
|
||||
Reference in New Issue
Block a user