Files
Gavin K 0c39bea2e6 Fix bugs in cloud_metadata_check: select() error fd, O(n²) cred path, redundant URL build
- probe_tcp_port: add error fd set to select() so failed non-blocking
  connects that only signal the error set are correctly detected
- build_aws_cred_path: track append position in a local variable instead
  of calling wstr_len() on each iteration (O(n) instead of O(n²))
- build_appservice_token_path: resolve the resource string once up front
  instead of building the URL with a hardcoded default then tearing it
  down and rebuilding when a custom resource is provided

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-06-11 03:34:11 +00:00
..

Cloud Metadata Check

Probes cloud-local metadata services from current process. Reports:

  • Cloud provider
  • AWS IMDS mode
  • Reachable instance identity material (bounded snippets by default)
  • Selected instance context fields
  • Azure App Service and Azure Arc managed identity exposure for one selected Azure audience
  • GCP OAuth scopes
  • Azure WireServer VM extension metadata when local administrator access is available

What It Checks

First probe: TCP to 169.254.169.254:80. Provider fingerprint on that host uses AWS → Azure → GCP priority (probe_status when none match).

  • AWS EC2 (169.254.169.254)
  • Azure VM (169.254.169.254)
    • Reports: provider: azure, managed identity token snippet for the selected audience; vm_name, location, resource_group, subscription_id, resource_id, tags, network (IMDS api-version 2025-04-07)
    • References: Azure IMDS, VM managed identity
  • Azure WireServer (168.63.129.16:32526)
    • Reports: wireserver_reachable, extension_count, extension names, public_settings_snip, protected_settings_cert_thumbprint, status SAS URL snippet; protected_settings: present (no decrypt). Requires local admin on Azure VM
    • References: WireServer / VM extensions (platform IP); extension settings background in NetSPI WireServer write-up
  • GCP (169.254.169.254)
    • Reports: provider: gcp, service account email, OAuth scopes, token snippet; project_id, zone, instance_name
    • References: Compute Engine metadata
  • Azure App Service (IDENTITY_ENDPOINT / MSI_ENDPOINT + matching header secret env vars)
    • Reports: provider: azure_appservice, identity_endpoint, managed identity token snippet for the selected audience (X-IDENTITY-HEADER, legacy secret retry). IMDS unreachable from this host
    • References: App Service managed identity
  • Azure Arc (127.0.0.1:40342)
    • Reports: himds_reachable, provider: azure_arc, challenge-token identity flow with selected audience check; arc_name, location, resource_group, subscription_id, resource_id, tags
    • References: Arc managed identity / HIMDS

Runs when any applicable path is reachable (IMDS TCP, App Service env, or HIMDS TCP). App Service and Arc blocks can run even when imds_reachable: no.

Credits

Azure coverage (IMDS compute paths, App Service MSI, WireServer, Arc HIMDS) benefited from research shared by @s1zz.

Arguments

Name Required Description
(none) Full output including bounded credential snippets
presence No Presence and context only; no credential snippets
-aud arm No Request Azure managed identity tokens for Azure Resource Manager. This is the default.
-aud graph No Request Azure managed identity tokens for Microsoft Graph.
-aud other:<resource> No Request a custom Azure audience such as https://vault.azure.net when the operator already knows the useful resource.
-aud other <resource> No Same as other:<resource>, split into two arguments.

Usage

beacon> inline-execute cloud_metadata_check.x64.o
beacon> inline-execute cloud_metadata_check.x64.o presence
beacon> inline-execute cloud_metadata_check.x64.o -aud graph
beacon> inline-execute cloud_metadata_check.x64.o presence -aud other:https://vault.azure.net

Example Output

AWS EC2 with IAM role (IMDSv2):

