Skip to content

Back to the catalog

PowerZure 2.1 Update
hausec.comarticle

PowerZure 2.1 Update

Release notes for PowerZure 2.1, a PowerShell Azure exploitation toolkit, detailing new offensive functions including Invoke-AzureVMUserDataAgent/Command which abuse the VM userData property for log-free command execution, and Invoke-AzureMIBackdoor which exposes the IMDS REST API externally via portproxying to steal Managed Identity JWTs without authentication. Also adds Get-AzureManagedIdentities and Get-AzurePIMAssignment for enumeration, plus several bug fixes to existing cmdlets.

TL;DR PowerZure 2.1 adds stealthy Azure persistence/exfil techniques abusing VM userData and the unauthenticated IMDS API to steal Managed Identity tokens with no Azure Event Log trace.
Document

What it is

Release notes for PowerZure 2.1, a PowerShell Azure exploitation toolkit. The summary already names the four offensive/enumeration functions; what follows is the operational detail an engineer needs to reason about detection and privilege — which the summary omits.

How it works — the details that matter for detection

Two of the new techniques are marketed on the same property: they leave no entry in the Azure Event Log.

  • userData command execution (Invoke-AzureVMUserDataAgent / -Command): the userData VM property is writable by any principal with VM write and readable by any principal with VM read. The agent is a Scheduled Task on the VM that polls userData via IMDS, executes any command it finds, and writes output back into userData for the reader to collect. The channel is the VM property itself, not a network callback.
  • Invoke-AzureMIBackdoor: exposes the internally-only IMDS REST API to the internet via portproxy, letting anyone unauthenticated request a Managed Identity JWT. The crucial operational detail the summary drops: by default it portproxies over 3389 (RDP), which breaks RDP on the VM until the rule is removed. The -NoRDP flag instead opens a custom port in the NSG firewall — but that NSG change does generate logs. So the stealthy default is self-signaling (RDP outage); the flexible option trades away the stealth.

Get-AzureManagedIdentities identifies MIs by enumerating service principals and matching application URIs containing identity.azure.net, then maps each to its role.

Preconditions

  • userData technique: attacker needs VM write to plant/command, VM read to collect output.
  • MIBackdoor: a Managed Identity configured on the VM (no JWT to steal otherwise); ability to set a portproxy rule on the host.

What to look for (defender takeaways)

  • The "no logs" claim is scoped to Azure Event Log — host-level artifacts remain: a Scheduled Task polling IMDS, and abnormal userData writes/reads. Alert on userData property modifications, which have no legitimate high-frequency use.
  • For MIBackdoor: an unexpected RDP outage on a VM, or a portproxy rule forwarding to 169.254.169.254, is the tell for the default mode; NSG rule additions opening a new port are the tell for -NoRDP.

Caveats (stated on the page)

  • Invoke-AzureCustomScriptExtension is currently only a wrapper — the file-less execution it promises is blocked pending an Azure REST API bug fix.
  • Get-AzurePIMAssignment gathers AzureRM assignments only; the AzureAD/PIM path is broken because the underlying Graph API returns 401 for any user.

Organisations named here

  • IMDS
  • Managed Identity
  • PIM

Technologies named here

  • Azure Virtual Machines
  • PowerZure
  • Az module
  • Azure Managed Identities
  • Azure Service Principals
  • AzureAD cmdlet
  • Azure PIM
  • Azure Network Security Group firewall
  • PowerShell
  • Azure

Techniques named here

  • Get-AzureManagedIdentities
  • Invoke-AzureCustomScriptExtension
  • Get-AzurePIMAssignment
  • Invoke-AzureVMUserDataAgent / Invoke-AzureVMUserDataCommand
  • Invoke-AzureMIBackdoor