pod_escape_log

Home

This document demonstrates a security vulnerability where a pod with hostPath access to /var/log can manipulate log files of other pods on the same node. By replacing a target pod's log file (e.g., 0.log) with a symbolic link to a sensitive file on the node (like /etc/passwd or /etc/kubernetes/kubelet.conf), an attacker can potentially read these sensitive files by accessing the logs through the Kubelet's log endpoint.

Caution: Granting pods hostPath access, especially to sensitive directories like /var/log, carries significant security risks. This example illustrates one such risk. Always follow the principle of least privilege.

1. Attacker Pod Setup (escaper)

First, we deploy a pod (escaper) that mounts the node's /var/log directory into its own /var/log/host path.

  1. Create the escaper Pod manifest (escaper.yaml):

    cat << EOF > escaper.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: escaper
    spec:
      containers:
      - name: escaper
        image: nginx # Any image that allows shell access can be used
        volumeMounts:
        - name: logs
          mountPath: /var/log/host
      # nodeSelector: # Optionally, select a specific node to run this pod on
      #   kubernetes.io/hostname: your-target-node
      volumes:
      - name: logs
        hostPath:
          path: /var/log/ # Mounts the entire /var/log from the host
          type: Directory
    EOF
  2. Deploy the escaper Pod:

    kubectl create -f escaper.yaml

2. Targeting Another Pod's Logs

Next, from within the escaper pod, we will navigate to the log directory of a target pod and replace its log files with symbolic links to sensitive files on the node.

  1. Access the escaper pod's shell:

  2. Inside the escaper pod, perform the following:

    • Navigate to the host's pod log directory:

    • List available pod log directories to identify a target. Each directory here typically corresponds to NAMESPACE_POD-NAME_POD-UID.

    • Choose a target pod's log directory and container log subdirectory. Each pod log directory is typically named in the format NAMESPACE_PODNAME_PODUID. For example, if you find a directory named default_victim-pod_some-uid and it has a container log subdirectory victim-container, you would:

      (Replace NAMESPACE_PODNAME_PODUID and CONTAINER_NAME with actual names from your environment.)

    • Manipulate the log files. For instance, replace 0.log with a symlink to /etc/passwd and 1.log with a symlink to /etc/kubernetes/kubelet.conf. You might need to remove existing log files first.

      (Corrected "passswd" to "passwd". Used ln -sf for force overwrite if link exists.)

    • Exit the escaper pod's shell:

3. Attempting Access via API Server (kubectl logs)

Attempting to read the manipulated logs via kubectl logs (which goes through the Kubernetes API server) will likely fail or show an error, as the API server expects actual log files, not arbitrary file content via symlinks that point outside the standard log structure.

  1. Identify the target pod and its namespace. (This is the pod whose logs you manipulated, e.g., victim-pod in namespace default).

  2. Attempt to fetch logs:

    You will likely see an error message, such as "unsupported log format" or similar, because the content of /etc/passwd is not what kubectl logs expects.

4. Direct Access via Kubelet Log Endpoint

The Kubelet on each node also serves logs directly via an HTTPS endpoint (typically port 10250). If an attacker can reach this endpoint with appropriate credentials (often found on the node, e.g., /etc/kubernetes/pki/apiserver-kubelet-client.key and .crt), they can read the content of the files pointed to by the symbolic links.

Note: The following commands are typically run from the Kubernetes node itself or a machine that has network access to the node's Kubelet port and possesses the necessary client certificates.

  1. Identify the target node's IP address (e.g., 10.10.2.35 in the original example) and the full path to the manipulated log file as seen by the Kubelet. This path is usually /var/log/pods/NAMESPACE_POD-NAME_POD-UID/CONTAINER-NAME/X.log.

  2. Use curl to fetch the content: Replace NODE_IP, NAMESPACE_PODNAME_PODUID, and CONTAINER_NAME with actual values.

    • To get the content of /etc/passwd (linked to 0.log):

    • To get the content of /etc/kubernetes/kubelet.conf (linked to 1.log):

    • To get the content of the copied passwd_copy_test file:

Example curl Output

The following is an example of verbose output from one such curl command, showing successful retrieval of file content (in this case, resembling /etc/passwd):

(Marked as text and generalized placeholders. Also added comments for clarity.)

Home

Last updated