Skip to content

Commit

Permalink
feat(scenarios): add pss misconfiguration
Browse files Browse the repository at this point in the history
  • Loading branch information
Ric Featherstone authored and 06kellyjac committed Dec 21, 2023
1 parent 6410a5a commit a3fc301
Show file tree
Hide file tree
Showing 6 changed files with 570 additions and 0 deletions.
23 changes: 23 additions & 0 deletions scenarios/config/pss-misconfiguration/tasks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
category: CNSecCon
difficulty: CNSecCon
kind: cp.simulator/scenario:1.0.0
objective: Fix misconfigurations
tasks:
"1":
hints:
- penalty: 10
text: luckily, pod security is namespaced nowadays!
- penalty: 10
text: who controls the controllers? they might have thought they are exempt from security policies...but be very careful when you attempt to change their mind!
- penalty: 10
text: https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller
- penalty: 10
text: security does not apply to ancient Pods
sortOrder: 1
startingPoint:
mode: pod
podName: admin
podNamespace: platform
podHost: master-0
summary: Can you fix the Pod Security misconfigurations so that the attacker's Pod can't be admitted anymore in the cluster?
name: pss-misconfiguration
9 changes: 9 additions & 0 deletions scenarios/playbooks/pss-misconfiguration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---

- name: PSS Misconfiguration
hosts: bastion:master-1
become: yes
vars:
state: present
roles:
- pss-misconfiguration
156 changes: 156 additions & 0 deletions scenarios/roles/pss-misconfiguration/files/manifests/01-scenario.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
apiVersion: v1
kind: Namespace
metadata:
name: dev-app-factory
labels:
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/enforce: privileged
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: dev-app-factory
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
name: nginx-pod
securityContext:
allowPrivilegeEscalation: true
runAsNonRoot: false
runAsUser: 0
capabilities:
add: ["SETUID", "SETGID", "SYS_CHROOT","CHOWN","KILL"]
---
apiVersion: v1
kind: Namespace
metadata:
name: platform
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: platform-admin
namespace: platform
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: platform-admin
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- delete
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- "apps"
resources:
- deployments
- daemonsets
- statefulsets
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: platform-admin-list
rules:
- apiGroups:
- ""
resources:
- namespaces
- resourcequotas
- limitranges
resourceNames:
- "dev-app-factory"
verbs:
- get
- list
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: platform-admin-bind
namespace: dev-app-factory
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: platform-admin
subjects:
- kind: ServiceAccount
name: platform-admin
namespace: platform
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: platform-admin-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: platform-admin-list
subjects:
- kind: ServiceAccount
name: platform-admin
namespace: platform
---
apiVersion: v1
kind: Pod
metadata:
name: admin
namespace: platform
spec:
serviceAccountName: platform-admin
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- operator: Exists
dnsPolicy: ClusterFirst
restartPolicy: Always
containers:
- image: docker.io/controlplaneoffsec/kubectl:latest
command: ["sleep", "2d"]
name: admin
imagePullPolicy: Always
volumeMounts:
- name: dm9sltetcm8
mountPath: /etc/kubernetes/manifests
readOnly: true
- name: dm9sltitcnc
mountPath: /etc/kubërnëtës
volumes:
- name: dm9sltetcm8
hostPath:
path: /etc/kubernetes/manifests
- name: dm9sltitcnc
hostPath:
path: /opt/k8s-upgrade
180 changes: 180 additions & 0 deletions scenarios/roles/pss-misconfiguration/files/manifests/02-flag-job.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: cp-checker
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cp-checker
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- create
- patch
- update
- apiGroups:
- "apps"
resources:
- deployments
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cp-checker-list
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cp-checker-bind
namespace: dev-app-factory
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cp-checker
subjects:
- kind: ServiceAccount
name: cp-checker
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cp-checker-list-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cp-checker-list
subjects:
- kind: ServiceAccount
name: cp-checker
namespace: kube-system
---
apiVersion: batch/v1
kind: Job
metadata:
name: namespace-checker
namespace: kube-system
spec:
backoffLimit: 999999999
template:
spec:
serviceAccountName: cp-checker
containers:
- name: namespace-checker
image: nixery.dev/shell/kubectl/curl/jq
command: ["bash", "-c"]
args:
- |
set -Eeuo pipefail
PSA_LEVEL='"restricted"';
function NAMESPACE_LABEL_CHECK {
(kubectl get ns dev-app-factory -ojson | jq '.metadata.labels."pod-security.kubernetes.io/enforce"')
}
# Waiting for namespace label to change
while [[ $(NAMESPACE_LABEL_CHECK) != $PSA_LEVEL ]];
do
sleep 10
done
(kubectl create secret generic flag-xyz --from-literal=flag=flag_ctf{MISCONFIG_GOT_PSA_LEVEL_WRONG} --namespace=dev-app-factory)
restartPolicy: Never
---
apiVersion: batch/v1
kind: Job
metadata:
name: psa-config-checker
namespace: kube-system
spec:
backoffLimit: 999999999
template:
spec:
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- operator: Exists
serviceAccountName: cp-checker
containers:
- name: psa-config-checker
image: docker.io/controlplaneoffsec/kubectl:latest
command: ["bash", "-c"]
args:
- |
set -Eeuo pipefail
# Waiting for the psa exemption to be removed, and ensure the defaults not be changed
until ! grep "system:serviceaccount:kube-system:replicaset-controller" /master/opt/k8s-upgrade/psa-config.yaml && grep "kube-system" /master/opt/k8s-upgrade/psa-config.yaml && grep "platform" /master/opt/k8s-upgrade/psa-config.yaml;
do
sleep 10
done
(kubectl create secret generic flag-wasd --from-literal=flag=flag_ctf{MISCONFIG_GOT_PSA_EXEMPTIONS_WRONG} --namespace=dev-app-factory)
volumeMounts:
- name: psaconfig
mountPath: /master/opt/k8s-upgrade/
readOnly: true
volumes:
- name: psaconfig
hostPath:
path: /opt/k8s-upgrade/
restartPolicy: Never
---
apiVersion: batch/v1
kind: Job
metadata:
name: pod-checker
namespace: kube-system
spec:
backoffLimit: 999999999
template:
spec:
serviceAccountName: cp-checker
containers:
- name: pod-checker
image: nixery.dev/shell/kubectl/curl/jq
command: ["bash", "-c"]
args:
- |
set -Eeuo pipefail
NS_MSG="No resources found in dev-app-factory namespace.";
POD_FORBID_EVENT="pods.*is forbidden: violates PodSecurity.*nginx-pod"
function POD_RUNNING {
(kubectl get pods -n dev-app-factory 2>&1)
}
function DEPLOY_SECURITY_WARNING_EVENT {
(kubectl get deploy nginx -n dev-app-factory -ojson | jq '.status.conditions[-1] | select(.reason=="FailedCreate") | .message ')
}
# Wait for Pod to be deleted for good and forbidden by PSS
until [[ $(POD_RUNNING) == "${NS_MSG}" && $(DEPLOY_SECURITY_WARNING_EVENT) =~ $POD_FORBID_EVENT ]];
do
sleep 10
done
(kubectl create secret generic flag-gotit --from-literal=flag=flag_ctf{MISCONFIG_PSS_HASHJACK_SAD_BLOCKED} --namespace=dev-app-factory)
restartPolicy: Never
Loading

0 comments on commit a3fc301

Please sign in to comment.