This blog series was co-authored by Security Consultant Megan Nilsen and TAC Practice Lead Andrew Schwartz.
本博客系列由安全顾问Megan Nilsen和TAC实践负责人Andrew Schwartz共同撰写。
1 Introduction 1 引言
If you were to collectively ask any Windows penetration tester or “red teamer” to recount their most common “attack paths,” there is no doubt that many, if not all of them, will include Active Directory (AD) based attacks. It’s easy to understand both why AD has been commonly dubbed the “attacker’s playground” and why a defender could become overwhelmed by the vast AD attack surface.
如果您集体要求任何Windows渗透测试人员或“红队员”讲述他们最常见的“攻击路径”,毫无疑问,许多(如果不是全部)将包括基于Active Directory(AD)的攻击。很容易理解为什么AD通常被称为“攻击者的游乐场”,以及为什么防御者可能会被巨大的AD攻击面所淹没。
The goal of this post is to provide the “blue team” with a greater level of understanding on how these attacks “may” operate, but also help identify where an adversary may be hiding. As such, this post will strive to collectively identify those AD attributes that an attacker or adversary may modify within a target environment to lead into further access.
这篇文章的目的是让“蓝队”对这些攻击“可能”如何运作有更深入的了解,同时也有助于确定对手可能藏身的地方。因此,这篇文章将努力共同识别攻击者或对手可能在目标环境中修改以导致进一步访问的 AD 属性。
It is important to note that this blog is assuming 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. This post also does not examine any post exploitation (i.e., forged Kerberos tickets, etc.). We are only addressing the modifications given that the primary purpose of this exercise is to build detections to identify when changes are made. Furthermore, a level of “intelligence” (i.e., providing an attribution of attack to adversary) has not been incorporated. While “attribution matters,” for time purposes, intelligence has not been mapped to each attack.
重要的是要注意,本博客假设对手已经在域中站稳脚跟,并且已经获得了对我们将要讨论的对象进行修改所需的适当访问权限。这篇文章也没有检查任何后期开发(即伪造的 Kerberos 票证等)。我们仅处理修改,因为本练习的主要目的是构建检测以确定何时进行更改。此外,尚未纳入一定程度的“情报”(即向对手提供攻击归属)。虽然“归因很重要”,但出于时间目的,情报尚未映射到每次攻击。
Lastly, this post will, in a series of three (3) parts, provide classic Splunk SPL queries for detecting the attacks outlined, using only Windows Event IDs as described. Furthermore, this blog post only examines a subset of the Windows Event logging data source, and not all possible telemetry within this data set have been analyzed.
最后,本文将通过一系列三 (3) 部分提供经典的 Splunk SPL 查询,用于检测概述的攻击,仅使用所述的 Windows 事件 ID。此外,此博客文章仅检查 Windows 事件日志记录数据源的子集,并且尚未分析此数据集中的所有可能遥测数据。
2 Using a Visual Roadmap – Object/Attribute Overview
2 使用可视化路线图 – 对象/属性概述
The following chart, from The Hacker Recipes, provides a visual roadmap and serves as a basis to the AD Objects and Attributes that we will be working with throughout this three (3) part series. We will step through this roadmap in order to try to provide as much detection coverage as possible.
以下图表来自黑客配方,提供了一个可视化路线图,并作为我们将在这三 (3) 部分系列中使用的 AD 对象和属性的基础。我们将逐步完成此路线图,以尝试提供尽可能多的检测覆盖范围。
Figure 1 – Object Review Flow Chart From the Hacker Recipes
图1 – 来自黑客配方的对象审查流程图
3 Logging Setup 3 日志记录设置
3.1 Windows Events 3.1 窗口事件
It should be noted that Event ID 5136 is not enabled by default and can be configured by enabling:
应该注意的是,默认情况下不启用事件 ID 5136,可以通过启用以下内容来配置:
Advanced Audit Policy Configuration > Audit Polices > DS Access > Audit Directory Service Changes.
高级审核策略配置>审核策略> DS 访问>审核目录服务更改。
However, there are some limitations with Event ID 5136, namely that it does not provide much contextual data for us to quickly identify what we would need to respond to a potential attack.
但是,事件 ID 5136 存在一些限制,即它没有为我们提供太多上下文数据来快速确定响应潜在攻击所需的内容。
Enter correlation…and Windows Event IDs 4662 and 4624. Both events are part of the Advanced Auditing policies and may not be enabled by default. If we combine the data from all three (3) Event IDs, we can essentially build a template to build detections for the various modifications/changes to provide greater contextual representation.
输入关联…和 Windows 事件 ID 4662 和 4624。这两个事件都是高级审核策略的一部分,默认情况下可能不启用。如果我们合并来自所有三 (3) 个事件 ID 的数据,我们基本上可以构建一个模板来构建各种修改/更改的检测,以提供更好的上下文表示。
Event 4662 is configured via by enabling:
事件 4662 通过启用以下内容进行配置:
Advanced Audit Policy Configuration > Audit Polices > DS Access > Audit Directory Service Access.
高级审核策略配置>审核策略> DS 访问>审核目录服务访问。
Event 4624 is frequently enabled by default but can be configured by enabling:
默认情况下,事件 4624 经常启用,但可以通过启用以下内容进行配置:
Advanced Audit Policy Configuration > Audit Polices > Logon/Logoff > Audit Logon
高级审核策略配置 > 审核策略 > 登录/注销 > 审核登录
If we combine the data from all three (3) Event IDs, we can essentially build a query that provides a greater contextual representation of the attack.
如果我们合并来自所有三 (3) 个事件 ID 的数据,我们基本上可以构建一个查询,以提供更大的攻击上下文表示形式。
In addition, for some detections, we may use other Events such as:
此外,对于某些检测,我们可能会使用其他事件,例如:
Event 5145, which can be configured by enabling:
事件 5145,可通过启用以下内容进行配置:
Advanced Audit Policy Configuration > Audit Polices > Detailed Tracking > Audit Detailed File Share
高级审核策略配置 >审核策略 > 详细跟踪>审核详细文件共享
Event 4742, which can be configured by enabling:
事件 4742,可通过启用以下内容进行配置:
Advanced Audit Policy Configuration > Audit Polices > Audit Computer Account Management
高级审核策略配置 >审核策略>审核计算机帐户管理
Event 4738, which can be configured by enabling:
事件 4738,可通过启用以下内容进行配置:
Advanced Audit Policy Configuration > Audit Polices > Audit User Account Management
3.2 SACL
Configuring a SACL is an additional step that must be taken even if the above listed Windows Events are currently being ingested.
For the purpose of this blog post, we have created a SACL entry on the root of our Domain to audit all objects; however, this can be done more granularly if logging volume is a concern.
Figure 2 – SACL Configuration for BREAKFASTLAND.LOCAL
Figure 3 – SACL Configuration
In addition, you may need to enable auditing for specific User or Computer objects. We will attempt to call these items out specifically as we run through each detection; however, if you find you are not receiving the logging for the object that is being modified, be sure to check your SACL for the object as that is likely to be the issue.
4 Blog Format 4 博客格式
Due to the length of this blog series and the number of attributes covered, it is important to do a quick overview of the format and what to expect.
由于本博客系列的长度和涵盖的属性数量,快速概述格式和预期内容非常重要。
Each section will contain the following headings:
每个部分将包含以下标题:
- Name of the Attribute (CN of the attribute)
属性的名称(属性的 CN) - Background 背景
- Will cover a brief overview of what the attribute (LDAP-Display-Name) is and the relevant links to Microsoft documentation
将简要概述属性(LDAP-显示名称)是什么以及指向Microsoft文档的相关链接
- Will cover a brief overview of what the attribute (LDAP-Display-Name) 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, will be broken out into a preceding or subsequent heading
如果为构建检测启用了其他审核,则此处也可能介绍它 – 或者,如果其他设置更复杂,则将分解为前面或后面的标题
- Will cover how the “attack” was performed, including relevant setup for modifying the attribute in question, screenshots/commands, and tools used
- 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
如导言中所述,尚未分析此数据集中所有可能的遥测数据点。但是,我们已尽力涵盖最易于访问且最突出的事件 ID,以便构建检测 - 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
如有必要,我们将为涉及更多复杂性或附加信息的检测提供逻辑流,以解释所显示的内容。但是,大多数检测将遵循类似的格式,不会进一步详细解释
- Will cover a variety of detections that will include a range of complexity
5 Object Modifications & Detections
5.1 Writing to msDS-Allowed-to-Act-On-Behalf-Of-Other-Identity
Beginning at the top of the Hacker Recipes flow chart, the first attribute modification on our list is regarding Resource Based Constrained Delegation (RBCD), whereby the attack may be writing to the attribute msDS-AllowedtoActOnBehalfOfOtherIdentity. This attribute was previously examined by Andrew, Jonathan Johnson, and Charlie Clark in this post.
As this has already been covered in detail, we will not be addressing this attribute within this post.
5.2 Writing to Service-Principal-Name (SPN)
5.2.1 Background
The Service Principal Name (SPN) of an object is a unique identifier that can be used by Kerberos to associate a “service instance” with an authentication attempt. SPNs are frequently abused by attackers using Impacket Modules such as GetUsersSPN.py or other hacker toolsets that exist to exploit existing SPNs or to create new ones that can be leveraged to bypass other authentication mechanisms.
5.2.2 Creating a Machine Account Using PowerMad
Before we can modify our SPN attribute, we are going to create a new machine account to use as our “victim” computer. This “victim” computer account will be used for many of the attribute modifications we will make with PowerMad and other tools moving forward through this blog series.
Figure 4 – Creating a New Computer Account
Figure 5 – Computer Account Creation with PowerMad
Before changing any attributes, this is what the IMPOSTER-GRANOLA$ machine account we created looks like as a freshly created object.
PS C:\Users\head.chef> Get-ADComputer -Identity “IMPOSTER-GRANOLA” -Properties * AccountExpirationDate : accountExpires : 9223372036854775807 AccountLockoutTime : AccountNotDelegated : False AllowReversiblePasswordEncryption : False AuthenticationPolicy : {} AuthenticationPolicySilo : {} BadLogonCount : 0 badPasswordTime : 0 badPwdCount : 0 CannotChangePassword : False CanonicalName : BREAKFASTLAND.LOCAL/Computers/IMPOSTER-GRANOLA Certificates : {} CN : IMPOSTER-GRANOLA codePage : 0 CompoundIdentitySupported : {} countryCode : 0 Created : 5/30/2023 11:59:24 AM createTimeStamp : 5/30/2023 11:59:24 AM Deleted : Description : DisplayName : DistinguishedName : CN=IMPOSTER-GRANOLA,CN=Computers,DC=BREAKFASTLAND,DC=LOCAL DNSHostName : IMPOSTER-GRANOLA.breakfastland.local DoesNotRequirePreAuth : False dSCorePropagationData : {12/31/1600 4:00:00 PM} Enabled : True HomedirRequired : False HomePage : instanceType : 4 IPv4Address : IPv6Address : isCriticalSystemObject : False isDeleted : KerberosEncryptionType : {} LastBadPasswordAttempt : LastKnownParent : lastLogoff : 0 lastLogon : 0 LastLogonDate : localPolicyFlags : 0 Location : LockedOut : False logonCount : 0 ManagedBy : MemberOf : {} MNSLogonAccount : False Modified : 5/30/2023 11:59:24 AM modifyTimeStamp : 5/30/2023 11:59:24 AM msDS-User-Account-Control-Computed : 0 Name : IMPOSTER-GRANOLA nTSecurityDescriptor : System.DirectoryServices.ActiveDirectorySecurity ObjectCategory : CN=Computer,CN=Schema,CN=Configuration,DC=BREAKFASTLAND,DC=LOCAL ObjectClass : computer ObjectGUID : 863169ce-25a7-468d-a147-3e193587df4f objectSid : S-1-5-21-1865600711-3446354287-3882071624-1113 OperatingSystem : OperatingSystemHotfix : OperatingSystemServicePack : OperatingSystemVersion : PasswordExpired : False PasswordLastSet : 5/30/2023 11:59:24 AM PasswordNeverExpires : False PasswordNotRequired : False PrimaryGroup : CN=Domain Computers,CN=Users,DC=BREAKFASTLAND,DC=LOCAL primaryGroupID : 515 PrincipalsAllowedToDelegateToAccount : {} ProtectedFromAccidentalDeletion : False pwdLastSet : 133299467648286422 SamAccountName : IMPOSTER-GRANOLA$ sAMAccountType : 805306369 sDRightsEffective : 15 ServiceAccount : {} servicePrincipalName : {RestrictedKrbHost/IMPOSTER-GRANOLA, HOST/IMPOSTER-GRANOLA, RestrictedKrbHost/IMPOSTER-GRANOLA.breakfastland.local, HOST/IMPOSTER-GRANOLA.breakfastland.local} ServicePrincipalNames : {RestrictedKrbHost/IMPOSTER-GRANOLA, HOST/IMPOSTER-GRANOLA, RestrictedKrbHost/IMPOSTER-GRANOLA.breakfastland.local, HOST/IMPOSTER-GRANOLA.breakfastland.local} SID : S-1-5-21-1865600711-3446354287-3882071624-1113 SIDHistory : {} TrustedForDelegation : False TrustedToAuthForDelegation : False UseDESKeyOnly : False userAccountControl : 4096 userCertificate : {} UserPrincipalName : uSNChanged : 376938 uSNCreated : 376936 whenChanged : 5/30/2023 11:59:24 AM whenCreated : 5/30/2023 11:59:24 AM
We will also need to build a SACL for the IMPOSTER-GRANOLA$ computer object in order to receive the appropriate logging within our SIEM. In this case I have enabled full auditing for this object.
Figure 6 – Adding Auditing for IMPOSTER-GRANOLA
5.2.3 Modifying the Attribute (Attack)
To modify the SPN attribute directly, we will use the PowerMad toolset, leveraging the Set-MachineAccountAttribute cmdlet:
Set-MachineAccountAttribute -Attribute ServicePrincipalName -Value ‘HOST/IMPOSTER-DEHYDRATOR.BREAKFASTLAND.LOCAL’
Figure 7 – Modifying SPN Attribute
图7 – 修改SPN属性
Figure 8 – ServicePrincipalName Attribute Post Modification
图 8 – 服务主体名称属性修改后
5.2.4 Building the Detections
5.2.4 构建检测
5.2.4.1 Detection With Event IDs 5136 and 4662
5.2.4.1 使用事件 ID 5136 和 4662 进行检测
index=main ((EventCode=5136 AND LDAP_Display_Name=servicePrincipalName) OR (EventCode=4624 AND Account_Name!=”*$” AND Account_Name!=”ANONYMOUS LOGON” AND Account_Name!=”SYSTEM”)) | 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] | table _time, EventCode, Mod_Account, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value | where len(Class)>0
Figure 9 – Detection with Event IDs 5136 and 4624 (1)
Figure 10 – Detection with Event IDs 5136 and 4624 (2)
5.2.4.2 Detection With Event IDs 5136, 4624, and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=servicePrincipalName) 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, Mod_Account, 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, Changed_Value, Logon_ID
Figure 11 – Detection with Event IDs 5136, 4662, 4624 (1)
图 11 – 事件 ID 为 5136、4662、4624 的检测 (1)
Figure 12 – Detection with Event IDs 5136, 4662, 4624 (2)
图12 – 事件ID为5136、4662、4624的检测 (2)
5.2.4.3 Detection With Event ID 4742
5.2.4.3 使用事件 ID 4742 进行检测
index=main EventCode=4742 | rex field=Message “(?<Account>(?ms)………………………………………………………………..Account\s+Name.*?(Account\s+Name:\s+)(\w+……….))” | rex field=Message “(?<SPN>(?ms)\s+Service\s+Principal\s+Name(.*).+?(?=Additional\s+))” | search SPN!=”*Service Principal Names: -*” | table _time, Account, Logon_ID, SPN
Figure 13 – Detection With Event ID 4742
5.3 Writing to msDS-Allowed-to-Delegate-To
5.3.1 Background
The msDS-AllowedToDelegateTo attribute contains a list of Service Principal Names that are used to configure services so they can obtain Kerberos Tickets used for “Constrained Delegation” for the targeted account.
5.3.2 Modifying the Attribute (Attack)
For this particular attack/attribute modification, we will first create a second new machine account with PowerMad.
Figure 14 – New Machine Account Creation
One thing to note with this attribute is that it cannot be modified unless the user making the change has the SeEnableDelegationPrivilege. This article discusses the requirements in more detail and is an excellent read.
Because we are running these commands with a Domain Administrator account, I was able to modify the attribute.
Figure 15 – Modifying msDS-AllowedToDelegateTo Attribute
Figure 16 – Attribute Post Modification
5.3.3 Building the Detections
5.3.3.1 Detection With Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-AllowedToDelegateTo) OR (EventCode=4624 AND Account_Name!=”*$” AND Account_Name!=”ANONYMOUS LOGON” AND Account_Name!=”SYSTEM”)) | 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] | table _time, EventCode, Mod_Account, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value | where len(Class)>0
Figure 17 – Detection With Event IDs 5136 and 4624 (1)
Figure 18 – Detection With Event IDs 5136 and 4624 (2)
5.3.3.2 Detection With Event IDs 5136, 4624, and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-AllowedToDelegateTo) 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, Mod_Account, 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, Changed_Value
Figure 19 – Detection With Event IDs 5136, 4662, 4624 (1)
Figure 20 – Detection With Event IDs 5136, 4662, 4624 (2)
5.3.3.3 Detection With Event ID 4742
index=main EventCode=4742 | rex field=Message “(?<Account>(?ms)………………………………………………………………..Account\s+Name.*?(Account\s+Name:\s+)(\w+……….))” | rex field=Message “(?<Delegate>(?ms)\s+AllowedToDelegateTo(.*).+?(?=Old\s+))” | search Delegate!=”*AllowedToDelegateTo: -*” | table _time, Account, Logon_ID, Delegate
Figure 21 – Detection With Event ID 4742
5.4 Shadow Credentials – Writing to msDS-Key-Credential-Link
5.4.1 Background
The msDS-KeyCredentialLink attribute can be used to store a key-based alternate set of credentials for a given user object—in this case, our victim account dacled.egg.
5.4.2 Modifying the Attribute (Attack)
To modify the msDS-KeyCredentialLinkattribute, we will be primarily following the attack walkthrough here.
Figure 22 – Executing Shadow Credentials Attack With Whisker
Figure 23 – Change in Object Post Attack
5.4.3 Building the Detections
5.4.3.1 Detection With Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-KeyCredentialLink) OR (EventCode=4624 AND Account_Name!=”*$” AND Account_Name!=”ANONYMOUS LOGON” AND Account_Name!=”SYSTEM”)) | 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] | table _time, EventCode, Mod_Account, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value | where len(Class)>0
Figure 24 – Detection of Modification for msKeyCredentialLink (1)
Figure 25 – Detection of Modification for msKeyCredentialLink (2)
As a quick note, because we have not specified a class for this query—and for other queries—you do not need to write a separate query to pick up modifications to computer objects, as they will be picked up automatically.
Figure 26 – msKeyCredentialLink Modification Showing Changes to User and Computer Objects
5.5 Logon Script (Script-Path)
5.5.1 Background 5.5.1 背景
The scriptPath attribute specifies the path designated for a user or computer object’s logon script.
scriptPath 属性指定为用户或计算机对象的登录脚本指定的路径。
5.5.2 Modifying the Attribute (Attack)
5.5.2 修改属性(攻击)
As previously, we will modify the scriptPath attribute with the following PowerMad Command:
如前所述,我们将使用以下 PowerMad 命令修改 scriptPath 属性:
Set-MachineAccountAttribute -Attribute scriptPath -Value ‘C:\TheFridge\Food.exe’
Figure 27 – Modifying scriptPath Attribute
图 27 – 修改脚本路径属性
Figure 28 – scriptPath Attribute Post Modification
5.5.3 Building the Detections
5.5.3.1 Detection with Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=scriptPath) OR (EventCode=4624 AND Account_Name!=”*$” AND Account_Name!=”ANONYMOUS LOGON” AND Account_Name!=”SYSTEM”)) | 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] | table _time, EventCode, Mod_Account, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value | where len(Class)>0
Figure 29 – Detection With Event IDs 5136 and 4624 (1)
Figure 30 – Detection With Event IDs 5136 and 4624 (2)
5.5.3.2 Detection With Event IDs 5136, 4624, and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=scriptPath) 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, Mod_Account, 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, Changed_Value, Logon_ID
Figure 31 – Detection With Event IDs 5136, 4662, 4624 (1)
图31 – 事件ID为5136、4662、4624的检测 (1)
Figure 32 – Detection With Event IDs 5136, 4662, 4624 (2)
图32 – 事件ID为5136、4662、4624的检测 (2)
5.5.3.3 Detection with Event ID 4742
5.5.3.3 使用事件 ID 4742 进行检测
index=main EventCode=4742 Script_Path!=”*-*” | rex field=Message “(?<Account>(?ms)………………………………………………………………..Account\s+Name.*?(Account\s+Name:\s+)(\w+……….))” | table _time, Account, Logon_ID, Script_Path
Figure 33 – Detection With Event ID 4742
5.6 ms-TS-Inital-Program
5.6.1 Background
The msTSInitialProgram attribute stores data for applications that should be started upon initial logon. This information will include the path and file name of the application(s).
5.6.2 Modifying the Attribute (Attack)
As previously, we will modify the msTSInitialProgram attribute with the following PowerMad Command:
Set-MachineAccountAttribute -Attribute msTSInitialProgram -Value ‘C:\TheFridge\More_Food.exe’
Figure 34 – Modifying msTSInitialProgram
Figure 35 – msTSInitialProgram Post Modification
5.6.3 Building the Detections
5.6.3.1 Detection With Event IDs 5136 and 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=msTSInitialProgram) OR (EventCode=4624 AND Account_Name!=”*$” AND Account_Name!=”ANONYMOUS LOGON” AND Account_Name!=”SYSTEM”)) | 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] | table _time, EventCode, Mod_Account, Source_Network_Address, Class, DN, Logon_ID, Type, LDAP_Display_Name, Value | where len(Class)>0
Figure 36 – Detection With Event IDs 5136 and 4624 (1)
Figure 37 – Detection With Event IDs 5136 and 4624 (2)
5.6.3.2 Detection With Event IDs 5136, 4624, and 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=msTSInitialProgram) 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, Mod_Account, 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, Changed_Value, Logon_ID
Figure 38 – Detection With Event IDs 5136, 4662, 4624 (1)
图 38 – 事件 ID 为 5136、4662、4624 的检测 (1)
Figure 39 – Detection With Event IDs 5136, 4662, 4624 (2)
5.7 GPO Abuse – Group-Policy-Container Class
5.7.1 Background
groupPolicyContainer is an AD Schema class that is modified when a GPO is updated through the Group Policy Editor. While modifying GPOs is a normal administrative task, it can also be abused by attackers who may use scheduled tasks or other GPO features to establish persistence or move laterally through the network.
groupPolicyContainer 是一个 AD 架构类,在通过组策略编辑器更新 GPO 时会对其进行修改。虽然修改 GPO 是一项正常的管理任务,但它也可能被攻击者滥用,他们可能使用计划任务或其他 GPO 功能来建立持久性或通过网络横向移动。
5.7.2 Modifying the Attribute (Attack)
5.7.2 修改属性(攻击)
While GPO can be modified through the GUI, we are going to leverage the tools mentioned in the Hacker Recipes to remotely modify a GPO from a machine connected to the network.
虽然可以通过 GUI 修改 GPO,但我们将利用黑客配方中提到的工具从连接到网络的计算机远程修改 GPO。
Using GPOwned.py, we first need to procure the “unique ID/Name” of the GPO we are going to be attacking. The syntax is simple:
使用 GPOwned.py,我们首先需要获取我们将要攻击的 GPO 的“唯一 ID/名称”。语法很简单:
python3 GPOwned.py -u cheese.omlette -p password -d breakfastland.local -dc-ip 10.0.2.4 -gpcmachine -listhpo
Figure 40 – GPOwned Output
图 40 – GP 输出
Once you’ve enumerated a list of GPOs on the domain, you can identify the “Name” —in our case the Default Domain Policy GPO— of the GPO you wish to modify, and then you can run the following command:
枚举域上的 GPO 列表后,可以标识要修改的 GPO 的“名称”(在本例中为默认域策略 GPO),然后可以运行以下命令:
python3 GPOwned.py -u head.chef -p password -d breakfastland.local -dc-ip 10.0.2.4 -gpcmachine -gpoimmtask -name ‘{31B2F340-016D-11D2-945F-00C04FB98}’ -author ‘BREAKFASTLAND\Domain Admins’ -taskname ‘ImaGPOAttack’ -taskdescription ‘For the blogs!’ -dstpath ‘c:\windows\system32\notepad.exe’
Figure 41 – GPOwned GPO Modification
图 41 – GP 修改 GPO
Note: This attack was run originally as a non-privileged user and was not successful. It was successful as a privileged user. Second, the author of this script notes that it can be a bit buggy and should be used with precaution in production environments. Specifically, the bug we encountered was that the script would not pick up or drop GPOs that were new or deleted. Thus, keep in mind that there may be removed GPOs that are listed but no longer exist.
注意:此攻击最初以非特权用户身份运行,未成功。作为特权用户,它很成功。其次,此脚本的作者指出,它可能有点错误,应在生产环境中谨慎使用。具体来说,我们遇到的错误是脚本不会选取或删除新的或删除的 GPO。因此,请记住,可能会删除已列出但不再存在的 GPO。
5.7.3 Building the Detections
At a very basic level, we can detect changes to the groupPolicyContainer “class” using Event ID 5136, as we have done with the majority of our previously built detections.
index=main EventCode=5136 Class=groupPolicyContainer |table _time, EventCode, GUID, Class, Value, Type, DN, Correlation_ID
Figure 42 – Basic Query to Detect Changes to groupPolicyContainer
图 42 – 用于检测对组策略容器的更改的基本查询
However, here we begin to run into some challenges with the limitations of Event ID 5136—namely, that while we can see evidence that the Group Policy GUID targeted in our attack was changed, we cannot see what exactly was changed or where it was changed from.
但是,在这里,我们开始遇到事件 ID 5136 限制的一些挑战,即,虽然我们可以看到攻击中针对的组策略 GUID 已更改的证据,但我们看不到确切更改的内容或更改的位置。
Given the breadth of function within GPO, this is critical to know in order to facilitate timely incident response and to assist analysts by adequately communicating information needs to AD/GPO Administrators.
鉴于 GPO 中功能的广泛性,了解这一点至关重要,以便促进及时的事件响应,并通过向 AD/GPO 管理员充分传达信息需求来帮助分析师。
To get the information we need, such a source IP address of the attacking host, as well as the change that was actually made to the GPO, we need to leverage Event ID 5145 and Event ID 4662.
若要获取所需的信息(例如攻击主机的源 IP 地址)以及实际对 GPO 所做的更改,我们需要利用事件 ID 5145 和事件 ID 4662。
Note: See the “Windows Events” section under “Logging Setup” within this blog for specifics on how to enable this logging.
注意:有关如何启用此日志记录的详细信息,请参阅本博客中“日志记录设置”下的“Windows 事件”部分。
In this case, the two (2) added events provide us with the following telemetry:
在这种情况下,添加的两 (2) 个事件为我们提供了以下遥测数据:
Event ID 5145: 事件 ID 5145:
- The Relative Target Name contained within this Event ID provides us with additional specifics on the actual network share/file/object accessed within our targeted GPO.
此事件 ID 中包含的相对目标名称为我们提供了有关在目标 GPO 中访问的实际网络共享/文件/对象的其他详细信息。 - Provides a source IP address
提供源 IP 地址
Event ID 4662:
- Gives additional contextual data about the object/class/attributes involved
- Can be omitted if telemetry from Event IDs 5136 and 5145 is sufficient for organizational needs
5.7.3.1 Detection With Event IDs 5136, 5145, and 4662
index=main ((EventCode=5136 AND Class=groupPolicyContainer AND (Type=”Value Added” OR Type=”Value Deleted”)) OR (EventCode=5145 AND Accesses=”WriteData (or AddFile)”) OR (EventCode=4662 AND Access_Mask=0x20 AND Object_Type=”%{f30e3bc2-9ff0-11d1-b603-0000f80367c1}”)) | eval new_time =strftime(_time, “%b %d, %Y %I:%M %p”) | table new_time, Source_Address, Logon_ID, Account_Name, EventCode, GUID, DN, Correlation_ID, Type, Relative_Target_Name, Access_Mask, Object_Type, Class | stats values by new_time |sort by new_time
Figure 43 – Detecting Modifications to groupPolicyContainer Object Complex (1)
图 43 – 检测对组策略容器对象复合体的修改 (1)
Figure 44 – Detecting Modifications to groupPolicyContainer Object Complex (2)
图 44 – 检测对组策略容器对象复合体的修改 (2)
6 Conclusion of Part 1A
6 第1A部分的结论
Due to the length, this post has been split into two sections (Part 1A and Part 1B). Please see this link for a total PDF version of Part 1.
由于篇幅较长,这篇文章分为两部分(第1A部分和第1B部分)。请参阅此链接以获取第 1 部分的完整 PDF 版本。
Lastly, this blog would not have been possible without help from the following people:
最后,如果没有以下人员的帮助,这个博客是不可能的:
Charlie Bromberg (@_nwodtuhs)
查理·布朗伯格 ( @_nwodtuhs)
Jonathan Johnson (@jsecurity101)
乔纳森·约翰逊 ( @jsecurity101)
Jim Sykora (@jimsycurity)
吉姆·西科拉 ( @jimsycurity)
Kelsey Segure (@KelseySegrue)
凯尔西·塞古雷 ( @KelseySegrue)
7 References: 7 参考资料:
https://www.thehacker.recipes/ad/movement/dacl
Windows Events: 视窗事件:
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4624
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5145
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4742
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4738
msDS-AllowedtoActOnBehalfOfOtherIdentity:
msDS-AllowedtoActOnBehalfOfOtherIdentity:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-msds-allowedtoactonbehalfofotheridentity
https://jsecurity101.medium.com/defending-the-three-headed-relay-17e1d6b6a339
Service Principal Name (SPN):
服务主体名称 (SPN):
https://learn.microsoft.com/en-us/windows/win32/ad/service-principal-names
https://learn.microsoft.com/en-us/windows/win32/ad/mutual-authentication-using-kerberos
https://github.com/fortra/impacket
https://github.com/fortra/impacket/blob/master/examples/GetUserSPNs.py
https://github.com/Kevin-Robertson/Powermad
msDS-AllowedtoDelegateTo:
msDS-AllowedtoDelegateTo:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-msds-allowedtodelegateto
https://skyblue.team/posts/delegate-krbtgt/
https://csandker.io/2020/02/10/KerberosDelegationAWrapUp.html
msDS-KeyCredentialLink: msDS-KeyCredentialLink:
https://cyberstoph.org/posts/2022/03/detecting-shadow-credentials/
ScriptPath: 脚本路径:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-scriptpath
msTSInitalProgram: msTSInitalProgram:
https://learn.microsoft.com/en-us/windows/win32/adschema/a-mstsinitialprogram
GPO: 通用数据保护条例:
https://learn.microsoft.com/en-us/windows/win32/adschema/c-grouppolicycontainer
https://github.com/Hackndo/pyGPOAbuse
https://github.com/X-C3LL/GPOwned
https://www.thehacker.recipes/ad/movement/group-policies
https://learn.microsoft.com/en-us/windows/win32/adschema/c-grouppolicycontainer
https://labs.withsecure.com/tools/sharpgpoabuse
AddMember: 添加成员:
https://www.thehacker.recipes/ad/movement/dacl/addmember
https://github.com/PowerShellMafia/PowerSploit
https://learn.microsoft.com/en-us/windows/win32/adschema/r-self-membership
https://learn.microsoft.com/en-us/windows/win32/adschema/a-member
ForceChangePassword: 强制更改密码:
https://www.thehacker.recipes/ad/movement/dacl/forcechangepassword
https://learn.microsoft.com/en-us/windows/win32/adschema/r-user-force-change-password
GrantOwnerShip: 授予船东:
https://www.thehacker.recipes/ad/movement/dacl/grant-ownership
LAPS/GMSA: 圈/GMSA:
https://www.trustedsec.com/blog/splunk-spl-queries-for-detecting-gmsa-attacks/
https://www.trustedsec.com/blog/a-lapse-in-judgement/
https://learn.microsoft.com/en-us/powerquery-m/datetime-fromfiletime
https://adsecurity.org/?p=4367
https://learn.microsoft.com/en-us/powershell/module/activedirectory/?view=windowsserver2022-ps
DCSync: DCSync:
https://github.com/fortra/impacket
https://www.alteredsecurity.com/post/a-primer-on-dcsync-attack-and-detection
https://www.thehacker.recipes/ad/movement/credentials/dumping/dcsync
msDS-GroupManagedServiceAccount/msDS-ManagedServiceAccount References:
msDS-GroupManagedServiceAccount/msDS-ManagedServiceAccount References:
https://woshub.com/group-managed-service-accounts-in-windows-server-2012/
https://blog.netwrix.com/2022/10/13/group-managed-service-accounts-gmsa/
PowerMad/Set-MachineAcccountAttribute:
PowerMad/Set-MachineAcccountAttribute:
https://github.com/Kevin-Robertson/Powermad
https://skyblue.team/posts/delegate-krbtgt/
Other: 其他:
https://specterops.io/wp-content/uploads/sites/3/2022/06/an_ace_up_the_sleeve.pdf
原文始发于Megan Nilsen:A Hitch-hacker’s Guide to DACL-Based Detections (Part 1A)
转载请注明:A Hitch-hacker’s Guide to DACL-Based Detections (Part 1A) | CTF导航