mirror of
https://github.com/aquasecurity/kube-hunter.git
synced 2026-05-07 01:39:08 +00:00
Merge pull request #90 from aquasecurity/detect-api-server
Only report API Servers that behave like Kubernetes API Servers
This commit is contained in:
@@ -12,17 +12,19 @@ class ApiServer(Service, Event):
|
||||
Service.__init__(self, name="API Server")
|
||||
|
||||
|
||||
# Other devices could have this port open, but we can check to see if it looks like a Kubernetes node
|
||||
# A Kubernetes API server will respond with a JSON message that includes a "code" field for the HTTP status code
|
||||
@handler.subscribe(OpenPortEvent, predicate=lambda x: x.port==443 or x.port==6443)
|
||||
class ApiServerDiscovery(Hunter):
|
||||
"""Api Server Discovery
|
||||
Checks for the existence of a an Api Server
|
||||
Checks for the existence of a an API Server
|
||||
"""
|
||||
def __init__(self, event):
|
||||
self.event = event
|
||||
|
||||
def execute(self):
|
||||
logging.debug("Attempting to discover an Api server")
|
||||
logging.debug("Attempting to discover an API server")
|
||||
main_request = requests.get("https://{}:{}".format(self.event.host, self.event.port), verify=False).text
|
||||
if "code" in main_request:
|
||||
if '"code"' in main_request:
|
||||
self.event.role = "Master"
|
||||
self.publish_event(ApiServer())
|
||||
self.publish_event(ApiServer())
|
||||
|
||||
@@ -24,12 +24,12 @@ class RunningAsPodEvent(Event):
|
||||
|
||||
def get_auth_token(self):
|
||||
try:
|
||||
with open("/run/secrets/kubernetes.io/serviceaccount/token") as token_file:
|
||||
with open("/var/run/secrets/kubernetes.io/serviceaccount/token") as token_file:
|
||||
return token_file.read()
|
||||
except IOError:
|
||||
pass
|
||||
def get_client_cert(self):
|
||||
return "/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
return "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
|
||||
class AzureMetadataApi(Vulnerability, Event):
|
||||
"""Access to the Azure Metadata API exposes information about the machines associated with the cluster"""
|
||||
|
||||
27
src/modules/discovery/test_apiserver.py
Normal file
27
src/modules/discovery/test_apiserver.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import requests_mock
|
||||
|
||||
from apiserver import ApiServer, ApiServerDiscovery
|
||||
from ...core.events.types import Event
|
||||
from ...core.events import handler
|
||||
|
||||
def test_ApiServer():
|
||||
|
||||
with requests_mock.Mocker() as m:
|
||||
m.get('https://mockOther:443', text='elephant')
|
||||
m.get('https://mockKubernetes:443', text='{"code":403}')
|
||||
|
||||
e = Event()
|
||||
e.port = 443
|
||||
e.host = 'mockOther'
|
||||
|
||||
a = ApiServerDiscovery(e)
|
||||
a.execute()
|
||||
|
||||
e.host = 'mockKubernetes'
|
||||
a.execute()
|
||||
|
||||
# We should only generate an ApiServer event for a response that looks like it came from a Kubernetes node
|
||||
@handler.subscribe(ApiServer)
|
||||
class testApiServer(object):
|
||||
def __init__(self, event):
|
||||
assert event.host == 'mockKubernetes'
|
||||
@@ -5,7 +5,8 @@ import uuid
|
||||
import ast
|
||||
|
||||
from ...core.events import handler
|
||||
from ...core.events.types import Vulnerability, Event, OpenPortEvent
|
||||
from ...core.events.types import Vulnerability, Event
|
||||
from ..discovery.apiserver import ApiServer
|
||||
from ...core.types import Hunter, ActiveHunter, KubernetesCluster, RemoteCodeExec, AccessRisk, InformationDisclosure, PrivilegeEscalation
|
||||
|
||||
""" Vulnerabilities """
|
||||
@@ -17,7 +18,7 @@ class ServerApiVersionEndPointAccess(Vulnerability, Event):
|
||||
self.evidence = evidence
|
||||
|
||||
# Passive Hunter
|
||||
@handler.subscribe(OpenPortEvent, predicate=lambda x: x.port == 443 or x.port == 6443)
|
||||
@handler.subscribe(ApiServer)
|
||||
class IsVulnerableToCVEAttack(Hunter):
|
||||
""" Node is running a Kubernetes version vulnerable to critical CVE-2018-1002105 """
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import requests
|
||||
import uuid
|
||||
|
||||
from ...core.events import handler
|
||||
from ...core.events.types import Vulnerability, Event, OpenPortEvent
|
||||
from ...core.events.types import Vulnerability, Event
|
||||
from ..discovery.apiserver import ApiServer
|
||||
from ...core.types import Hunter, ActiveHunter, KubernetesCluster, RemoteCodeExec, AccessRisk, InformationDisclosure
|
||||
|
||||
|
||||
@@ -203,7 +204,7 @@ class ApiServerPassiveHunterFinished(Event):
|
||||
|
||||
|
||||
# Passive Hunter
|
||||
@handler.subscribe(OpenPortEvent, predicate=lambda x: x.port == 443 or x.port == 6443)
|
||||
@handler.subscribe(ApiServer)
|
||||
class AccessApiServerViaServiceAccountToken(Hunter):
|
||||
""" API Server Hunter
|
||||
Accessing the API server within a compromised pod might grant an attacker full control over the cluster
|
||||
|
||||
Reference in New Issue
Block a user