Хакерские рецепты



BloodHound releases

Service Principal Name (SPN):

This blog series was co-authored by Security Consultant Megan Nilsen and TAC Practice Lead Andrew Schwartz.

When misconfigured, ACEs can be abused to operate lateral movement or privilege escalation within an AD domain.

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

  • If you want to see your company advertised in HackTricks or download HackTricks in PDF Check the SUBSCRIPTION PLANS!

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

  • If you want to see your company advertised in HackTricks or download HackTricks in PDF Check the SUBSCRIPTION PLANS!


Credit: https://rohnspowershellblog.wordpress.com/2013/03/19/viewing-service-acls/

public enum ServiceAccessFlags : uint

QueryConfig = 1,

ChangeConfig = 2,

QueryStatus = 4,

EnumerateDependents = 8,

Start = 16,

Stop = 32,

PauseContinue = 64,

Interrogate = 128,

Delete = 65536,

ReadControl = 131072,

WriteDac = 262144,

WriteOwner = 524288,

Synchronize = 1048576,

AccessSystemSecurity = 16777216,

GenericAll = 268435456,

GenericExecute = 536870912,

GenericWrite = 1073741824,

GenericRead = 2147483648

If display name was provided, get the actual service name:

Make sure computer has ‘sc.exe’:

Could not find \system32\sc.exe command!

Get SDDL using sc.exe

Get the DACL from the SDDL string

Couldn’t get security descriptor for service ”:

Create the custom object with the note properties

Add the ‘Access’ property:

Add ‘AccessToString’ property that mimics a property of the same name from normal Get-Acl call

ReadGMSAPassword

This abuse stands out a bit from other abuse cases. It can be carried out when controlling an object that has enough permissions listed in the target gMSA account’s msDS-GroupMSAMembership attribute’s DACL. Usually, these objects are principals that were configured to be explictly allowed to use the gMSA account.

The attacker can then read the gMSA (group managed service accounts) password of the account if those requirements are met.

On UNIX-like systems, gMSADumper (Python) can be used to read and decode gMSA passwords. It supports cleartext NTLM, pass-the-hash and Kerberoas authentications.

Alternative #1: Impacket’s ntlmrelayx tool can be used to read and decode gMSA passwords. Some tests showed ntlmrelayx missed entries gMSADumper didn’t.

In order to easily fake a relayed authentication, once the relay servers are up and running, the tester can browse http://127.0.0.1/ in order to trigger a basic authentication that will then be relayed by ntlmrelayx, like this.

Alternative #3: Using bloodyAD

Introduction

In this continuation to our first post (Part 1A), we will further explore Active Directory (AD) attribute-based attacks and their subsequent detections. This post will complete the stepping through of the flow chart provided in the DACL section of the Hacker Recipes.

Although this post will make use of a variety of different “attack” tools, it should be noted that the tool is a means for use to execute the attack, but we are more focused on the underlying techniques of modifiable attributes and the detections surrounding them.

Just as the first post established, a couple of reminders:

  • We are operating under the assumption that the adversary already has a foothold within the domain and has acquired the appropriate access they need to make modifications to the objects we will discuss.
  • Post-exploitation is not a focus.
  • Intelligence applied to adversary attribution has not been mapped.
  • A subset of Windows Event logging has been used, and not all the possible telemetry data points within this data set have been analyzed.

All joking aside, Exchange has ravaged my AD DACLs. To the point Exchange isn’t even working right. I built a lab with an identical AD structure but fresh on 2022-OS/2019-EX-CU12 just so I can see what the correct permissions look like.

What I would rather do is this on the clean side:

$acl = get-acl -path "AD:DC=prod,DC=widgets,DC=corp"
$acl.Access | ? {$_.IdentityReference -like "*Exchange*" -or $_.IdentityReference -like "*Organization*"} | export-CliXml -Path c:\temp\ftw.xml

Then remove row records from the text file I don’t need to import, for those I do I would modify the domain name in the xml file to match the production side:

$CleanACLs = Import-Clixml C:\temp\ftw.xml
$TestVictom = "AD:CN=Poor User,OU=Employees,DC=prod,DC=myCompany,DC=corp"
$acl = get-acl -path $TestVictom
#Testing just one ACL
$NewACE = ($CleanACLs)[0]
$acl.AddAccessRule($newACE)
Set-Acl -Path $TestVictom -AclObject $acl

