Post

Kubernetes - Security Contexts

Lab assignment for understanding security contexts in Kubernetes

Kubernetes - Security Contexts

Prerequisites

  • Kubernetes
  • kubectl

Assignment

  • Create a Security Contexts which define privilege and access control settings for a Pod or Container.
  • We will use a custom image that includes a rogue binary for demonstration purposes.
  • This binary allows escalation from a normal user to root in a Kubernetes pod.
1
kubectl run ubuntu --image=spurin/rootshell:latest -o yaml --dry-run=client -- sleep infinity | tee ubuntu_secure.yaml
1
kubectl apply -f ubuntu_secure.yaml
  • With the pod running, let’s execute into it and observe the current user privileges. You’ll notice that we have root access:
1
kubectl exec -it ubuntu -- bash
1
exit
  • Modify our YAML file to include a Security Context that specifies running as a non-root user with a specific UID and GID:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cat <<EOF > ubuntu_secure.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ubuntu
  name: ubuntu
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 1000
  containers:
  - args:
    - sleep
    - infinity
    image: spurin/rootshell:latest
    name: ubuntu
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
EOF
  • Let’s replace the existing pod with our updated configuration. This replacement might take a little longer:
1
kubectl replace --force -f ubuntu_secure.yaml
  • Let’s exec into the pod again. This time, you’ll observe that we’re logged in as a non-root user:
1
kubectl exec -it ubuntu -- bash
  • If we run id, this will confirm we are a non root user:
1
id
  • However, if we run the /rootshell binary this will allow privilege escalation:
1
/rootshell
  • We can even run commands that require root access like apt update -
1
apt update
  • Repeat this command until we exit the container:
1
exit
  • To further secure our pod, we will add an additional Security Context to the container specification, disallowing privilege escalation.:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cat <<EOF > ubuntu_secure.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: ubuntu
  name: ubuntu
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 1000
  containers:
  - args:
    - sleep
    - infinity
    image: spurin/rootshell:latest
    name: ubuntu
    resources: {}
    securityContext:
      allowPrivilegeEscalation: false
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
EOF
  • Again, let’s replace the pod with our new security settings:
1
kubectl replace --force -f ubuntu_secure.yaml
  • Now, exec into the pod one more time:
1
kubectl exec -it ubuntu -- bash
  • And try to escalate privileges, you can try this multiple times, the command will succeed but without root priviledge:
1
/rootshell
  • And issue exit until we fully exit the container:
1
exit
  • Finally, let’s clean up by deleting the pod and removing the YAML file -
1
kubectl delete -f ubuntu_secure.yaml --now ; rm -rf ubuntu_secure.yaml
This post is licensed under CC BY 4.0 by the author.