Skip to content

Commit

Permalink
Added checks on api responses before json.loads, added a quick scanni…
Browse files Browse the repository at this point in the history
…ng option, to scan part of the subnet
  • Loading branch information
danielsagi committed Jun 12, 2018
1 parent c52e684 commit 73a4e83
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 61 deletions.
15 changes: 2 additions & 13 deletions src/core/events/types/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def __init__(self, name, path="", secure=False):
self.name = name
self.secure = secure
self.path = path
self.role = "Node"

def get_name(self):
return self.name
Expand All @@ -58,26 +59,14 @@ def __init__(self, component, name):
self.component = component
self.name = name
self.evidence = ""
self.role = "Node"

def get_name(self):
return self.name

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 """
Expand Down
15 changes: 15 additions & 0 deletions src/modules/discovery/apiserver.py
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion src/modules/discovery/hosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def azure_metadata_discovery(self):
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)))

Expand Down
24 changes: 13 additions & 11 deletions src/modules/hunting/aks.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,19 @@ def __init__(self, event):

# 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()
Expand Down
78 changes: 42 additions & 36 deletions src/modules/hunting/kubelet.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

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)
Expand Down Expand Up @@ -252,18 +252,20 @@ def run(self, command, container):
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):
Expand All @@ -272,26 +274,28 @@ def __init__(self, event):

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):
def __init__(self, event):
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):
Expand All @@ -301,18 +305,20 @@ def __init__(self, event):
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

0 comments on commit 73a4e83

Please sign in to comment.