However, my dreams were busted by this error on the “$acl.AddAccessRule($newACE)” line:

MethodException: Cannot convert argument “rule”, with value: “System.DirectoryServices.ActiveDirectoryAccessRule”, for “AddAccessRule” to type “System.DirectoryServices.ActiveDirectoryAccessRule”: “Cannot convert the “System.DirectoryServices.ActiveDirectoryAccessRule” value of type “Deserialized.System.DirectoryServices.ActiveDirectoryAccessRule” to type “System.DirectoryServices.ActiveDirectoryAccessRule”.”

It seems something as silly as the fact the import-clixml changing ALL of the objects to add the deserialized. is the issue. I am fairly sure the objects are identical otherwise. Ironically, I was using clixml to preserve object type.

Anyone got any magic to get these objects to not have the prefix of deserialized?

Otherwise, anyone have a decent way to export an AD object DACL to an editable text file, with a way to re-import? The only thing I need to do in the text file is remove unneeded rows (which I can technically filter on the source side) as well change the domain name of the IdentityReference).

DACL abuse potential paths can be identified by BloodHound from UNIX-like (using the Python ingestor bloodhound.py) and Windows (using the SharpHound ingestor) systems.

In order to navigate the notes, testers can use the mindmap below.

Impacket’s dacledit (Python) can be used with the -inheritance flag for that purpose (PR#1291).

This can be performed with OUned.py.

BloodHound ACE edges

  • AddKeyCredentialLink, a write permission on an object’s Key-Credential-Link attribute, for Shadow Credentials attacks

  • AddSelf, similar to AddMember. While AddMember is WriteProperty access right on the target’s Member attribute, AddSelf is a Self access right on the target’s Member attribute, allowing the attacker to add itself to the target group, instead of adding arbitrary principals.

  • AddAllowedToAct, a write permission on an object’s msDS-Allowed-To-Act-On-Behalf-Of-Other-Identity attribute, for Kerberos RBCD attacks

  • SyncLAPSPassword, both DS-GetChanges and DS-GetChangesInFilteredSet, for synchronizing LAPS password domain-wise

Common namePermission value / GUIDPermission typeDescription

Edit the object’s DACL (i.e. “inbound” permissions).

Combination of almost all other rights.

Combination of write permissions (Self, WriteProperty) among other things.

Edit one of the object’s attributes. The attribute is referenced by an “ObjectType GUID”.

With the “SeRestorePrivilege” right it is possible to specify an arbitrary owner.

Perform “Validated writes” (i.e. edit an attribute’s value and have that value verified and validate by AD). The “Validated writes” is referenced by an “ObjectType GUID”.

Peform “Extended rights”. “AllExtendedRights” refers to that permission being unrestricted. This right can be restricted by specifying the extended right in the “ObjectType GUID”.

Control Access Right (extended right)

Change the password of the object without having to know the previous one.

Control Access Right (extended right)

One of the two extended rights needed to operate a DCSync.

Control Access Right (extended right)

One of the two extended rights needed to operate a DCSync.

Edit the “member” attribute of the object.

Edit the “servicePrincipalName” attribute of the object.

Blog Format

Due to the length of this post and the number of attributes covered, it is important to remember a couple of key formatting guidelines from Part 1A as we step through this post.

  • Name of the Attribute (common name (CN) of the attribute)
  • Background
    • Will cover a brief overview of what the attribute () is and the relevant links to Microsoft documentation
  • Modifying the Attribute (Attack)
    • Will cover how the “attack” was performed, including relevant setup for modifying the attribute in question, screenshots/commands, and tools used
    • If additional auditing was enabled for building the detection, it will also likely be covered here—or, if additional setup was more complex, it will be broken out into a preceding or subsequent heading.
  • Building the Detections
    • Will cover a variety of detections that will include a range of complexity
    • As was stated in the introduction, not all the possible telemetry data points within this data set have been analyzed. However, we have tried our best to cover the Event IDs that are most accessible and prominent for building out detections.
    • Where necessary, we will provide a flow of logic for detections that involve more complexity or additional information to interpret what is being shown. However, most detections will follow a similar format and will not be explained in further detail.

WriteDACL

You get WriteDACL permission when you have ‘Read Permission’ and ‘Write Permission’ over an object:

Хакерские рецепты

For example in this scenario we have these permissions set on object ‘trinity’. To verify that we indeed have the WriteDACL permission, we can use powershell:

Хакерские рецепты

Indeed we have WriteDACL permission over object ‘trinity’. Next thing we can do is to grant ourselves full control over this object because we still don’t have that permission, we only have permission to modify the object’s DACL. And modifying the object’s DACL is what we are going to do:

Хакерские рецепты

With this we granted ourselves full control over ‘trinity’. Now to verify it:

Хакерские рецепты

GenericAll on Group

We can have GenericAll permission on an object when we have full control over it:

Хакерские рецепты

To verify it:

Хакерские рецепты
Хакерские рецепты
Хакерские рецепты

Security Researchers

Amirhossein Gholizadeh, Surya Dev Singh

Exploitation of ForceChangePassword misconfiguration

since it allows us to change the password, without knowing the old password , we
can you this command :

$pass = ConvertTo-SecureString '[Your New Password Here]' -AsPlainText -
Force
set-domainuserpassword -identity -accountpassword $pass
runas /user: cmd.exe
[target_user]
Хакерские рецепты

GenericAll on User

Хакерские рецепты

But for the sake of simplicity we are just going to change its password:

Хакерские рецепты
Хакерские рецепты
Хакерские рецепты

It has worked perfectly!

Logging Setup

Configuring a SACL is an additional step that must be taken even if the above listed Windows Events are currently being ingested.

Please refer to Part 1A on how to enable and configure the logging setup of the SACL and how to enable/ingest the above Windows Event IDs.

Access Control List (ACL)

There are two types of ACLs:

  • System Access Control List (SACL): Governs the auditing of access attempts to an object.

  • SACL: Used for auditing access to objects, where ACEs define the types of access to be logged in the Security Event Log. This can be invaluable for detecting unauthorized access attempts or troubleshooting access issues.

System Interaction with ACLs

The Local Security Authority (LSASS) processes access requests to objects by examining the DACL for ACEs that match the security principal attempting access. Access is immediately granted if no relevant ACEs are found. Otherwise, LSASS compares the ACEs against the security principal’s SID in the access token to determine access eligibility.

  • ACLs: Define access permissions through DACLs and audit rules through SACLs.

  • Access Decision: Made by comparing DACL ACEs with the access token; SACLs are used for auditing.

There arey three main types of Access Control Entries (ACEs):

Each ACE has four critical components:

  1. A flag that identifies the ACE type (access denied, allowed, or system audit).

  2. Inheritance flags that determine if child objects can inherit the ACE from their parent.

  3. An access mask, a 32-bit value specifying the object’s granted rights.

Access determination is conducted by sequentially examining each ACE until:

  • An Access-Denied ACE explicitly denies the requested rights to a trustee identified in the access token.

  • Access-Allowed ACE(s) explicitly grant all requested rights to a trustee in the access token.

  • Upon checking all ACEs, if any requested right has not been explicitly allowed, access is implicitly denied.

Order of ACEs

The way ACEs (rules that say who can or cannot access something) are put in a list called DACL is very important. This is because once the system gives or denies access based on these rules, it stops looking at the rest.

There is a best way to organize these ACEs, and it is called “canonical order.” This method helps make sure everything works smoothly and fairly. Here is how it goes for systems like Windows 2000 and Windows Server 2003:

  • First, put all the rules that are made specifically for this item before the ones that come from somewhere else, like a parent folder.

  • In those specific rules, put the ones that say “no” (deny) before the ones that say “yes” (allow).

  • For the rules that come from somewhere else, start with the ones from the closest source, like the parent, and then go back from there. Again, put “no” before “yes.”

This setup helps in two big ways:

  • It makes sure that if there is a specific “no,” it is respected, no matter what other “yes” rules are there.

  • It lets the owner of an item have the final say on who gets in, before any rules from parent folders or further back come into play.

By doing things this way, the owner of a file or folder can be very precise about who gets access, making sure the right people can get in and the wrong ones can’t.

So, this “canonical order” is all about making sure the access rules are clear and work well, putting specific rules first and organizing everything in a smart way.

Example from here

This is the classic security tab of a folder showing the ACL, DACL and ACEs:

If we click the Advanced button we will get more options like inheritance:

And if you add or edit a Security Principal:

And last we have the SACL in the Auditing tab:

Explaining Access Control in a Simplified Manner

When managing access to resources, like a folder, we use lists and rules known as Access Control Lists (ACLs) and Access Control Entries (ACEs). These define who can or cannot access certain data.

Denying Access to a Specific Group

Imagine you have a folder named Cost, and you want everyone to access it except for a marketing team. By setting up the rules correctly, we can ensure that the marketing team is explicitly denied access before allowing everyone else. This is done by placing the rule to deny access to the marketing team before the rule that allows access to everyone.

Allowing Access to a Specific Member of a Denied Group

Let’s say Bob, the marketing director, needs access to the Cost folder, even though the marketing team generally shouldn’t have access. We can add a specific rule (ACE) for Bob that grants him access, and place it before the rule that denies access to the marketing team. This way, Bob gets access despite the general restriction on his team.

Understanding Access Control Entries

Each ACE contains important information like who the rule applies to (using a Security Identifier or SID), what the rule allows or denies (using an access mask), and how it’s inherited by other objects.

Key Differences Between ACE Types

  • Generic ACEs are suitable for simple access control scenarios, where the same rule applies to all aspects of an object or to all objects within a container.

In summary, ACLs and ACEs help define precise access controls, ensuring that only the right individuals or groups have access to sensitive information or resources, with the ability to tailor access rights down to the level of individual properties or object types.

Access Control Entry Layout

ACE FieldDescription

Flag that indicates the type of ACE. Windows 2000 and Windows Server 2003 support six types of ACE: Three generic ACE types that are attached to all securable objects. Three object-specific ACE types that can occur for Active Directory objects.

Set of bit flags that control inheritance and auditing.

Number of bytes of memory that are allocated for the ACE.

32-bit value whose bits correspond to access rights for the object. Bits can be set either on or off, but the setting’s meaning depends on the ACE type. For example, if the bit that corresponds to the right to read permissions is turned on, and the ACE type is Deny, the ACE denies the right to read the object’s permissions. If the same bit is set on but the ACE type is Allow, the ACE grants the right to read the object’s permissions. More details of the Access mask appear in the next table.

Access Mask Layout

Bit (Range)MeaningDescription/Example

0 – 15

Object Specific Access Rights

Read data, Execute, Append data

16 – 22

Standard Access Rights

Delete, Write ACL, Write Owner

Can access security ACL

24 – 27

Generic ALL (Read, Write, Execute)

All things necessary to execute a program

All things necessary to write to a file

All things necessary to read a file

GenericAll/GenericWrite on Computer

If we have GenericAll / GenericWrite ACL on Computer , we can exploit it by adding
a fake computer to the domain.

Хакерские рецепты
# Add a computer to the domain via domain credentials
impacket-addcomputer domain.com/user -dc-ip 192.168.x.x -computer-name 'ATTACK$' -computer-pass 'AttackerPC1!'
#Add a computer account via hashed credentials
impacket-addcomputer domain.com/user -dc-ip 192.168.x.x -hashes :19a3a7550ce8c505c2d46b5e39d6f808 -computer-name 'ATTACK$' -computer-pass 'AttackerPC1!'
# Add a computer account via domain credentials
impacket-addcomputer -computer-name 'COMPUTER$' -computer-pass 'SomePassword' -dc-host $DomainController -domain-netbios $DOMAIN 'DOMAIN\user:password'
# Modify a computer account password
impacket-addcomputer -computer-name 'COMPUTER$' -computer-pass 'SomePassword' -dc-host $DomainController -no-add 'DOMAIN\user:password'
# Delete a computer account
impacket-addcomputer -computer-name 'COMPUTER$' -dc-host $DomainController -delete 'DOMAIN\user:password'

Object Modifications & Detections

Background

In this case, AddMember refers to the PowerView cmdlet or Linux RPC commands that can be used to perform the attack, and not necessarily the attribute/object misconfiguration that we are actually leveraging. 

  • GenericAll
  • AllExtendedRights—Note: When we experimented with modifying group membership by allowing for AllExtendedRights without adding additional permissions, we were unable to modify the group membership.

Modifying the Objects (Attack) – Generic Write

Image045

Figure 45 – New Imposter Account

Image046

Image047

Image048

Figure 48 – Confirmation of Group Add

Building the Detections

Detection With Event IDs 5136 and 4662
((index=main EventCode=5136   Class=group  LDAP_Display_Name=nTSecurityDescriptor     GUID="{5b2c1c16-8aab-47ef-a55a-7a94684a65c4}") OR (index=main Account_Name!=*$ Object_Type="%{bf967a9c-0de6-11d0-a285-00aa003049e2}" Object Name="%{5b2c1c16-8aab-47ef-a55a-7a94684a65c4}"  EventCode=4662 Access_Mask = 0x40000)) 
| eval Logon_ID=if(EventCode==4662,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1)) 
| eval user=if(EventCode==4662,mvindex( Account_Name,-1), mvindex( Account_Name,-1)) 
| eval DACL=if(EventCode==5136,mvindex( Value,-1), mvindex( Value,-1)) 
| join type=outer Logon_ID 
     [ search index=main Account_Name!=*$ Object_Type="%{bf967a9c-0de6-11d0-a285-00aa003049e2}" Object_Name="%{5b2c1c16-8aab-47ef-a55a-7a94684a65c4}"  EventCode=4662 Access_Mask = 0x40000 
     | eval Props=Properties 
     | eval AccessMask=Access_Mask 
     | eval ObjectType=Object_Type 
     | eval ObjectName=Object_Name 
     |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName] 