[+] cloud_metadata_check started
[i] imds_reachable: yes
[i] provider: aws
[i] imds_mode: v2
[+] iam_role: MyInstanceRole
[i] identity_available: yes
[+] access_key_id: ASIAEXAMPLE1234567
[+] secret_key_snip: wJalrXUtnFEMI/K7MDENG
[+] token_snip: IQoJb3JpZ2luX2VjEPT/nd
[i] instance_id: i-0abc123def456
[i] region: us-east-1
[+] cloud_metadata_check complete

Azure VM with managed identity:

[+] cloud_metadata_check started
[i] imds_reachable: yes
[i] provider: azure
[i] identity_available: yes
[i] token_audience_arm: yes
[+] managed_identity_snip: eyJ0eXAiOiJKV1QiLCJhbGci
[i] vm_name: prod-web-01
[i] location: eastus
[i] resource_group: prod-rg
[i] subscription_id: 11111111-2222-3333-4444
[i] resource_id: /subscriptions/11111111-2222-3333-4444/resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/prod-web-01
[i] tags: {"environment":"prod","owner":"platform"}
[i] network: [{"ipv4":{"ipAddress":[{"privateIpAddress":"10.0.1.4"...}
[!] wireserver: skipped (requires local administrator)
[+] cloud_metadata_check complete

Azure App Service with managed identity:

[+] cloud_metadata_check started
[i] imds_reachable: no
[i] provider: azure_appservice
[i] identity_endpoint: 127.0.0.1:41566
[i] identity_available: yes
[i] token_audience_graph: yes
[+] managed_identity_snip: eyJ0eXAiOiJKV1QiLCJhbGci
[+] cloud_metadata_check complete

Azure Arc-enabled server with HIMDS and custom resource:

[+] cloud_metadata_check started
[i] imds_reachable: no
[i] himds_reachable: yes
[i] provider: azure_arc
[i] identity_available: yes
[i] token_audience_other: yes
[+] managed_identity_snip: eyJ0eXAiOiJKV1QiLCJhbGci
[i] arc_name: arc-server-01
[i] location: westeurope
[i] resource_group: hybrid-rg
[i] subscription_id: 11111111-2222-3333-4444
[i] resource_id: /subscriptions/11111111-2222-3333-4444/resourceGroups/hybrid-rg/providers/Microsoft.HybridCompute/machines/arc-server-01
[i] tags: scenario:Managed Identity
[+] cloud_metadata_check complete

Azure VM with WireServer extension metadata:

[+] cloud_metadata_check started
[i] imds_reachable: yes
[i] provider: azure
[i] identity_available: no
[i] vm_name: prod-web-01
[i] location: eastus
[i] wireserver_reachable: yes
[i] extension_count: 2
[i] extension: MicrosoftMonitoringAgent
[+] public_settings_snip: {}
[+] protected_settings_cert_thumbprint: 0123456789ABCDEF0123456789ABCDEF01234567
[+] status_sas_url_snip: https://storageacct.blob.core.windows.net/vmstatus/container?sv=...
[!] protected_settings: present
[+] cloud_metadata_check complete

Azure VM with multiple user-assigned managed identities:

[+] cloud_metadata_check started
[i] imds_reachable: yes
[i] provider: azure
[i] identity_available: no
[!] azure_uami: multiple user-assigned identities attached; specify client_id/resource_id for IMDS
[i] token_audience_arm: no (status=400)
[+] cloud_metadata_check complete

Non-cloud or blocked IMDS:

[+] cloud_metadata_check started
[i] imds_reachable: no
[+] cloud_metadata_check complete

Limitations

  • Cloud-local only (169.254.169.254, App Service env, or Arc 127.0.0.1:40342). Arc tokens and WireServer need elevated access; protected extension settings are not decrypted.
  • Single user-assigned Azure managed identities can emit tokens without a selector. Multiple user-assigned identities require a known client_id or resource_id; the BOF reports the IMDS selection error but does not accept a selector argument.
  • Azure managed identity probing requests one audience per run. ARM is the default; use -aud graph or -aud other:<resource> for targeted token checks when the resource audience matters.
  • Output is truncated snippets; shared IMDS uses AWS → Azure → GCP priority.