diff --git a/docs/queries/dsl.md b/docs/queries/dsl.md index 3092f7dfe..59729f30d 100644 --- a/docs/queries/dsl.md +++ b/docs/queries/dsl.md @@ -17,33 +17,37 @@ _DSL definition code available [here](https://github.com/DataDog/KubeHound/blob/ ### Retrieve cluster data -| Method | Gremlin equivalent | -| --------------------------- | -------------------------------------------------------- | -| `.cluster([string...])` | `.has("class","Cluster")` | -| `.containers([string...])` | `.has("class","Container")` | -| `.endpoints([int])` | `.has("class","Endpoint")` | -| `.groups([string...])` | `.has("class","Group")` | -| `.hostMounts([string...])` | `.has("class","Volume").has("type", "HostPath")` | -| `.nodes([string...])` | `.has("class","Node")` | -| `.permissions([string...])` | `.has("class","PermissionSet")` | -| `.pods([string...])` | `.has("class","Pod")` | -| `.run([string...])` | `.has("runID", P.within(ids)` | -| `.sas([string...])` | `.has("class","Identity").has("type", "ServiceAccount")` | -| `.services([string...])` | `.has("class","Endpoint").has("exposure", EXTERNAL)` | -| `.users([string...])` | `.has("class","Identity").has("type", "User")` | -| `.volumes([string...])` | `.has("class","Volume")` | +> These methods are defined in the [`KubeHoundTraversalSourceDsl`](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/graph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalSourceDsl.java) class. + +| Method | Gremlin equivalent | Example usage | +| --------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------------- | +| `.cluster([string...])` | `.has("class","Cluster")` | `kh.cluster("kind-kubehound.local")` | +| `.containers([string...])` | `.has("class","Container")` | `kh.cluster("kind-kubehound.local").containers("nginx")` | +| `.endpoints([int])` | `.has("class","Endpoint")` | `kh.cluster("kind-kubehound.local").endpoints(3)` | +| `.hostMounts([string...])` | `.has("class","Volume").has("type", "HostPath")` | `kh.cluster("kind-kubehound.local").hostMounts("/proc")` | +| `.nodes([string...])` | `.has("class","Node")` | `kh.cluster("kind-kubehound.local").nodes("control-plane")` | +| `.permissions([string...])` | `.has("class","PermissionSet")` | `kh.cluster("kind-kubehound.local").permissions("system::kube-controller")` | +| `.pods([string...])` | `.has("class","Pod")` | `kh.cluster("kind-kubehound.local").pods("app-pod")` | +| `.run([string...])` | `.has("runID", P.within(ids))` | `kh.run("01he5ebh73tah762qgdd5k4wqp")` | +| `.services([string...])` | `.has("class","Endpoint").has("exposure", "EXTERNAL")` | `kh.cluster("kind-kubehound.local").services("app-front-proxy")` | +| `.sas([string...])` | `.has("class","Identity").has("type", "ServiceAccount")` | `kh.cluster("kind-kubehound.local").sas("postgres-admin")` | +| `.users([string...])` | `.has("class","Identity").has("type", "User")` | `kh.cluster("kind-kubehound.local").users("user@domain.tld")` | +| `.groups([string...])` | `.has("class","Identity").has("type", "Group")` | `kh.cluster("kind-kubehound.local").groups("engineering")` | +| `.volumes([string...])` | `.has("class","Volume")` | `kh.cluster("kind-kubehound.local").volumes("db-data")` | ### Retrieving attack oriented data +> These methods are defined in the [`KubeHoundTraversalDsl`](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/graph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) class. + | Method | Gremlin equivalent | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `.attacks()` | `.outE().inV().path()` | | `.critical()` | `.has("critical", true)` | -| `.criticalPaths(int)` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/kubegraph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | -| `.criticalPathsFilter(int, string...)` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/kubegraph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | -| `.criticalPathsFreq([maxHops])` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/kubegraph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | +| `.criticalPaths(int)` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/graph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | +| `.criticalPathsFilter(int, string...)` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/graph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | +| `.criticalPathsFreq([maxHops])` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/graph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | | `.hasCriticalPath()` | `.where(__.criticalPaths().limit(1))` | -| `.minHopsToCritical([maxHops])` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/kubegraph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | +| `.minHopsToCritical([maxHops])` | see [KubeHoundTraversalDsl.java](https://github.com/DataDog/KubeHound/blob/main/deployments/kubehound/graph/dsl/kubehound/src/main/java/com/datadog/ase/kubehound/KubeHoundTraversalDsl.java) | For more detailed explanation, please see below. diff --git a/docs/reference/attacks/CE_MODULE_LOAD.md b/docs/reference/attacks/CE_MODULE_LOAD.md index 516f8ec4c..f4a26c395 100644 --- a/docs/reference/attacks/CE_MODULE_LOAD.md +++ b/docs/reference/attacks/CE_MODULE_LOAD.md @@ -11,8 +11,8 @@ mitreAttackTactic: TA0004 - Privilege escalation # CE_MODULE_LOAD -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | Load a kernel module from within an overprivileged container to breakout into the node. @@ -72,4 +72,4 @@ Avoid running containers as the `root` user. Enforce running as an unprivileged + [Compendium Of Container Escapes](https://i.blackhat.com/USA-19/Thursday/us-19-Edwards-Compendium-Of-Container-Escapes-up.pdf) + [Linux Privilege Escalation - Exploiting Capabilities - StefLan's Security Blog](https://steflan-security.com/linux-privilege-escalation-exploiting-capabilities/) -+ [Module Load Breakout](https://raesene.github.io/blog/2023/08/06/fun-with-privileged-container-breakout/) \ No newline at end of file ++ [Module Load Breakout](https://raesene.github.io/blog/2023/08/06/fun-with-privileged-container-breakout/) diff --git a/docs/reference/attacks/CE_NSENTER.md b/docs/reference/attacks/CE_NSENTER.md index a602febc8..b9ba8dfc6 100644 --- a/docs/reference/attacks/CE_NSENTER.md +++ b/docs/reference/attacks/CE_NSENTER.md @@ -11,8 +11,8 @@ mitreAttackTactic: TA0004 - Privilege escalation # CE_NSENTER -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | Container escape via the nsenter built-in linux program that allows executing a binary into another namespace. @@ -86,4 +86,3 @@ Avoid running containers as the `root` user. Enforce running as an unprivileged + [nsenter(1) - Linux manual page](https://man7.org/linux/man-pages/man1/nsenter.1.html) + [Bad Pod #2: Privilege and HostPid](https://bishopfox.com/blog/kubernetes-pod-privilege-escalation#Pod2) + [Debugging containers using nsenter](https://jaanhio.me/blog/nsenter-debug/) - diff --git a/docs/reference/attacks/CE_PRIV_MOUNT.md b/docs/reference/attacks/CE_PRIV_MOUNT.md index fc35f3b45..f1ef17557 100644 --- a/docs/reference/attacks/CE_PRIV_MOUNT.md +++ b/docs/reference/attacks/CE_PRIV_MOUNT.md @@ -11,8 +11,8 @@ mitreAttackTactic: TA0004 - Privilege escalation # CE_PRIV_MOUNT -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | Mount the host disk and gain access to the host via arbitrary filesystem write diff --git a/docs/reference/attacks/CE_SYS_PTRACE.md b/docs/reference/attacks/CE_SYS_PTRACE.md index 2912b1a92..9da79dc4c 100644 --- a/docs/reference/attacks/CE_SYS_PTRACE.md +++ b/docs/reference/attacks/CE_SYS_PTRACE.md @@ -11,8 +11,8 @@ mitreAttackTactic: TA0004 - Privilege escalation # CE_SYS_PTRACE -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | Given the requisite capabilities, abuse the legitimate OS debugging mechanisms to escape the container via attaching to a node process. @@ -84,4 +84,3 @@ Avoid running containers as the `root` user. Enforce running as an unprivileged ## References: + [Container Escape: All You Need is Cap (Capabilities)](https://www.cybereason.com/blog/container-escape-all-you-need-is-cap-capabilities?hs_amp=true) - diff --git a/docs/reference/attacks/CE_UMH_CORE_PATTERN.md b/docs/reference/attacks/CE_UMH_CORE_PATTERN.md index a8377404c..0ecb2c1fc 100644 --- a/docs/reference/attacks/CE_UMH_CORE_PATTERN.md +++ b/docs/reference/attacks/CE_UMH_CORE_PATTERN.md @@ -9,8 +9,8 @@ mitreAttackTactic: TA0004 - Privilege escalation Container escape via the `core_pattern` `usermode_helper` in the case of an exposed `/proc` mount. -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | ## Details @@ -37,7 +37,7 @@ proc /hostproc proc rw,nosuid,nodev,noexec,relatime 0 0 ## Exploitation -First find the path of the container’s filesystem on the host. This can be done by retrieving the current mounts (see [VOLUME_DISCOVER](./VOLUME_DISCOVER.md#checks)). Looks for the `upperdir` value of the overlayfs entry associated with containerd: +First find the path of the container's filesystem on the host. This can be done by retrieving the current mounts (see [VOLUME_DISCOVER](./VOLUME_DISCOVER.md#checks)). Looks for the `upperdir` value of the overlayfs entry associated with containerd: ```bash $ cat /etc/mtab # or `cat /proc/mounts` depending on the system @@ -73,7 +73,7 @@ apt update && apt install gcc gcc -o crash /tmp/crash.c ``` -Next write a shell script to be triggered inside the container’s file system as `shell.sh`: +Next write a shell script to be triggered inside the container's file system as `shell.sh`: ```bash # Reverse shell diff --git a/docs/reference/attacks/CE_VAR_LOG_SYMLINK.md b/docs/reference/attacks/CE_VAR_LOG_SYMLINK.md index f9412700f..4b5558686 100644 --- a/docs/reference/attacks/CE_VAR_LOG_SYMLINK.md +++ b/docs/reference/attacks/CE_VAR_LOG_SYMLINK.md @@ -11,15 +11,15 @@ mitreAttackTactic: TA0006 - Credential Access # CE_VAR_LOG_SYMLINK -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | Arbitrary file reads on the host from a node via an exposed `/var/log` mount. ## Details -A pod running as root and with a mount point to the node’s `/var/log` directory can expose the entire contents of its host filesystem to any user who has access to its logs, enabling an attacker to read arbitrary files on the host node. See [Kubernetes Pod Escape Using Log Mounts](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts) for a more detailed explanation of the technique. +A pod running as root and with a mount point to the node's `/var/log` directory can expose the entire contents of its host filesystem to any user who has access to its logs, enabling an attacker to read arbitrary files on the host node. See [Kubernetes Pod Escape Using Log Mounts](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts) for a more detailed explanation of the technique. ## Prerequisites @@ -65,7 +65,7 @@ Setup the symlink: ln -s / /host/var/log/root_link ``` -Call the kubelet API to read the “logs” and extract pod service account tokens: +Call the kubelet API to read the "logs" and extract pod service account tokens: ```bash $ KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) diff --git a/docs/reference/attacks/CONTAINER_ATTACH.md b/docs/reference/attacks/CONTAINER_ATTACH.md index e9436873d..042fc8a3b 100644 --- a/docs/reference/attacks/CONTAINER_ATTACH.md +++ b/docs/reference/attacks/CONTAINER_ATTACH.md @@ -11,9 +11,9 @@ mitreAttackTactic: TA0008 - Lateral Movement # CONTAINER_ATTACH -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| -| [Pod](../entities/pod.md) | [Container](../entities/container.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | +| Source | Destination | MITRE | +| ------------------------- | ------------------------------------- | -------------------------------------------------------------------- | +| [Pod](../entities/pod.md) | [Container](../entities/container.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | Attach to a container running within a pod given access to the pod. @@ -69,4 +69,4 @@ kubectl describe pod ## References: -+ [Official Kubernetes Documentation](https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/) \ No newline at end of file ++ [Official Kubernetes Documentation](https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/) diff --git a/docs/reference/attacks/ENDPOINT_EXPLOIT.md b/docs/reference/attacks/ENDPOINT_EXPLOIT.md index 9a05e3706..2e64134ac 100644 --- a/docs/reference/attacks/ENDPOINT_EXPLOIT.md +++ b/docs/reference/attacks/ENDPOINT_EXPLOIT.md @@ -12,8 +12,8 @@ mitreAttackTactic: TA0008 - Lateral Movement Represents a network endpoint exposed by a container that could be exploited by an attacker (via means known or unknown). This can correspond to a Kubernetes service, node service, node port, or container port. -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ----------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------ | | [Endpoint](../entities/endpoint.md) | [Container](../entities/container.md) | [Exploitation of Remote Services, T1210](https://attack.mitre.org/techniques/T1210/) | ## Details @@ -51,4 +51,3 @@ None ## References: + [Official Kubernetes documentation: EndpointSlices ](https://kubernetes.io/docs/concepts/storage/volumes/) - diff --git a/docs/reference/attacks/EXPLOIT_CONTAINERD_SOCK.md b/docs/reference/attacks/EXPLOIT_CONTAINERD_SOCK.md index 78d98e900..c60f6cb45 100644 --- a/docs/reference/attacks/EXPLOIT_CONTAINERD_SOCK.md +++ b/docs/reference/attacks/EXPLOIT_CONTAINERD_SOCK.md @@ -11,9 +11,9 @@ mitreAttackTactic: TA0008 - Lateral Movement # EXPLOIT_CONTAINERD_SOCK -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| -| [Container](../entities/container.md) | [Container](../entities/container.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | +| Source | Destination | MITRE | +| ------------------------------------- | ------------------------------------- | -------------------------------------------------------------------- | +| [Container](../entities/container.md) | [Container](../entities/container.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | Container escape via the `containerd.sock` file that allows executing a binary into another container. diff --git a/docs/reference/attacks/EXPLOIT_HOST_READ.md b/docs/reference/attacks/EXPLOIT_HOST_READ.md index 66d0c3c17..12b3025b6 100644 --- a/docs/reference/attacks/EXPLOIT_HOST_READ.md +++ b/docs/reference/attacks/EXPLOIT_HOST_READ.md @@ -11,8 +11,8 @@ mitreAttackTactic: TA0004 - Privilege escalation # EXPLOIT_HOST_READ -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | Exploit an arbitrary read from a sensitive host path mounted into the container to gain execution on the host. diff --git a/docs/reference/attacks/EXPLOIT_HOST_TRAVERSE.md b/docs/reference/attacks/EXPLOIT_HOST_TRAVERSE.md index b29d19ba9..c132b02fc 100644 --- a/docs/reference/attacks/EXPLOIT_HOST_TRAVERSE.md +++ b/docs/reference/attacks/EXPLOIT_HOST_TRAVERSE.md @@ -11,8 +11,8 @@ mitreAttackTactic: TA0006 - Credential Access # EXPLOIT_HOST_TRAVERSE -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------- | ------------------------------- | -------------------------------------------------------------------------- | | [Volume](../entities/volume.md) | [Volume](../entities/volume.md) | [Unsecured Credentials, T1552](https://attack.mitre.org/techniques/T1552/) | This attack represents the ability to steal a K8s API token from a container via access to a mounted parent volume of the `/var/lib/kubelet/pods` directory. @@ -102,4 +102,3 @@ automountServiceAccountToken: false + [The Path Less Traveled: Abusing Kubernetes Defaults (Video)](https://www.youtube.com/watch?v=HmoVSmTIOxM) + [The Path Less Traveled: Abusing Kubernetes Defaults (GitHub)](https://github.com/mauilion/blackhat-2019) + [Securing Kubernetes Clusters by Eliminating Risky Permissions](https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions) - diff --git a/docs/reference/attacks/EXPLOIT_HOST_WRITE.md b/docs/reference/attacks/EXPLOIT_HOST_WRITE.md index a76aba3ca..13d91b84a 100644 --- a/docs/reference/attacks/EXPLOIT_HOST_WRITE.md +++ b/docs/reference/attacks/EXPLOIT_HOST_WRITE.md @@ -11,8 +11,8 @@ mitreAttackTactic: TA0004 - Privilege escalation # EXPLOIT_HOST_WRITE -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ------------------------------------- | --------------------------- | ------------------------------------------------------------------- | | [Container](../entities/container.md) | [Node](../entities/node.md) | [Escape to Host, T1611](https://attack.mitre.org/techniques/T1611/) | Exploit an arbitrary write from a sensitive host path mounted into the container to gain execution on the host. @@ -73,4 +73,3 @@ Avoid running containers as the `root` user. Enforce running as an unprivileged + [Bad Pods: Kubernetes Pod Privilege Escalation](https://bishopfox.com/blog/kubernetes-pod-privilege-escalation) + [7 Ways to Escape a Container](https://www.panoptica.app/research/7-ways-to-escape-a-container) + [Atomic Red Team T1611](https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1611/T1611.md) - diff --git a/docs/reference/attacks/IDENTITY_ASSUME.md b/docs/reference/attacks/IDENTITY_ASSUME.md index 0e84037df..aa069178c 100644 --- a/docs/reference/attacks/IDENTITY_ASSUME.md +++ b/docs/reference/attacks/IDENTITY_ASSUME.md @@ -11,9 +11,9 @@ mitreAttackTactic: TA0004 - Privilege escalation # IDENTITY_ASSUME -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| -| [Container](../entities/container.md), [Node](../entities/node.md) | [Identity](../entities/identity.md) | [Valid Accounts, T1078](https://attack.mitre.org/techniques/T1078/) | +| Source | Destination | MITRE | +| ------------------------------------------------------------------ | ----------------------------------- | ------------------------------------------------------------------- | +| [Container](../entities/container.md), [Node](../entities/node.md) | [Identity](../entities/identity.md) | [Valid Accounts, T1078](https://attack.mitre.org/techniques/T1078/) | Represents the capacity to act as an [Identity](../entities/identity.md) via ownership of a service account token, user PKI certificate, etc. @@ -100,4 +100,4 @@ Use a pod security policy or admission controller to prevent or limit the identi + [Official Kubernetes Documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authentication-strategies) + [CURLing the Kubernetes API](https://nieldw.medium.com/curling-the-kubernetes-api-server-d7675cfc398c) + [Kubelet API Overview](https://www.deepnetwork.com/blog/2020/01/13/kubelet-api.html) -+ [Node AuthN/AuthZ](https://kubernetes.io/docs/reference/access-authn-authz/node/) \ No newline at end of file ++ [Node AuthN/AuthZ](https://kubernetes.io/docs/reference/access-authn-authz/node/) diff --git a/docs/reference/attacks/IDENTITY_IMPERSONATE.md b/docs/reference/attacks/IDENTITY_IMPERSONATE.md index de176002e..272091ce5 100644 --- a/docs/reference/attacks/IDENTITY_IMPERSONATE.md +++ b/docs/reference/attacks/IDENTITY_IMPERSONATE.md @@ -9,9 +9,9 @@ mitreAttackTactic: TA0004 - Privilege escalation With a [user impersonation privilege](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) an attacker can impersonate a more privileged account. -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| -| [PermissionSet](../entities/permissionset.md) | [Identity](../entities/identity.md) | [Valid Accounts, T1078](https://attack.mitre.org/techniques/T1078/) | +| Source | Destination | MITRE | +| --------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------- | +| [PermissionSet](../entities/permissionset.md) | [Identity](../entities/identity.md) | [Valid Accounts, T1078](https://attack.mitre.org/techniques/T1078/) | ## Details diff --git a/docs/reference/attacks/PERMISSION_DISCOVER.md b/docs/reference/attacks/PERMISSION_DISCOVER.md index 95c71a760..19a6f82d9 100644 --- a/docs/reference/attacks/PERMISSION_DISCOVER.md +++ b/docs/reference/attacks/PERMISSION_DISCOVER.md @@ -13,8 +13,8 @@ mitreAttackTactic: TA0007 - Discovery Represents the permissions granted to an identity that can be discovered by an attacker. -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| ----------------------------------- | --------------------------------------------- | -------------------------------------------------------------------------------- | | [Identity](../entities/identity.md) | [PermissionSet](../entities/permissionset.md) | [Permission Groups Discovery, T1069](https://attack.mitre.org/techniques/T1078/) | ## Details @@ -55,4 +55,3 @@ None + [Official Kubernetes Documentation:Using RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) + [Kubernetes RBAC Details](https://octopus.com/blog/k8s-rbac-roles-and-bindings) - diff --git a/docs/reference/attacks/POD_ATTACH.md b/docs/reference/attacks/POD_ATTACH.md index 210a795db..e8772c79e 100644 --- a/docs/reference/attacks/POD_ATTACH.md +++ b/docs/reference/attacks/POD_ATTACH.md @@ -11,9 +11,9 @@ mitreAttackTactic: TA0008 - Lateral Movement # POD_ATTACH -| Source | Destination | MITRE | -| --------------------------- | ------------------------------------- |----------------------------------| -| [Node](../entities/node.md) | [Pod](../entities/pod.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | +| Source | Destination | MITRE | +| --------------------------- | ------------------------- | -------------------------------------------------------------------- | +| [Node](../entities/node.md) | [Pod](../entities/pod.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | Attach to a running K8s pod from a K8s node. @@ -146,4 +146,4 @@ ctr -n k8s.io task exec -t --exec-id full-control 0f36d12d60d12d041df8941 + [Kubernetes API Reference Docs](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#pod-v1-core) + https://iximiuz.com/en/posts/containerd-command-line-clients/ + https://nanikgolang.netlify.app/post/containers/ -+ https://www.mankier.com/8/ctr \ No newline at end of file ++ https://www.mankier.com/8/ctr diff --git a/docs/reference/attacks/POD_CREATE.md b/docs/reference/attacks/POD_CREATE.md index 8dba88abe..1b5411da2 100644 --- a/docs/reference/attacks/POD_CREATE.md +++ b/docs/reference/attacks/POD_CREATE.md @@ -13,8 +13,8 @@ mitreAttackTechnique: "T1053.007 - Scheduled Task/Job: Container Orchestration J Create a pod with significant privilege (`CAP_SYSADMIN`, `hostPath=/`, etc) and schedule on a target node via setting the `nodeName` selector. -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| +| Source | Destination | MITRE | +| --------------------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------- | | [PermissionSet](../entities/permissionset.md) | [Node](../entities/node.md) | [Container Orchestration Job, T1053.007](https://attack.mitre.org/techniques/T1053/007/) | ## Details diff --git a/docs/reference/attacks/POD_EXEC.md b/docs/reference/attacks/POD_EXEC.md index 3f09b25e5..f4be389d7 100644 --- a/docs/reference/attacks/POD_EXEC.md +++ b/docs/reference/attacks/POD_EXEC.md @@ -13,9 +13,9 @@ mitreAttackTactic: TA0008 - Lateral Movement With the correct privileges an attacker can use the Kubernetes API to obtain a shell on a running pod. -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| -| [PermissionSet](../entities/permissionset.md) | [Pod](../entities/pod.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | +| Source | Destination | MITRE | +| --------------------------------------------- | ------------------------- | -------------------------------------------------------------------- | +| [PermissionSet](../entities/permissionset.md) | [Pod](../entities/pod.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | ## Details diff --git a/docs/reference/attacks/POD_PATCH.md b/docs/reference/attacks/POD_PATCH.md index 3418e37bb..6642c246d 100644 --- a/docs/reference/attacks/POD_PATCH.md +++ b/docs/reference/attacks/POD_PATCH.md @@ -13,9 +13,9 @@ mitreAttackTactic: TA0008 - Lateral Movement With the correct privileges an attacker can use the Kubernetes API to modify certain properties of an existing pod and achieve code execution within the pod -| Source | Destination | MITRE | -| ----------------------------------------- | ------------------------------------- |----------------------------------| -| [PermissionSet](../entities/permissionset.md) | [Pod](../entities/pod.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | +| Source | Destination | MITRE | +| --------------------------------------------- | ------------------------- | -------------------------------------------------------------------- | +| [PermissionSet](../entities/permissionset.md) | [Pod](../entities/pod.md) | [Lateral Movement, TA0008](https://attack.mitre.org/tactics/TA0008/) | ## Details diff --git a/docs/reference/entities/common.md b/docs/reference/entities/common.md index faf186e20..eb4303bc4 100644 --- a/docs/reference/entities/common.md +++ b/docs/reference/entities/common.md @@ -4,35 +4,35 @@ Common properties can be set on any vertices within the graph. ## Ownership Information -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| app | `string` | Internal app name extracted from object labels | -| team | `string` | Internal team name extracted from object labels | -| service | `string` | Internal service name extracted from object labels | +| Property | Type | Description | +| -------- | -------- | -------------------------------------------------- | +| app | `string` | Internal app name extracted from object labels | +| team | `string` | Internal team name extracted from object labels | +| service | `string` | Internal service name extracted from object labels | ## Risk Information -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| critical | `bool` | Whether the vertex is a critical asset within the cluster. Critical assets form the termination condition of an attack path and represent an asset that leads to complete cluster compromise | -| compromised | `int` | Enum defining asset compromise for scenario-based simulations | +| Property | Type | Description | +| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| critical | `bool` | Whether the vertex is a critical asset within the cluster. Critical assets form the termination condition of an attack path and represent an asset that leads to complete cluster compromise | +| compromised | `int` | Enum defining asset compromise for scenario-based simulations | ## Store Information -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| storeID | `string` | Unique store database identifier of the store objected generating the vertex | +| Property | Type | Description | +| -------- | -------- | ---------------------------------------------------------------------------- | +| storeID | `string` | Unique store database identifier of the store objected generating the vertex | ## Namespace Information -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| namespace | `string` | Kubernetes namespace to which the object (or its parent) belongs | -| isNamespaced | `bool` | Whether or not the object has an associated namespace | +| Property | Type | Description | +| ------------ | -------- | ---------------------------------------------------------------- | +| namespace | `string` | Kubernetes namespace to which the object (or its parent) belongs | +| isNamespaced | `bool` | Whether or not the object has an associated namespace | ## Run Information -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| runID | `string` | Unique ULID identifying a KubeHound run | -| cluster | `string` | Kubernetes cluster to which the entity belongs | +| Property | Type | Description | +| -------- | -------- | ---------------------------------------------- | +| runID | `string` | Unique ULID identifying a KubeHound run | +| cluster | `string` | Kubernetes cluster to which the entity belongs | diff --git a/docs/reference/entities/container.md b/docs/reference/entities/container.md index a40cbd29e..f6edf346f 100644 --- a/docs/reference/entities/container.md +++ b/docs/reference/entities/container.md @@ -6,32 +6,34 @@ Properties that are interesting to attackers can be set at a Pod level such as h ## Properties -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| name | `string` | Name of the container in Kubernetes | -| image | `string` | Docker the image run by the container | -| command | `[]string` | The container entrypoint| -| args | `[]string` | List of arguments passed to the container | -| capabilities | `[]string` | List of additional [capabilities](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container) added to the container via k8s securityContext | -| privileged | `bool` | Whether the container is run in [privileged](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core) mode | -| privesc | `bool` | Whether the container can gain more privileges than its parent process [details here](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core) | -| hostPid | `bool` | Whether the container can access the host’s PID namespace | -| hostIpc | `bool` | Whether the container can access the host’s IPC namespace | -| hostNetwork | `bool` | Whether the container can access the host’s network namespace| -| runAsUser | `int64` | The user account the container is running under e.g 0 for root | -| ports | `[]string` | List of ports exposed by the container | -| pod | `string` | The name of the pod running the container | -| node | `string` | The name of the node running the container | +| Property | Type | Description | +| ------------ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | `string` | Name of the container in Kubernetes | +| image | `string` | Docker the image run by the container | +| command | `[]string` | The container entrypoint | +| args | `[]string` | List of arguments passed to the container | +| capabilities | `[]string` | List of additional [capabilities](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container) added to the container via k8s securityContext | +| privileged | `bool` | Whether the container is run in [privileged](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core) mode | +| privesc | `bool` | Whether the container can gain more privileges than its parent process [details here](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core) | +| hostPid | `bool` | Whether the container can access the host's PID namespace | +| hostIpc | `bool` | Whether the container can access the host's IPC namespace | +| hostNetwork | `bool` | Whether the container can access the host's network namespace | +| runAsUser | `int64` | The user account the container is running under e.g 0 for root | +| ports | `[]string` | List of ports exposed by the container | +| pod | `string` | The name of the pod running the container | +| node | `string` | The name of the node running the container | ## Common Properties -+ [storeID](./common.md#store-information) + [app](./common.md#ownership-information) -+ [team](./common.md#ownership-information) -+ [service](./common.md#ownership-information) ++ [cluster](./common.md#run-information) + [compromised](./common.md#risk-information) -+ [namespace](./common.md#namespace-information) + [isNamespaced](./common.md#namespace-information) ++ [namespace](./common.md#namespace-information) ++ [runID](./common.md#run-information) ++ [service](./common.md#ownership-information) ++ [storeID](./common.md#store-information) ++ [team](./common.md#ownership-information) ## Definition diff --git a/docs/reference/entities/endpoint.md b/docs/reference/entities/endpoint.md index 23d77170e..f49bb7851 100644 --- a/docs/reference/entities/endpoint.md +++ b/docs/reference/entities/endpoint.md @@ -4,28 +4,29 @@ A network endpoint exposed by a container accessible via a Kubernetes service, e ## Properties -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| name | `string` | Unique endpoint name | -| serviceEndpoint | `string` | Name of the service if the endpoint is exposed outside the cluster via an endpoint slice | -| serviceDns | `string` | FQDN of the service if the endpoint is exposed outside the cluster via an endpoint slice | -| addressType | `string` | Type of the addresses array (IPv4, IPv6, etc) | -| addresses | `string` | Array of addresses exposing the endpoint | -| port | `int` | Exposed port of the endpoint | -| portName | `string` | Name of the exposed port | -| protocol | `string` | Endpoint protocol (TCP, UDP, etc) | -| exposure | `string` | Enum value describing the level of exposure of the endpoint (see [EndpointExposureType](https://github.com/DataDog/KubeHound/tree/main/pkg/kubehound/models/shared/constants.go)) | - +| Property | Type | Description | +| --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | `string` | Unique endpoint name | +| serviceEndpoint | `string` | Name of the service if the endpoint is exposed outside the cluster via an endpoint slice | +| serviceDns | `string` | FQDN of the service if the endpoint is exposed outside the cluster via an endpoint slice | +| addressType | `string` | Type of the addresses array (IPv4, IPv6, etc) | +| addresses | `string` | Array of addresses exposing the endpoint | +| port | `int` | Exposed port of the endpoint | +| portName | `string` | Name of the exposed port | +| protocol | `string` | Endpoint protocol (TCP, UDP, etc) | +| exposure | `string` | Enum value describing the level of exposure of the endpoint (see [EndpointExposureType](https://github.com/DataDog/KubeHound/tree/main/pkg/kubehound/models/shared/constants.go)) | ## Common Properties -+ [storeID](./common.md#store-information) + [app](./common.md#ownership-information) -+ [team](./common.md#ownership-information) -+ [service](./common.md#ownership-information) ++ [cluster](./common.md#run-information) + [compromised](./common.md#risk-information) -+ [namespace](./common.md#namespace-information) + [isNamespaced](./common.md#namespace-information) ++ [namespace](./common.md#namespace-information) ++ [runID](./common.md#run-information) ++ [service](./common.md#ownership-information) ++ [storeID](./common.md#store-information) ++ [team](./common.md#ownership-information) ## Definition diff --git a/docs/reference/entities/identity.md b/docs/reference/entities/identity.md index 4c9a901a3..a1af5c9a6 100644 --- a/docs/reference/entities/identity.md +++ b/docs/reference/entities/identity.md @@ -4,20 +4,22 @@ Identity represents a Kubernetes user or service account. ## Properties -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| name | `string` | Name of the identity principal in Kubernetes | -| type | `string` | Type of identity (user, serviceaccount, etc) | +| Property | Type | Description | +| -------- | -------- | ---------------------------------------------- | +| name | `string` | Name of the identity principal in Kubernetes | +| type | `string` | Type of identity (user, serviceaccount, group) | ## Common Properties -+ [storeID](./common.md#store-information) + [app](./common.md#ownership-information) -+ [team](./common.md#ownership-information) -+ [service](./common.md#ownership-information) ++ [cluster](./common.md#run-information) + [critical](./common.md#risk-information) -+ [namespace](./common.md#namespace-information) + [isNamespaced](./common.md#namespace-information) ++ [namespace](./common.md#namespace-information) ++ [runID](./common.md#run-information) ++ [service](./common.md#ownership-information) ++ [storeID](./common.md#store-information) ++ [team](./common.md#ownership-information) ## Definition diff --git a/docs/reference/entities/node.md b/docs/reference/entities/node.md index 162c7d034..13e57dc50 100644 --- a/docs/reference/entities/node.md +++ b/docs/reference/entities/node.md @@ -4,20 +4,22 @@ A Kubernetes node. Kubernetes runs workloads by placing containers into Pods to ## Properties -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| name | `string` | Name of the node in Kubernetes | +| Property | Type | Description | +| -------- | -------- | ------------------------------ | +| name | `string` | Name of the node in Kubernetes | ## Common Properties -+ [storeID](./common.md#store-information) + [app](./common.md#ownership-information) -+ [team](./common.md#ownership-information) -+ [service](./common.md#ownership-information) ++ [cluster](./common.md#run-information) + [compromised](./common.md#risk-information) + [critical](./common.md#risk-information) -+ [namespace](./common.md#namespace-information) + [isNamespaced](./common.md#namespace-information) ++ [namespace](./common.md#namespace-information) ++ [runID](./common.md#run-information) ++ [service](./common.md#ownership-information) ++ [storeID](./common.md#store-information) ++ [team](./common.md#ownership-information) ## Definition @@ -26,4 +28,3 @@ A Kubernetes node. Kubernetes runs workloads by placing containers into Pods to ## References + [Official Kubernetes documentation](https://kubernetes.io/docs/concepts/architecture/nodes/) - diff --git a/docs/reference/entities/permissionset.md b/docs/reference/entities/permissionset.md index 8fc2edcc7..d7f97a30c 100644 --- a/docs/reference/entities/permissionset.md +++ b/docs/reference/entities/permissionset.md @@ -4,20 +4,22 @@ A permission set represents a Kubernetes RBAC `Role` or `ClusterRole`, which con ## Properties -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| name | `string` | Name of the underlying role in Kubernetes | -| rules | `[]string` | List of strings representing the access granted by the role (see generator function [flattenPolicyRules](https://github.com/DataDog/KubeHound/tree/main/pkg/kubehound/models/converter/graph.go))| +| Property | Type | Description | +| -------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | `string` | Name of the underlying role in Kubernetes | +| rules | `[]string` | List of strings representing the access granted by the role (see generator function [flattenPolicyRules](https://github.com/DataDog/KubeHound/tree/main/pkg/kubehound/models/converter/graph.go)) | ## Common Properties -+ [storeID](./common.md#store-information) + [app](./common.md#ownership-information) -+ [team](./common.md#ownership-information) -+ [service](./common.md#ownership-information) ++ [cluster](./common.md#run-information) + [critical](./common.md#risk-information) -+ [namespace](./common.md#namespace-information) + [isNamespaced](./common.md#namespace-information) ++ [namespace](./common.md#namespace-information) ++ [runID](./common.md#run-information) ++ [service](./common.md#ownership-information) ++ [storeID](./common.md#store-information) ++ [team](./common.md#ownership-information) ## Definition @@ -26,4 +28,3 @@ A permission set represents a Kubernetes RBAC `Role` or `ClusterRole`, which con ## References + [Official Kubernetes documentation](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) - diff --git a/docs/reference/entities/pod.md b/docs/reference/entities/pod.md index b34b6214c..49d90080b 100644 --- a/docs/reference/entities/pod.md +++ b/docs/reference/entities/pod.md @@ -4,23 +4,25 @@ A Kubernetes pod - the smallest deployable units of computing that you can creat ## Properties -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| name | `string` | Name of the pod in Kubernetes | -| shareProcessNamespace | `bool` | whether all the containers in the pod share a process namespace (details [here](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#pod-v1-core)) | -| serviceAccount | `string` | The name of the `serviceaccount` used to run this pod. See [Kubernetes documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) for further details | -| node | `string` | The name of the node running the pod | +| Property | Type | Description | +| --------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | `string` | Name of the pod in Kubernetes | +| shareProcessNamespace | `bool` | whether all the containers in the pod share a process namespace (details [here](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#pod-v1-core)) | +| serviceAccount | `string` | The name of the `serviceaccount` used to run this pod. See [Kubernetes documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) for further details | +| node | `string` | The name of the node running the pod | ## Common Properties -+ [storeID](./common.md#store-information) + [app](./common.md#ownership-information) -+ [team](./common.md#ownership-information) -+ [service](./common.md#ownership-information) ++ [cluster](./common.md#run-information) + [compromised](./common.md#risk-information) + [critical](./common.md#risk-information) -+ [namespace](./common.md#namespace-information) + [isNamespaced](./common.md#namespace-information) ++ [namespace](./common.md#namespace-information) ++ [runID](./common.md#run-information) ++ [service](./common.md#ownership-information) ++ [storeID](./common.md#store-information) ++ [team](./common.md#ownership-information) ## Definition @@ -29,4 +31,3 @@ A Kubernetes pod - the smallest deployable units of computing that you can creat ## References + [Official Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/pods/) - diff --git a/docs/reference/entities/volume.md b/docs/reference/entities/volume.md index aa98d75b2..a3c7b32f1 100644 --- a/docs/reference/entities/volume.md +++ b/docs/reference/entities/volume.md @@ -4,22 +4,24 @@ Volume represents a volume mounted in a container and exposed by a node. ## Properties -| Property | Type | Description | -| ----------------| --------- |----------------------------------------| -| name | `string` | Name of the volume mount in the container spec | -| type | `string` | Type of volume mount (host/projected/etc). See [Kubernetes documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volume-v1-core) for details | -| sourcePath | `string` | The path of the volume in the host (i.e node) filesystem | -| mountPath | `string` | The path of the volume in the container filesystem | -| readonly | `bool` | Whether the volume has been mounted with `readonly` access | +| Property | Type | Description | +| ---------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | `string` | Name of the volume mount in the container spec | +| type | `string` | Type of volume mount (host/projected/etc). See [Kubernetes documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volume-v1-core) for details | +| sourcePath | `string` | The path of the volume in the host (i.e node) filesystem | +| mountPath | `string` | The path of the volume in the container filesystem | +| readonly | `bool` | Whether the volume has been mounted with `readonly` access | ## Common Properties -+ [storeID](./common.md#store-information) + [app](./common.md#ownership-information) -+ [team](./common.md#ownership-information) -+ [service](./common.md#ownership-information) -+ [namespace](./common.md#namespace-information) ++ [cluster](./common.md#run-information) + [isNamespaced](./common.md#namespace-information) ++ [namespace](./common.md#namespace-information) ++ [runID](./common.md#run-information) ++ [service](./common.md#ownership-information) ++ [storeID](./common.md#store-information) ++ [team](./common.md#ownership-information) ## Definition @@ -28,4 +30,3 @@ Volume represents a volume mounted in a container and exposed by a node. ## References + [Official Kubernetes documentation](https://kubernetes.io/docs/concepts/storage/volumes/) - diff --git a/docs/reference/graph.schema.json b/docs/reference/graph.schema.json new file mode 100644 index 000000000..78edfe103 --- /dev/null +++ b/docs/reference/graph.schema.json @@ -0,0 +1,231 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/GraphSchema", + "definitions": { + "GraphSchema": { + "type": "object", + "additionalProperties": false, + "properties": { + "apiVersion": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/Metadata" + }, + "spec": { + "$ref": "#/definitions/Spec" + } + }, + "required": [ + "apiVersion", + "kind", + "metadata", + "spec" + ], + "title": "GraphSchema" + }, + "Metadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "name", + "version" + ], + "title": "Metadata" + }, + "Spec": { + "type": "object", + "additionalProperties": false, + "properties": { + "enums": { + "type": "array", + "items": { + "$ref": "#/definitions/Enum" + } + }, + "vertices": { + "type": "array", + "items": { + "$ref": "#/definitions/Vertex" + } + }, + "verticeProperties": { + "type": "array", + "items": { + "$ref": "#/definitions/VerticeProperty" + } + }, + "edges": { + "type": "array", + "items": { + "$ref": "#/definitions/Edge" + } + }, + "edgeProperties": { + "type": "array", + "items": {} + }, + "relationships": { + "type": "array", + "items": { + "$ref": "#/definitions/Relationship" + } + } + }, + "required": [ + "edgeProperties", + "edges", + "enums", + "relationships", + "verticeProperties", + "vertices" + ], + "title": "Spec" + }, + "Edge": { + "type": "object", + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "description", + "label" + ], + "title": "Edge" + }, + "Vertex": { + "type": "object", + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "description", + "label" + ], + "title": "Vertex" + }, + "Enum": { + "type": "object", + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "values": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "label", + "values" + ], + "title": "Enum" + }, + "Relationship": { + "type": "object", + "additionalProperties": false, + "properties": { + "from": { + "$ref": "#/definitions/From" + }, + "to": { + "$ref": "#/definitions/From" + }, + "label": { + "type": "string" + } + }, + "required": [ + "from", + "label", + "to" + ], + "title": "Relationship" + }, + "VerticeProperty": { + "type": "object", + "additionalProperties": false, + "properties": { + "property": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/Type" + }, + "labels": { + "type": "array", + "items": { + "$ref": "#/definitions/From" + } + }, + "description": { + "type": "string" + }, + "array": { + "type": "boolean" + }, + "example": { + "type": "string" + }, + "enum": { + "type": "string" + } + }, + "required": [ + "description", + "labels", + "property", + "type" + ], + "title": "VerticeProperty" + }, + "From": { + "type": "string", + "enum": [ + "Container", + "Endpoint", + "Identity", + "Node", + "PermissionSet", + "Pod", + "Volume" + ], + "title": "From" + }, + "Type": { + "type": "string", + "enum": [ + "STRING", + "INTEGER", + "BOOL" + ], + "title": "Type" + } + } +} diff --git a/docs/reference/graph.yaml b/docs/reference/graph.yaml new file mode 100644 index 000000000..73d3c3d83 --- /dev/null +++ b/docs/reference/graph.yaml @@ -0,0 +1,571 @@ +# yaml-language-server: $schema=graph.schema.json +apiVersion: app.kubehound.io/models/v1 +kind: GraphSchema +metadata: + name: Kubehound Graph Schema + version: v1 +spec: + # Define the enumerations used in properties. + enums: + - label: AddressType + values: + - IPv4 + - IPv6 + - label: Protocol + values: + - TCP + - UDP + - label: EndpointExposure + values: + - None + - ClusterIP + - NodeIP + - External + - Public + - label: IdentityType + values: + - User + - ServiceAccount + - Group + - label: VolumeType + values: + - HostPath + - EmptyDir + - ConfigMap + - Secret + - PersistentVolumeClaim + - Projected + - DownwardAPI + - CSI + - Ephemeral + - AzureDisk + - AzureFile + - CephFS + - Cinder + - FC + - FlexVolume + - Flocker + - GCEPersistentDisk + - Glusterfs + - ISCSI + - NFS + - PhotonPersistentDisk + - PortworxVolume + - Quobyte + - RBD + - ScaleIO + - StorageOS + - VsphereVolume + + # Define the vertices in the graph. + vertices: + - label: Container + description: >- + A container image running on a Kubernetes pod. Containers in a Pod are + co-located and co-scheduled to run on the same node. + - label: Endpoint + description: >- + A network endpoint exposed by a container accessible via a Kubernetes + service, external node port or cluster IP/port tuple. + - label: Identity + description: Identity represents a Kubernetes user or service account. + - label: Node + description: >- + A Kubernetes node. Kubernetes runs workloads by placing containers into + Pods to run on Nodes. A node may be a virtual or physical machine, + depending on the cluster. + - label: PermissionSet + description: >- + A permission set represents a Kubernetes RBAC Role or ClusterRole, which + contain rules that represent a set of permissions that has been bound to + an identity via a RoleBinding or ClusterRoleBinding. Permissions are + purely additive (there are no "deny" rules). + - label: Pod + description: >- + A Kubernetes pod - the smallest deployable units of computing that you can + create and manage in Kubernetes. + - label: Volume + description: Volume represents a volume mounted in a container and exposed by a node. + + # Define the properties for each vertex in the graph. + verticeProperties: + - property: app + type: STRING + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + description: Internal app name extracted from object labels. + - property: cluster + type: STRING + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + - Volume + description: Kubernetes cluster to which the entity belongs. + - property: compromised + type: INTEGER + labels: + - Container + - Endpoint + - Node + - Pod + description: Enum defining asset compromise for scenario-based simulations. + - property: critical + type: BOOL + labels: + - Identity + - Node + - PermissionSet + - Pod + description: >- + Whether the vertex is a critical asset within the cluster. Critical assets + form the termination condition of an attack path and represent an asset + that leads to complete cluster compromise. + - property: isNamespace + type: BOOL + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + description: Whether or not the object has an associated namespace. + - property: namespace + type: STRING + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + description: Kubernetes namespace to which the object (or its parent) belongs. + - property: runID + type: STRING + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + - Volume + description: Unique ULID identifying a KubeHound run. + - property: service + type: STRING + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + description: Internal service name extracted from object labels. + - property: storeID + type: STRING + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + description: >- + Unique store database identifier of the store objected generating the + vertex. + - property: team + type: STRING + labels: + - Container + - Endpoint + - Identity + - Node + - PermissionSet + - Pod + description: Internal team name extracted from object labels. + - property: name + type: STRING + labels: + - Container + description: Name of the container in Kubernetes. + - property: image + type: STRING + labels: + - Container + description: Docker the image run by the container. + - property: command + type: STRING + array: true + labels: + - Container + description: List of command used as the container entrypoint. + - property: args + type: STRING + array: true + labels: + - Container + description: List of arguments passed to the container. + - property: capabilities + type: STRING + array: true + labels: + - Container + description: >- + List of additional capabilities added to the container via k8s + securityContext. + example: 'CAP_NET_ADMIN,CAP_SYS_TIME' + - property: privilegied + type: BOOL + labels: + - Container + description: Whether the container is run in privileged mode. + - property: privesc + type: BOOL + labels: + - Container + description: Whether the container can gain more privileges than its parent process. + - property: hostPid + type: BOOL + labels: + - Container + description: Whether the container can access the host's PID namespace. + - property: hostIpc + type: BOOL + labels: + - Container + description: Whether the container can access the host's IPC namespace. + - property: hostNetwork + type: BOOL + labels: + - Container + description: Whether the container can access the host's network namespace. + - property: runAsUser + type: INTEGER + labels: + - Container + description: The user account uid the container is running under e.g 0 for root. + - property: ports + type: STRING + array: true + labels: + - Container + description: List of ports exposed by the container. + example: '8080,8443' + - property: pod + type: STRING + labels: + - Container + description: The name of the pod running the container. + - property: node + type: STRING + labels: + - Container + description: The name of the node running the container. + - property: name + type: STRING + labels: + - Endpoint + description: Unique endpoint name. + - property: serviceEndpoint + type: STRING + labels: + - Endpoint + description: >- + Name of the service if the endpoint is exposed outside the cluster via an + endpoint slice. + - property: serviceDns + type: STRING + labels: + - Endpoint + description: >- + FQDN of the service if the endpoint is exposed outside the cluster via an + endpoint slice. + - property: addressType + type: STRING + labels: + - Endpoint + description: Type of the addresses array (IPv4 or IPv6). + enum: AddressType + - property: addresses + type: STRING + array: true + labels: + - Endpoint + description: Array of addresses exposing the endpoint. + example: 172.17.8.24 + - property: port + type: INTEGER + labels: + - Endpoint + description: Port exposed by the endpoint. + - property: portName + type: STRING + labels: + - Endpoint + description: Name of the exposed port. + - property: protocol + type: STRING + labels: + - Endpoint + description: Endpoint protocol. + enum: Protocol + - property: exposure + type: STRING + labels: + - Endpoint + description: Enum value describing the level of exposure of the endpoint. + enum: EndpointExposure + - property: name + type: STRING + labels: + - Identity + description: Name of the identity principal in Kubernetes + - property: type + type: STRING + labels: + - Identity + description: Type of identity + enum: IdentityType + - property: name + type: STRING + labels: + - Node + description: Name of the node in Kubernetes. + - property: name + type: STRING + labels: + - PermissionSet + description: Name of the underlying role in Kubernetes + - property: role + type: STRING + labels: + - PermissionSet + description: Role name associated to the permission. + - property: roleBinding + type: STRING + labels: + - PermissionSet + description: Kubernetes role binding. + - property: rules + type: STRING + array: true + labels: + - PermissionSet + description: List of rules associated with the permission set. + - property: name + type: STRING + labels: + - Pod + description: Name of the pod in Kubernetes. + - property: shareProcessNamespace + type: BOOL + labels: + - Pod + description: Whether all the containers in the pod share a process namespace. + - property: serviceAccount + type: STRING + labels: + - Pod + description: The name of the serviceaccount used to run this pod. + - property: node + type: STRING + labels: + - Pod + description: The name of the node running the pod. + - property: name + type: STRING + labels: + - Volume + description: Name of the volume mount in the container spec. + - property: type + type: STRING + labels: + - Volume + description: Type of volume mount (host/projected/etc). + enum: VolumeType + - property: sourcePath + type: STRING + labels: + - Volume + description: The path of the volume in the host (i.e node) filesystem. + - property: mountPath + type: STRING + labels: + - Volume + description: The path where the volume is mounted in the container. + - property: readOnly + type: BOOL + labels: + - Volume + description: Whether the volume is mounted in read-only mode. + + # Define the edges in the graph. + edges: + - label: CE_MODULE_LOAD + description: A container can load a kernel module on the node. + - label: CE_NSENTER + description: >- + Container escape via the nsenter built-in linux program that allows + executing a binary into another namespace. + - label: CE_PRIV_MOUNT + description: >- + Mount the host disk and gain access to the host via arbitrary filesystem + write + - label: CE_SYS_TRACE + description: >- + Given the requisite capabilities, abuse the legitimate OS debugging + mechanisms to escape the container via attaching to a node process. + - label: CE_UMH_CORE_PATTERN + description: >- + Abuse the User Mode Helper (UMH) mechanism to execute arbitrary code in + the host. + - label: CE_VAR_LOG_SYMLINK + description: Abuse the /var/log symlink to gain access to the host filesystem. + - label: EXPLOIT_HOST_READ + description: Read sensitive files on the host. + - label: EXPLOIT_HOST_WRITE + description: Write sensitive files on the host. + - label: EXPLOIT_CONTAINERD_SOCK + description: Exploit the containerd socket to gain access to the host. + - label: IDENTITY_ASSUME + description: >- + Represents the capacity to act as an Identity via ownership of a service + account token, user PKI certificate, etc. + - label: CONTAINER_ATTACH + description: >- + Attach to a running container to execute commands or inspect the + container. + - label: ENDPOINT_EXPLOIT + description: >- + Represents a network endpoint exposed by a container that could be + exploited by an attacker (via means known or unknown). This can correspond + to a Kubernetes service, node service, node port, or container port. + - label: PERMISSION_DISCOVER + description: Discover permissions granted to an identity. + - label: EXPLOIT_HOST_TRAVERSE + description: >- + This attack represents the ability to steal a K8s API token from a + container via access to a mounted parent volume of the + /var/lib/kubelet/pods directory. + - label: TOKEN_STEAL + description: >- + This attack represents the ability to steal a K8s API token from an + accessible volume. + - label: ROLE_BIND + description: Bind a role to an identity. + - label: IDENTITY_IMPERSONATE + description: Impersonate an identity. + - label: POD_ATTACH + description: Attach to a running pod to execute commands or inspect the pod. + - label: POD_CREATE + description: Create a pod on a node. + - label: POD_EXEC + description: Execute a command in a pod. + - label: POD_PATCH + description: Patch a pod on a node. + - label: SHARE_PS_NAMESPACE + description: All containers in a pod share the same process namespace. + - label: TOKEN_BRUTEFORCE + description: Bruteforce a token. + - label: TOKEN_LIST + description: List tokens. + - label: VOLUME_ACCESS + description: Access a volume mounted in a container. + - label: VOLUME_DISCOVER + description: Discover volumes mounted in a container. + + # Define the properties for each edge in the graph. + edgeProperties: [] + + # Define the relationships between vertices and edges in the graph. + relationships: + - from: Container + to: Container + label: SHARE_PS_NAMESPACE + - from: Container + to: Node + label: CE_MODULE_LOAD + - from: Container + to: Container + label: CE_NSENTER + - from: Container + to: Node + label: CE_PRIV_MOUNT + - from: Container + to: Node + label: CE_SYS_TRACE + - from: Container + to: Node + label: CE_UMH_CORE_PATTERN + - from: Container + to: Node + label: CE_VAR_LOG_SYMLINK + - from: Container + to: Node + label: EXPLOIT_HOST_READ + - from: Container + to: Node + label: EXPLOIT_HOST_WRITE + - from: Container + to: Container + label: EXPLOIT_CONTAINERD_SOCK + - from: Container + to: Identity + label: IDENTITY_ASSUME + - from: Container + to: Volume + label: VOLUME_DISCOVER + - from: Pod + to: Container + label: CONTAINER_ATTACH + - from: Endpoint + to: Container + label: ENDPOINT_EXPLOIT + - from: Identity + to: PermissionSet + label: PERMISSION_DISCOVER + - from: Volume + to: Volume + label: EXPLOIT_HOST_TRAVERSE + - from: Volume + to: Identity + label: TOKEN_STEAL + - from: Node + to: Identity + label: IDENTITY_ASSUME + - from: Node + to: Pod + label: POD_ATTACH + - from: Node + to: Volume + label: VOLUME_ACCESS + - from: PermissionSet + to: Identity + label: IDENTITY_IMPERSONATE + - from: PermissionSet + to: Node + label: POD_CREATE + - from: PermissionSet + to: Node + label: POD_EXEC + - from: PermissionSet + to: Node + label: POD_PATCH + - from: PermissionSet + to: PermissionSet + label: ROLE_BIND + - from: PermissionSet + to: Identity + label: TOKEN_BRUTEFORCE + - from: PermissionSet + to: Identity + label: TOKEN_LIST