mirror of
https://github.com/aquasecurity/kube-hunter.git
synced 2026-02-28 16:50:25 +00:00
Compare commits
7 Commits
added_docs
...
fix_passiv
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4037f5325 | ||
|
|
d9e651efa5 | ||
|
|
9414e2e6bc | ||
|
|
5a578fd8ab | ||
|
|
ed09849ced | ||
|
|
bf7023d01c | ||
|
|
ef3a51cacc |
23
docs/_kb/KHV052.md
Normal file
23
docs/_kb/KHV052.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
vid: KHV052
|
||||
title: Exposed Pods
|
||||
categories: [Information Disclosure]
|
||||
---
|
||||
|
||||
# {{ page.vid }} - {{ page.title }}
|
||||
|
||||
## Issue description
|
||||
|
||||
An attacker could view sensitive information about pods that are bound to a Node using the exposed /pods endpoint
|
||||
This can be done either by accessing the readonly port (default 10255), or from the secure kubelet port (10250)
|
||||
|
||||
## Remediation
|
||||
|
||||
Ensure kubelet is protected using `--anonymous-auth=false` kubelet flag. Allow only legitimate users using `--client-ca-file` or `--authentication-token-webhook` kubelet flags. This is usually done by the installer or cloud provider.
|
||||
|
||||
Disable the readonly port by using `--read-only-port=0` kubelet flag.
|
||||
|
||||
## References
|
||||
|
||||
- [Kubelet configuration](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)
|
||||
- [Kubelet authentication/authorization](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/)
|
||||
@@ -35,10 +35,7 @@ class ExposedPodsHandler(Vulnerability, Event):
|
||||
|
||||
def __init__(self, pods):
|
||||
Vulnerability.__init__(
|
||||
self,
|
||||
component=Kubelet,
|
||||
name="Exposed Pods",
|
||||
category=InformationDisclosure,
|
||||
self, component=Kubelet, name="Exposed Pods", category=InformationDisclosure, vid="KHV052"
|
||||
)
|
||||
self.pods = pods
|
||||
self.evidence = f"count: {len(self.pods)}"
|
||||
@@ -378,8 +375,9 @@ class SecureKubeletPortHunter(Hunter):
|
||||
container_name="test",
|
||||
cmd="",
|
||||
)
|
||||
# if we get a Method Not Allowed, we know we passed Authentication and Authorization.
|
||||
return self.session.get(run_url, verify=False, timeout=config.network_timeout).status_code == 405
|
||||
# if we get this message, we know we passed Authentication and Authorization, and that the endpoint is enabled.
|
||||
status_code = self.session.post(run_url, verify=False, timeout=config.network_timeout).status_code
|
||||
return status_code == requests.codes.NOT_FOUND
|
||||
|
||||
# returns list of currently running pods
|
||||
def test_running_pods(self):
|
||||
@@ -1139,11 +1137,16 @@ class ProveSystemLogs(ActiveHunter):
|
||||
f"{self.base_url}/" + KubeletHandlers.LOGS.value.format(path="audit/audit.log"),
|
||||
verify=False,
|
||||
timeout=config.network_timeout,
|
||||
).text
|
||||
logger.debug(f"Audit log of host {self.event.host}: {audit_logs[:10]}")
|
||||
# iterating over proctitles and converting them into readable strings
|
||||
proctitles = []
|
||||
for proctitle in re.findall(r"proctitle=(\w+)", audit_logs):
|
||||
proctitles.append(bytes.fromhex(proctitle).decode("utf-8").replace("\x00", " "))
|
||||
self.event.proctitles = proctitles
|
||||
self.event.evidence = f"audit log: {proctitles}"
|
||||
)
|
||||
|
||||
# TODO: add more methods for proving system logs
|
||||
if audit_logs.status_code == requests.status_codes.codes.OK:
|
||||
logger.debug(f"Audit log of host {self.event.host}: {audit_logs.text[:10]}")
|
||||
# iterating over proctitles and converting them into readable strings
|
||||
proctitles = []
|
||||
for proctitle in re.findall(r"proctitle=(\w+)", audit_logs.text):
|
||||
proctitles.append(bytes.fromhex(proctitle).decode("utf-8").replace("\x00", " "))
|
||||
self.event.proctitles = proctitles
|
||||
self.event.evidence = f"audit log: {proctitles}"
|
||||
else:
|
||||
self.event.evidence = "Could not parse system logs"
|
||||
|
||||
Reference in New Issue
Block a user