Solved some exception bugs & did some refactoring to code & Added event & splited active & passive hunter

This commit is contained in:
ori.agmon
2018-10-02 18:55:50 +03:00
parent f4ff44012e
commit 7201f5e236
3 changed files with 83 additions and 29 deletions

View File

@@ -41,7 +41,7 @@ class EventQueue(Queue, object):
self.subscribe_event(event, hook=hook, predicate=predicate)
return hook
return wrapper
# getting uninstantiated event object
def subscribe_event(self, event, hook=None, predicate=None):
if ActiveHunter in hook.__mro__:
@@ -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))
@@ -75,13 +75,13 @@ class EventQueue(Queue, object):
hook = self.get()
try:
hook.execute()
except Exception as ex:
except Exception as ex:
logging.debug(ex.message)
self.task_done()
logging.debug("closing thread...")
def notifier(self):
time.sleep(2)
time.sleep(2)
while self.unfinished_tasks > 0:
logging.debug("{} tasks left".format(self.unfinished_tasks))
time.sleep(3)
@@ -91,5 +91,5 @@ class EventQueue(Queue, object):
self.running = False
with self.mutex:
self.queue.clear()
handler = EventQueue(800)
handler = EventQueue(800)

View File

@@ -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

View 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