| table  time, LogonID, Account_Name, Props, AccessMask, ObjectType, ObjectName,  DN, GUID, DACL, Class, Type
|stats values by time, LogonID, DACL

Image049 1

Figure 49 – AddMember Final Query (1)

Image050 2

Figure – AddMember Final Query (2)

Image051

Figure – SDDL Review

Detection With Event IDs 5136, 4662, and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=member) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval Changed_Value=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))
| join type=outer Logon_ID [ search (EventCode=5136) OR (EventCode=4624) | stats count by Logon_ID, Account_Name, Source_Network_Address | table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID [ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20 | eval Props=Properties | eval AccessMask=Access_Mask | eval ObjectType=Object_Type | eval ObjectName=Object_Name | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))" |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, ChangedValue

Image052 1

Image053 2

Background

  • GenericAll
  • AllExtendedRights
  • User-Force-Change-Password

Modifying the Objects

Image054

Figure 54 – Adding Privileges to Account

Now we can utilize PowerSploit to change the password of our victim account.

Image055

Figure 55 – Changing Account Password with PowerSploit

Image056

Figure 56 – Validating Password Change With CrackMapExec

Building the Detections

Detection With Event IDs 5136 and 4662
 ((index=main EventCode=5136   Class=user  LDAP_Display_Name=nTSecurityDescriptor) OR (index=main Account_Name!=*$ Object_Type="%{bf967aba-0de6-11d0-a285-00aa003049e2}" EventCode=4662 Access_Mask = 0x40000))
