Added checks on api responses before json.loads, added a quick scanning option, to scan part of the subnet

This commit is contained in:
daniel_sagi
2018-06-12 14:30:28 +03:00
parent c52e684272
commit 73a4e83781
5 changed files with 73 additions and 61 deletions

View File

@@ -40,6 +40,7 @@ class Service(object):
self.name = name
self.secure = secure
self.path = path
self.role = "Node"
def get_name(self):
return self.name
@@ -58,6 +59,7 @@ class Vulnerability(object):
self.component = component
self.name = name
self.evidence = ""
self.role = "Node"
def get_name(self):
return self.name
@@ -65,19 +67,6 @@ class Vulnerability(object):
def explain(self):
return self.__doc__
class Information(object):
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
def explain(self):
return self.__doc__
def proof(self):
return self.name
event_id_count = 0
""" Discovery/Hunting Events """

View File

@@ -0,0 +1,15 @@
import requests
from ...core.types import Hunter
from ...core.events import handler
from ...core.events.types import OpenPortEvent
@handler.subscribe(OpenPortEvent, predicate=lambda x: x.port==443)
class ApiServerDiscovery(Hunter):
def __init__(self, event):
self.event = event
def execute(self):
main_request = requests.get("https://{}:{}".format(self.event.host, self.event.port), verify=False).text
if "code" in main_request:
self.event.role = "Master"

View File

@@ -90,7 +90,7 @@ class HostDiscovery(Hunter):
address, subnet= "", ""
for interface in machine_metadata["network"]["interface"]:
address, subnet = interface["ipv4"]["subnet"][0]["address"], interface["ipv4"]["subnet"][0]["prefix"]
for ip in self.generate_subnet(address, sn=subnet):
for ip in self.generate_subnet(address, sn=subnet if not config.quick else "24"):
self.publish_event(NewHostEvent(host=ip, cloud="Azure"))
self.publish_event(AzureMetadataApi(cidr="{}/{}".format(address, subnet)))

View File

@@ -27,17 +27,19 @@ class AzureSpnHunter(Hunter):
# getting a container that has access to the azure.json file
def get_key_container(self):
pods_data = json.loads(requests.get(self.base_url + "/pods", verify=False).text)["items"]
for pod_data in pods_data:
for container in pod_data["spec"]["containers"]:
for mount in container["volumeMounts"]:
path = mount["mountPath"]
if '/etc/kubernetes/azure.json'.startswith(path):
return {
"name": container["name"],
"pod": pod_data["metadata"]["name"],
"namespace": pod_data["metadata"]["namespace"]
}
raw_pods = requests.get(self.base_url + "/pods", verify=False).text
if "items" in raw_pods:
pods_data = json.loads(raw_pods)["items"]
for pod_data in pods_data:
for container in pod_data["spec"]["containers"]:
for mount in container["volumeMounts"]:
path = mount["mountPath"]
if '/etc/kubernetes/azure.json'.startswith(path):
return {
"name": container["name"],
"pod": pod_data["metadata"]["name"],
"namespace": pod_data["metadata"]["namespace"]
}
def execute(self):
container = self.get_key_container()

View File

