Sneaky Active Directory Persistence #14: SID History

The content in this post describes a method by which an attacker could persist administrative access to Active Directory after having Domain Admin level rights for 5 minutes.

I presented on this AD persistence method in Las Vegas at DEF CON 23 (2015).

Complete list of Sneaky Active Directory Persistence Tricks posts

SID History is an attribute that supports migration scenarios. Every user account has an associated Security IDentifier (SID) which is used to track the security principal and the access the account has when connecting to resources. SID History enables access for another account to effectively be cloned to another. This is extremely useful to ensure users retain access when moved (migrated) from one domain to another. Since the user’s SID changes when the new account is created, the old SID needs to map to the new one. When a user in Domain A is migrated to Domain B, a new user account is created in DomainB and DomainA user’s SID is added to DomainB’s user account’s SID History attribute. This ensures that DomainB user can still access resources in DomainA.

The interesting part of this is that SID History works for SIDs in the same domain as it does across domains in the same forest, which means that a regular user account in DomainA can contain DomainA SIDs and if the DomainA SIDs are for privileged accounts or groups, a regular user account can be granted Domain Admin rights without being a member of Domain Admins.

Note: A regular user in a domain can contain the Enterprise Admin SID in its SID History from another domain in the Active Directory forest, thus “elevating” access for the user account to effective Domain Admin in all domains in the forest. if you have a forest trust without SID Filtering enabled (also called Quarantine), it’s possible to inject a SID from another forest and it will be added to the user token when authenticated and used for access evaluations.

Mimikatz enables SID History injection to any user account (requires Domain Admin or equivalent rights). In this scenario, the attacker creates the user account “bobafett” and adds the default administrator account for the domain, “ADSAdministrator” (RID 500), to the account’s SID History attribute.

SneakyPersistence-AddSIDHistory-BobaFett-ADSADministrator

When the bobafett account logs on, all of the SIDs associated with the account are added to the user’s token which is used to determine access to resources. The SIDs associated with the account is the user’s SID, the group SIDs in which the user is a member (including groups that those groups are a member of), and SIDs contained in SID History.

Using the PowerShell Active Directory cmdlet “Get-ADUser”, we can see there is no group membership assigned to the bobafett account, though it does have a SID in SIDHistory (the ADSAdministrator account).

SneakyPersistence-AddSIDHistory-GetUSerInfo-BobaFett

When bobafett logs on, the SIDs associated with the account are evaluated and access determined based on these SIDs. Since the bobafett account is associated with the ADSAdmnistrator account (RID 500), the bobafett account has all access the ADSAdministrator account has, including Domain Admin rights.

Leveraging the bobafett user account and the rights granted to it through SID History, it is possible to use PowerShell remoting to pull the KRBTGT account password data from a Domain Controller.

SneakyPersistence-AddSIDHistory-BobaFett-Exploit-PS-Krbtgt


Detection

The best way to detect SID History account escalation is to enumerate all users with data in the SID History attribute and flag the ones which include SIDs in the same domain*. If users haven’t been migrated, you can simply search for all users with data in the SIDHistory attribute. This is why it’s important to clean up SID History after a migration is complete (and the user is added to the correct groups for required resource access).

The PowerShell AD Cmdlet “Get-ADUser” is most useful for detecting “Same Domain SID History”:

# Detect Same Domain SID History
Import-Module ActiveDirectory
[string]$DomainSID = ( (Get-ADDomain).DomainSID.Value )

Get-ADUser -Filter “SIDHistory -Like ‘*'” -Properties SIDHistory | `
Where { $_.SIDHistory -Like “$DomainSID-*” }

This graphic shows the result of running the “Same Domain SIDHistory” Detection PowerShell Script. Note that the SID in the user’s SIDHistory ends with “500” which is the default domain Administrator account which is a member of Administrators, Domain Admins, Schema Admins, and Enterprise Admins by default.
SneakyPersistence-SIDHistory-BothanSpy-SIDHistory-PowerShell-SameDomainDetection

*Note: In multi-domain forests, it is recommended to look for admin group SIDs (and member account SIDs) in every domain in the forest as well as trusted domains/forests.

 

Detection via Domain Controller Events

Detection of successful modification or failed attempt to modify the SIDHistory attribute is possible with the following logging:

Configure sub-category auditing under Account Management,  “Audit User Account Management” (success) on Domain Controllers for the following event ids:

  • 4765: SID History was added to an account.
  • 4766: An attempt to add SID History to an account failed.

 

(Visited 68,161 times, 8 visits today)

3 comments

    • Sinister on September 20, 2015 at 2:07 pm

    Hi there.
    Excellent material.
    But where is “Sneaky Active Directory Persistence” trick number 13 ?

    1. Good catch. It will be posted after DerbyCon… 😉

    • Brad on September 21, 2015 at 1:35 pm

    Looks like you’re using Powershell 2.0 for your detection query. It wouldn’t work for me under PS 3.0 or 4.0; Get-ADUser gave me a syntax error on your -Filter statement. The below works correctly on all versions:


    Import-Module ActiveDirectory
    [string]$DomainSID = ( (Get-ADDomain).DomainSID.Value )
    Get-ADUser -Filter "SIDHistory -Like '*'" -Properties SIDHistory | `
    Where {$_.SIDHistory -Like "$DomainSID-*"}

Comments have been disabled.