| eval Logon_ID=if(EventCode==4662,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval user=if(EventCode==4662,mvindex( Account_Name,-1), mvindex( Account_Name,-1))
| eval DACL=if(EventCode==5136,mvindex( Value,-1), mvindex( Value,-1))
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$ Object_Type="%bf967aba-0de6-11d0-a285-00aa003049e2}}" EventCode=4662 Access_Mask = 0x40000
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName] 
| table  time, LogonID, Account_Name, Props, AccessMask, ObjectType, ObjectName,  DN, GUID, DACL, Class, Type
|stats values by time, LogonID,DACL

Image057 1

Figure 57 – Final Query Detecting ForceChangePassword Modification (1)

Image058 2

Figure – Final Query Detecting ForceChangePassword Modification (2)

GrantOwnerShip

Background

  • GenericAll
  • WriteOwner

For this section, we will be focusing on the WriteOwner permission. However, the detections built should detect the use of both rights.

Modifying the Objects (Attack)

First, we begin by “misconfiguring” our dacled.egg object to give imposter.oatmeal, our attacker account, WriteOwner permissions.

Image059

Then we use PowerView to set ownership.

Image060

Figure 60 – Setting Ownership with PowerView

Building the Detections

Image061 1

Image062 2

Image063

Figure – SDDL Detecting WriteOwner Privileges on dacled.egg