@@ -7,7 +7,7 @@ import urllib3
from __main__ import config
from ...core.events import handler
from ...core.events.types import (KubernetesCluster, Kubelet, Vulnerability, Information, Event)
from ...core.events.types import (KubernetesCluster, Kubelet, Vulnerability, Event)
from ..discovery.kubelet import ReadOnlyKubeletEvent, SecureKubeletEvent, ExposedPodsHandler
from ...core.types import Hunter, ActiveHunter
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
@@ -252,18 +252,20 @@ class ProveRunHandler(ActiveHunter):
return requests.post(run_url, verify=False, params={'cmd': command}).text
def execute(self):
pods_data = json.loads(requests.get("https://{host}:{port}/pods".format(host=self.event.host, port=self.event.port), verify=False).text)['items']
for pod_data in pods_data:
container_data = next((container_data for container_data in pod_data["spec"]["containers"]), None)
if container_data:
output = self.run("uname -a", container={
"namespace": pod_data["metadata"]["namespace"],
"pod": pod_data["metadata"]["name"],
"name": container_data["name"]
})
if output and "exited with" not in output:
self.event.evidence = "uname: " + output
break
pods_raw = requests.get("https://{host}:{port}/pods".format(host=self.event.host, port=self.event.port), verify=False).text
if "items" in pods_raw:
pods_data = json.loads(pods_raw)['items']
for pod_data in pods_data:
container_data = next((container_data for container_data in pod_data["spec"]["containers"]), None)
if container_data:
output = self.run("uname -a", container={
"namespace": pod_data["metadata"]["namespace"],
"pod": pod_data["metadata"]["name"],
"name": container_data["name"]
})
if output and "exited with" not in output:
self.event.evidence = "uname: " + output
break
@handler.subscribe(ExposedPodsHandler)
class ProvePodsHandler(ActiveHunter):
@@ -272,13 +274,14 @@ class ProvePodsHandler(ActiveHunter):
def execute(self):
protocol = "https" if self.event.port == 10250 else "http"
pods_data = json.loads(requests.get("{protocol}://{host}:{port}/pods".format(
pods_raw = requests.get("{protocol}://{host}:{port}/pods".format(
protocol=protocol,
host=self.event.host,
port=self.event.port),
verify=False)
.text)['items']
self.event.evidence = "bound pods: {}".format(len(pods_data))
verify=False).text
if "items" in pods_raw:
pods_data = json.loads(pods_raw)['items']
self.event.evidence = "bound pods: {}".format(len(pods_data))
@handler.subscribe(ExposedRunningPodsHandler)
class ProveRunningPodsHandler(ActiveHunter):
@@ -286,12 +289,13 @@ class ProveRunningPodsHandler(ActiveHunter):
self.event = event
def execute(self):
pods_data = json.loads(requests.get("https://{host}:{port}/runningpods".format(
pods_raw = requests.get("https://{host}:{port}/pods".format(
host=self.event.host,
port=self.event.port),
verify=False)
.text)['items']
self.event.evidence = "running pods: {}".format(len(pods_data))
verify=False).text
if "items" in pods_raw:
pods_data = json.loads(pods_raw)['items']
self.event.evidence = "running pods: {}".format(len(pods_data))
@handler.subscribe(ExposedContainerLogsHandler)
class ProveContainerLogsHandler(ActiveHunter):
@@ -301,18 +305,20 @@ class ProveContainerLogsHandler(ActiveHunter):
self.base_url = "{protocol}://{host}:{port}".format(protocol=protocol, host=self.event.host, port=self.event.port)
def execute(self):
pods_data = json.loads(requests.get(self.base_url + "/pods", verify=False).text)['items']
for pod_data in pods_data:
container_data = next((container_data for container_data in pod_data["spec"]["containers"]), None)
if container_data:
output = requests.get(self.base_url + "/containerLogs/{podNamespace}/{podID}/{containerName}".format(
podNamespace=pod_data["metadata"]["namespace"],
podID=pod_data["metadata"]["name"],
containerName=container_data["name"]
), verify=False)
if output.status_code == 200 and output.text:
self.event.evidence = "{}: {}".format(
container_data["name"],
output.text.encode('utf-8')
)
break
pods_raw = requests.get(self.base_url + "/pods", verify=False).text
if "items" in pods_raw:
pods_data = json.loads(pods_raw)['items']
for pod_data in pods_data:
container_data = next((container_data for container_data in pod_data["spec"]["containers"]), None)
if container_data:
output = requests.get(self.base_url + "/containerLogs/{podNamespace}/{podID}/{containerName}".format(
podNamespace=pod_data["metadata"]["namespace"],
podID=pod_data["metadata"]["name"],
containerName=container_data["name"]
), verify=False)
if output.status_code == 200 and output.text:
self.event.evidence = "{}: {}".format(
container_data["name"],
output.text.encode('utf-8')
)
return