June 1, 2023
Targeting MSOL Accounts to Compromise Internal Networks
The MSOL (Microsoft Online Services) account in Azure Active Directory Connect is used to connect to and manage the on-premises Active Directory and Azure Active Directory. It provides the necessary permissions to synchronize user, group, and other directory objects between the on-premises Active Directory and Azure Active Directory. Additionally, MSOL accounts can be used for Office 365 services.
It serves as the service account for the Azure AD Connect sync service which runs on the on-premises server. Azure AD Connect synchronizes the on-premises Active Directory with Azure Active Directory, enabling users to use their on-premises credentials to access Azure AD and Office 365 resources.
MSOL accounts are frequently overlooked by both red and blue team security professionals due to the perception that domain administrator accounts are the primary target for privilege escalation and network pivoting. As such, high-priority groups such as Domain Administrators are closely monitored for any suspicious activity.
Compromising an MSOL account can have significant advantages over a domain administrator account during covert assessments of an internal network. These advantages include:
- Reduced detection: MSOL accounts typically have less visibility and fewer security controls than domain administrator accounts, making it more challenging for defenders to detect a compromise.
- Increased persistence: MSOL accounts often have access to a broader range of resources and services, such as cloud-based applications, which can provide the attacker with a longer-term foothold in the organization’s network.
- Elevated privileges: An MSOL account can often be used to gain access to other resources, such as email and file-sharing systems, which can then be used to target other accounts and systems, eventually leading to domain administrator access.
As cloud-integrated Active Directory environments have become increasingly prevalent, the rate of MSOL accounts has grown accordingly. These accounts often provide extensive access to various objects within an internal network, including the ability to force reset passwords, add members to groups regardless of the groups’ attributed privilege level, and even perform DCSync on domain controllers.
Below is an instance of an MSOL account from a previous internal engagement:
Outbound Object Control
In this instance, the MSOL account has been assigned to the Domain User and DENY_VPN group and has been granted ‘GenericWrite’ access to high-priority groups, various rights for domain users, and DCSync rights for the domain. It is reasonable that an account of this nature would possess these rights, as it synchronizes account information from an on-premise Active Directory to a cloud-based Azure Active Directory. However, it should be noted that these permissions may be exploited in certain environments.
Preparing to Exploit
In order to retrieve the unencrypted password of the MSOL account, certain prerequisites must be met:
- Obtainment of valid Active Directory credentials for executing an LDAP query (if the domain security level is inadequate, this may not be necessary).
- Identification of the Azure Active Directory Connect server.
- This can be quickly and easily located by utilizing Bloodhound. The steps to locate the server include searching for the MSOL account and reviewing the associated description:
- Or by performing an LDAP search to find the MSOL description:
|ldapsearch -H ldap://ACME-DC01.ACME.CORP:389 -D “ACME\<username>” -w “<password>” -b “DC=ACME,DC=CORP” ‘(description=*Azure*)’ description|
- Local administrator access to the mentioned computer, in this case, LOONEY.ACME.CORP.
Getting the Goods
Once access to the machine has been obtained, locate the path “C:\Program Files\Microsoft SQL Server\[version number]\Tools\Binn” and execute the command as specified:
Method 1: azuread_decrypt_msol_v2.ps1 by xpn (Recommended)
We will utilize the information provided to make necessary modifications to this PowerShell script created by security researcher, xpn. Specifically, modifications will be made to line 4. The original line of code,
|$client = new-object System.Data.SqlClient.SqlConnection -ArgumentList “Data Source=(localdb)\.\ADSync;Initial Catalog=ADSync”|
will be updated to:
|$client = new-object System.Data.SqlClient.SqlConnection -ArgumentList “Data Source=(localdb)\.\ADSync2019;Initial Catalog=ADSync”|
Now we can run the MSOL decryption script in an Administrator PowerShell prompt:
With the acquisition of the plaintext password, we can now move to the post-exploitation phase of the operation.
How does this script work?
- The script starts by creating a SQL connection object to connect to the local SQL Server instance and the ADSync database.
- It then runs a query on the mms_server_configuration table in the ADSync database to extract the keyset_id, instance_id, and entropy needed to decrypt the credentials.
- Next, the script runs a query on the mms_management_agent table in the ADSync database to extract the private_configuration_xml and encrypted_configuration data.
- The script then uses the xp_cmdshell stored procedure to run a PowerShell command that uses the mcrypt.dll library to decrypt the encrypted_configuration data using the keyset_id, instance_id, and entropy that were obtained from the previous query.
- The script then uses the Select-Xml cmdlet to parse the private_configuration_xml and decrypted_configuration data to extract the domain, username, and password.
- Finally, the script displays the extracted credentials to the console.
Method 2: ADSyncQuery / adconnectdump.py by fox-it
The MSOL and Synchronized account passwords can be retrieved from the network using Fox-It’s ADSyncQuery.exe and AdConnectDump.py, in conjunction with Impacket’s Remote Procedure Call (RPC) capability. Much like the PowerShell method, we must possess local administrator access to the Azure Active Directory Connect server. Moreover, to execute this technique, Python 2.7 with the Impacket library and Microsoft SQL Server with SqlLocalDB must be installed on the targeted domain-joined computer. While this setup seems improbable, this attack can be carried out in two stages for the sake of evasion. Initially, we run adconnectdump.py from any operating system linked to the internal network. Subsequently, we transfer the mdf file to a Windows machine equipped with MSSQL and communication to the ADSync machine and execute ADSyncQuery.exe C:\path\to\file.mdf > output.txt. This two-stage procedure eliminates the need for Python2.7 and Impacket installation on the target machine.
Like the PowerShell script, we may need to make modifications to the python code for successful exfiltration.
For lines 78 and 80, we made the following changes:
|# Original: Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf|
with open(‘ADSync.mdf’,’wb’) as fh:
self.__smbConnection.getFile(‘C$’,r’Program Files\Microsoft Azure AD Sync\Data\ADSync2019\ADSync.mdf’, fh.write)# Original: Program Files\Microsoft Azure AD Sync\Data\ADSync_log.ldf
with open(‘ADSync_log.LDF’,’wb’) as fh:
self.__smbConnection.getFile(‘C$’,r’Program Files\Microsoft Azure AD Sync\Data\ADSync2019\ADSync_log.ldf’, fh.write)
Once these conditions and modifications are met, extracting the Azure AD and Local DB credentials is possible.
Change a user’s password
A tool such as Bloodhound can greatly enhance the efficiency of identifying and analyzing potential attack vectors during the post-exploitation phase of this attack vector. Below is an example of an account takeover via ‘ForceChangePassword’ using the compromised MSOL account.
The use of PowerView (and its associated documentation) enables the modification of a target user’s password with ease. However, this action should be avoided during penetration testing as it can lead to unintended business disruption. This technique is only demonstrated for proof-of-concept purposes.
|$SecPassword = ConvertTo-SecureString ‘<MSOL_ Password>’ -AsPlainText -Force|
$Cred = New-Object System.Management.Automation.PSCredential(‘ACME\MSOL_’, $SecPassword)
$UserPassword = ConvertTo-SecureString ‘whatsupdoc?’ -AsPlainText -Force Set
Set-DomainUserPassword -Identity bbunny -AccountPassword $UserPassword -Credential $Cred
Using the Impacket library, we can perform a secrets dump on a specified domain controller to extract all user hashes on the domain. This is possible because the MSOL account has the necessary permissions to synchronize user, group, and other directory objects between the on-premises Active Directory and Azure Active Directory. This means that it also has the necessary permissions to perform a DCSync (Domain Controller Sync) operation.
While there is no direct patch for the MSOL account’s excessive permissions, there are certainly countermeasures that can be implemented to ensure the server(s) running Azure Active Directory Connect is unlikely to be compromised by following best practices:
- Ensure the server does not share local administrator passwords with other domain computers.
- ADSync machines should be protected with the same scrutiny as domain controllers.
- Implement a least-privilege methodology throughout the domain, with a specific focus on the server running Azure Active Directory Connect to ensure that only necessary access is granted.
- Ensure SMB signing is enabled to prevent NTLM relay attacks on the subnet.