It will also identify when the owner of the object has been changed with the PowerShell cmdlet.

Image064

Figure -SDDL Post Ownership Change

4.4      LAPS and gMSA

ms-Mcs-AdmPwdExpirationTime

Background

Modifying the Attribute

Before we can modify the attribute, we must first convert the time of the new password expiration that’s stored inside the given AD attribute in Windows File time format.

The easiest way to do this is to simply use the PowerShell AD module to first query the computer and object whose expiration time you’re trying to identify, and then use PowerShell to convert the time stamp to human-readable format.

Get-ADComputer PAN-PC -Properties ms-Mcs-AdmPwdExpirationTime
[datetime]::FromFileTimeUTC(133308023294324030)

Image065

Figure – Reading ms-MCS-AdmPwdExpirationTime Attribute

When changing the expiration time using PowerMad, your specified value will need to be submitted in the Windows File time format.

Image066

Figure – Modifying Attribute with PowerMad

Building the Detections

Detection With Event IDs 5136, 4662, and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=ms-Mcs-AdmPwdExpirationTime) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID [ search (EventCode=5136) OR (EventCode=4624) | stats count by Logon_ID, Account_Name, Source_Network_Address | table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID [ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20 | eval Props=Properties | eval AccessMask=Access_Mask | eval ObjectType=Object_Type | eval ObjectName=Object_Name | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))" |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, Value, LogonID

Image067 1

Figure – Detection With Event IDs 5136, 4624, 4662 (1)

Image068 2

Figure – Detection With Event IDs 5136, 4624, 4662 (2)

Detection With Event IDs 5136, 4662, and 4624 Excluding Machine Accounts

 It is important to note that the previous detection will also catch legitimate changes to LAPS passwords. To filter out the legitimate events, we can remove the machine accounts.

That said, it is advisable to keep both queries to ensure that detection is not evaded if an attacker creates or compromises a machine account.

index=main ((EventCode=5136 AND LDAP_Display_Name=ms-Mcs-AdmPwdExpirationTime) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| join type=outer Logon_ID [ search (EventCode=5136) OR (EventCode=4624) | stats count by Logon_ID, Account_Name, Source_Network_Address | table Account_Name,Logon_ID, Source_Network_Address ]
| join type=outer Logon_ID [ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20 | eval Props=Properties | eval AccessMask=Access_Mask | eval ObjectType=Object_Type | eval ObjectName=Object_Name | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))" |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| search Mod_Account!=*$
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, Value, LogonID

Image069 1

Figure – Detection Excluding Machine Accounts (1)

Image070 2

Figure – Detection Excluding Machine Accounts (2)

PrincipalsAllowedToRetrieveManagedPassword/ms-DS-GroupMSAMembership (gMSA)

Background

The AD attribute governs who can read the gMSA Password.

 However, it is important to outline that the value isn’t the attribute that we should be auditing, since this value is only used when making changes within PowerShell.

 Instead, the change made with the flag stores the value assigned in the PowerShell cmdlet to the attribute within AD. This interpretation is also backed up by this article.

Image071

Figure – Pre- and Post-Change Values of msDS-GroupMSAMEmbership attribute

An attacker who can insert themselves into this attribute then has the ability to read the gMSA account password itself.

Modifying the Objects (Attack)

Image072

Figure – Modifying the gMSA Account

Get-ADServiceAccount -Identity granola.bar -Properties *

Image073

Figure – Validating Changes to gMSA Account

Building the Detections

Detection with Event ID 5136, 4662, and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-GroupMSAMembership) OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM" AND Source_Network_Address!="-") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))
| eval LogonID=mvindex(Logon_ID,0)
| eval LogonID_2=mvindex(Logon_ID,1)
| join type=outer Logon_ID [ search (EventCode=5136 AND LDAP_Display_Name=msDS-GroupMSAMembership) | table Logon_ID, ]
| join type=outer LogonID_2 [ search (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM" AND Source_Network_Address!="-") | table Account_Name,LogonID_2, Source_Network_Address ]
| join type=outer Logon_ID [ search index=main Account_Name!=*$ EventCode=4662 Access_Mask = 0x20 | eval Props=Properties | eval AccessMask=Access_Mask | eval ObjectType=Object_Type | eval ObjectName=Object_Name | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))" |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties]
| search Mod_Account!=*$
| table time, LogonID, Mod_Account, Source_Network_Address , Class, DN, Type, LDAP_Display_Name, Value, AccessMask, Props, Object_Properties
| where len(Class)>0
| stats values by time, LogonID, DN

Image074 1

Figure – Detection With Event IDs 4662, 5136 and 4624 (1)

Image075 2

Figure – Detection With Event IDs 4662, 5136 and 4624 (2)

4.6      DCSync Rights

Background

The ability to perform a DCSync is prized by attackers everywhere—unsurprising, considering that having the ability to extract a domain ntds.dit file is, in many ways, how you can obtain the proverbial keys to the AD kingdom.

  • DS-Replication-Get-Changes
  • DS-Replication-Get-Changes-All
  • DS-Replication-Get-Changes-In-Filtered-Set

However, it is important to note that DS-Replication-Get-Changes-In-Filtered-Set is not specifically needed for an account to perform a DCSync. Only the first two (2) bullets are needed.

Creating a New Account & Modifying the Objects

net user imposter.egg /domain

Image076

Figure 76 – Creating an “Imposter” Account

Add-ObjectACL -PrincipalIdentity imposter.egg -Rights DCSync

Image077

Figure 77 – Adding DCSync Rights

If we look at our privileges now, we can see the new rights reflected:

Image078

Figure 78 – Account SID

Image079

Figure 79 – Newly Added ACEs Added to Domain Root DACL

Image080

Figure 80 – DCSync

Building the Detections

Note: If you modify the DCSync objects directly, you will generate an Event ID 5136 event with the objects of the same name. However, when I attempted this (adding an imposter.egg account to each object), I was unable to perform a successful DCSync. Jim helped clarify that the reason behind this is because for DCSync (and several other rights), it only matters if the Security Principal is granted/delegated those rights at the domain root object.

Instead, this time, we will be hunting for an Event 5136, with domainDNS as the class and the actual domain as the “DN.”

Detection with Event ID 5136
index=main EventCode=5136 Class=domainDNS DN="DC=BREAKFASTLAND,DC=LOCAL" | table  time, LogonID, DN, GUID, Value, Class, Type 

Image081 1

Figure 81 – Basic DCSync Query (1)

Image082 2

Figure – Basic DCSync Query (2)

This is a decent query for detecting adding privileges for the broader domain and works both with privilege modifications through Powerview and when privileges are modified manually in ADUC. However, in our opinion, this alone lacks a lot of telemetry. Adding a correlation with Event ID 4662 for additional context is a good idea.

The “object type” in this case is the GUID of the domainDNS object, and “object_name” is the GUID of our domain (BREAKFASTLAND.LOCAL), which was used in our detection based on 5136 and can be filtered to look for “WRITE_DAC” access via an access mask of 0x4000.

Detection with Event ID 4662
 index=main Account_Name!=*$ Object_Type="%{19195a5b-6da0-11d0-afd3-00c04fd930c9}" Object_Name="%{754fb287-55d2-4d68-b7fc-0332e1746740}"  EventCode=4662  
Access_Mask = 0x40000 | table time, Logon_ID, Account_Name, Access_Mask, Object_Type, Object_Name, Properties 

Image083

Figure 83 – DCSync With Event ID 4662

Then, if you are using a SIEM with the ability to utilize a complex query language, you can combine the two (2) queries to put all the telemetry in one (1) view. As a quick note, this does place all the entries in the “Value” field in one (1) column, but it condenses the table view in Splunk to one (1) line, making it easy to quickly look at and reference the events in a separate tab if more detail is needed.

Detection with Event ID 5136 and 4662
 index=main ((EventCode=5136 Class=domainDNS DN="DC=BREAKFASTLAND,DC=LOCAL") OR (index=main Account_Name!=*$ Object_Type="%{19195a5b-6da0-11d0-afd3-00c04fd930c9}" Object_Name="%{754fb287-55d2-4d68-b7fc-0332e1746740}"  EventCode=4662 Access_Mask = 0x40000))
| eval Logon_ID=if(EventCode==4662,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval user=if(EventCode==4662,mvindex( Account_Name,-1), mvindex( Account_Name,-1))
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$ Object_Type="%{19195a5b-6da0-11d0-afd3-00c04fd930c9}" Object_Name="%{754fb287-55d2-4d68-b7fc-0332e1746740}"  EventCode=4662 Access_Mask = 0x40000
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName]
| table time, Logon_ID, Account_Name, Props, AccessMask, ObjectType, ObjectName,  DN, GUID, Value, Class
|stats values by Value 

Image084 1

Figure 84 – Detecting Changes to the Domain (1)

Image085 2

Figure – Detecting Changes to the Domain (2)

Image086

Figure – Additional Events

To build a higher fidelity detection, we need to address the ‘Value’ field and attempt to understand the hieroglyphic text that are SDDLs. 

Table Part1 B

The SDDL string values to note here are:

  • OA – Object Access Allowed
  • CI – Container Inherit; DirectoryObjectControlAccess.
  • CC – DirectoryObjectCreateChild
  • CR – All Extended Rights

And if we translate the SDDL using our SDDL conversion tool, we can see that the permissions for the dacled.egg attribute were in fact made to the domain.

Image087

Figure – SDDL Editor String for DCSync

Image088

However, the query still identified when the DCSync rights were added.

Image089

Figure – Comparison Post DCSync Added

Detection with Event ID 5136 and 4662 (Improved Filtering)

And then lastly, one (1) final change was made to the query—instead of using only the as the filter parameter, it was expanded to include the DCSync rights objects.

index=main ((EventCode=5136 Class=domainDNS DN="DC=BREAKFASTLAND,DC=LOCAL" AND Value=*(OA;CI;CR;89e95b76-444d-4c62-991a-0facbeda640c)(OA;CI;CR;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2)(OA;CI;CR;1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)*) OR (index=main Account_Name!=*$ Object_Type="%{19195a5b-6da0-11d0-afd3-00c04fd930c9}" Object_Name="%{754fb287-55d2-4d68-b7fc-0332e1746740}"  EventCode=4662 Access_Mask = 0x40000))
| eval Logon_ID=if(EventCode==4662,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval user=if(EventCode==4662,mvindex( Account_Name,-1), mvindex( Account_Name,-1))
| eval DACL=if(EventCode==5136,mvindex( Value,-1), mvindex( Value,-1))
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$ Object_Type="%{19195a5b-6da0-11d0-afd3-00c04fd930c9}" Object_Name="%{754fb287-55d2-4d68-b7fc-0332e1746740}"  EventCode=4662 Access_Mask = 0x40000
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName]
| table  time, LogonID, Account_Name, Props, AccessMask, ObjectType, ObjectName,  DN, GUID, DACL, Class
|stats values by Logon_ID

Image090 1

Figure – Final DCSync Query (1)

Image091 2

Figure – Final DCSync Query (2)

ForceChangePassword on User

get-objectacl -resolveguids | ? {($_.securityidentifier -eq "
[your_current_user_sid]") -and ($_.objectacetype -eq "User-Force-Change-
Password")}
Хакерские рецепты
Bloodhound
Хакерские рецепты

WriteProperty on Group

We have WriteProperty permission on a group when we have ‘Read all properties’ and ‘Write all properties’ permissions set over it:

Хакерские рецепты
Хакерские рецепты

We have ‘WriteProperty’ permission over the ‘Test Group’ object. In this case we can add ourselves to this lonely group which has no members:

Хакерские рецепты

To do so:

Хакерские рецепты

And checking the group again:

Хакерские рецепты

We are now a member of the ‘Test Group’ group.

Conclusion of Part 1B

While this isn’t the end of this series (stay tuned for parts 2 and 3), there are a few key takeaways from this post that are important to note. Most notably, while Event ID 5136 is the core event throughout all the detections that were built throughout Parts 1A through 3, there are accompanying events that are equally important to these detections. Event ID 4624 will give you a source IP, while Event ID 4662 can provide context to the detection.

It’s also important to note that in most cases, multiple queries were built for each detection where possible. This is because it is critical to have multiple points of detection to fall back on in case attackers manage to develop new attacks that may not trigger one (1) solitary detection. Supplementally, most if not all queries in this post should be tweaked to account for differing GUIDs and objects within your own domain, while some will remain the same, such as the GUIDs for the DCSync Rights objects. Other methods of detection can also be incorporated here, such as PowerShell event logging, and while we were unable to find these detections in LDAP logs, they could possibly exist in that telemetry as well.

And lastly, it is important to remember that for SIEMs that may not have the advanced query language that exists within Splunk, all these queries can be broken into smaller sections or multiple queries.

Due to the length, this post has been split into two sections (Part1A and Part1B). Please see this link for a total PDF version of Part 1.

AllExtendedRights

itself is compromised, that domain object will have both the DS-Replication-
Get-Changes and DS-Replication-Get-Changes-All privilege . Both rights

allow a principal to replicate objects from the Domain (DCSync).

Хакерские рецепты
:/>  Проверка целостности системных файлов Windows 10 | remontka.pro