Skip to content

Commit

Permalink
adding additional detection and updating typo
Browse files Browse the repository at this point in the history
  • Loading branch information
dluxtron committed Nov 15, 2023
1 parent 7b2a05c commit cea88ac
Show file tree
Hide file tree
Showing 15 changed files with 1,733 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ search: '`wineventlog_security` EventCode=5136 ObjectClass=group
| rex field=new_ace "(?P<aceType>.*?);(?P<aceFlags>.*?);(?P<aceAccessRights>.*?);(?P<aceObjectGuid>.*?);(?P<aceInheritedTypeGuid>.*?);(?P<aceSid>.*?)$"
| rex max_match=100 field=aceAccessRights "(?P<AccessRights>[A-Z]{2})"
| rex max_match=100 field=aceFlags "(?P<aceFlags>[A-Z]{2})"
| lookup ace_control_access_rights_lookup.csv control_access_rights_guid as aceObjectGuid OUTPUT control_access_rights_value as ControlAccessRights
| lookup ace_access_rights_lookup.csv access_rights_string as AccessRights OUTPUT access_rights_value
| lookup ace_type_lookup.csv ace_type_string as aceType OUTPUT ace_type_value as aceType
| lookup ace_flag_lookup.csv flag_string as aceFlags OUTPUT flag_value as ace_flag_value
| lookup ace_access_rights_lookup.csv access_rights_string as AccessRights OUTPUT access_rights_value
| lookup msad_guid_lookup guid as aceObjectGuid OUTPUT displayName as ControlAccessRights
``` Optional SID resolution lookups
| lookup identity_lookup_expanded objectSid as aceSid OUTPUT downLevelDomainName as user
| lookup admon_groups_def objectSid as aceSid OUTPUT cn as group ```
| lookup builtin_groups_lookup.csv builtin_group_string as aceSid OUTPUT builtin_group_name as builtin_group
| eval aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",'access_rights_value'), aceFlags=coalesce(ace_flag_value,"This object only"), user=coalesce(user, group, builtin_group, aceSid), ControlAccessRights=coalesce(ControlAccessRights,aceObjectGuid)
| stats values(aceType) as aceType values(aceFlags) as aceFlags(inheritance) values(ControlAccessRights) as ControlAccessRights values(aceAccessRights) as aceAccessRights values(aceInheritedTypeGuid) as inheritedTypeGuid values(new_ace) as new_ace by _time ObjectClass ObjectDN src_user SubjectLogonId user OpCorrelationID
| search aceAccessRights IN ("Full control","All validated writes","All extended rights","Modify permissions","Modify owner","Write all properties")
| eval ControlAccessRights=if(mvcount(ControlAccessRights)=1 AND ControlAccessRights="","All rights",'ControlAccessRights')
| eval aceType=coalesce(ace_type_value,aceType), aceInheritance=coalesce(ace_flag_value,"This object only"), aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",coalesce(access_rights_value,AccessRights)), aceControlAccessRights=if((ControlAccessRights="Write member" OR aceObjectGuid="bf9679c0-0de6-11d0-a285-00aa003049e2") AND (aceAccessRights="All validated writes" OR AccessRights="SW"),"Add/remove self as member",coalesce(ControlAccessRights,aceObjectGuid)), user=coalesce(user, group, builtin_group, aceSid)
| stats values(aceType) as aceType values(aceInheritance) as aceInheritance values(aceControlAccessRights) as aceControlAccessRights values(aceAccessRights) as aceAccessRights values(new_ace) as new_ace values(aceInheritedTypeGuid) as aceInheritedTypeGuid by _time ObjectClass ObjectDN src_user SubjectLogonId user OpCorrelationID
| eval aceControlAccessRights=if(mvcount(aceControlAccessRights)=1 AND aceControlAccessRights="","All rights",'aceControlAccessRights')
| search NOT aceType IN ("*denied*","D","OD","XD") AND aceAccessRights IN ("Full control","All extended rights","All validated writes","Create all child objects","Delete all child objects","Delete subtree","Delete","Modify permissions","Modify owner","Write all properties",CC,CR,DC,DT,SD,SW,WD,WO,WP)
| `windows_ad_dangerous_group_acl_modification_filter`'
how_to_implement: See link in references for how to configure logging for these eventcodes. Include lookups for SID resolution if evt_resolve_ad_obj is set to 0.
known_false_positives: Unknown
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Windows AD Dangerous User ACL Modification
id: ec5b6790-595a-4fb8-ad43-56e5b55a9617
version: 1
date: '2023-11-15'
author: Dean Luxton
status: production
type: TTP
data_source:
- Windows Security 5136
description: User ACL modification event with potentially dangerous permissions applied.
search: '`wineventlog_security` EventCode=5136 ObjectClass=user
| eval old_value=if(OperationType=="%%14675",AttributeValue,null), new_value=if(OperationType=="%%14674",AttributeValue,null)
| stats min(_time) as _time values(old_value) as old_value values(new_value) as new_value values(OperationType) as OperationType by ObjectClass ObjectDN OpCorrelationID src_user SubjectLogonId
| rex field=old_value max_match=10000 "\((?P<old_values>.*?)\)"
| rex field=new_value max_match=10000 "\((?P<new_ace>.*?)\)"
| mvexpand new_ace
| where NOT new_ace IN (old_values)
| rex field=new_ace "(?P<aceType>.*?);(?P<aceFlags>.*?);(?P<aceAccessRights>.*?);(?P<aceObjectGuid>.*?);(?P<aceInheritedTypeGuid>.*?);(?P<aceSid>.*?)$"
| rex max_match=100 field=aceAccessRights "(?P<AccessRights>[A-Z]{2})"
| rex max_match=100 field=aceFlags "(?P<aceFlags>[A-Z]{2})"
| lookup msad_guid_lookup.csv guid as aceObjectGuid OUTPUT displayName as ControlAccessRights
| lookup ace_access_rights_lookup.csv access_rights_string as AccessRights OUTPUT access_rights_value
| lookup ace_type_lookup.csv ace_type_string as aceType OUTPUT ace_type_value as aceType
| lookup ace_flag_lookup.csv flag_string as aceFlags OUTPUT flag_value as ace_flag_value
``` Optional SID resolution lookups
| lookup identity_lookup_expanded objectSid as aceSid OUTPUT downLevelDomainName as user
| lookup admon_groups_def objectSid as aceSid OUTPUT cn as group ```
| lookup builtin_groups_lookup.csv builtin_group_string as aceSid OUTPUT builtin_group_name as builtin_group
| eval aceType=coalesce(ace_type_value,aceType), aceFlags=coalesce(ace_flag_value,"This object only"), aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",coalesce(access_rights_value,AccessRights)), aceControlAccessRights=coalesce(ControlAccessRights,aceObjectGuid), user=coalesce(user, group, builtin_group, aceSid)
| stats values(aceType) as aceType values(aceFlags) as aceFlags values(aceControlAccessRights) as aceControlAccessRights values(aceAccessRights) as aceAccessRights values(new_ace) as new_ace values(aceInheritedTypeGuid) as aceInheritedTypeGuid by _time ObjectClass ObjectDN src_user SubjectLogonId user OpCorrelationID
| eval aceControlAccessRights=if(mvcount(aceControlAccessRights)=1 AND aceControlAccessRights="","All rights",'aceControlAccessRights')
| search NOT aceType IN (*denied*,D,OD,XD) AND aceAccessRights IN ("Full control","All extended rights","All validated writes","Create all child objects","Delete all child objects","Delete subtree","Delete","Modify permissions","Modify owner","Write all properties",CC,CR,DC,DT,SD,SW,WD,WO,WP)
| `windows_ad_dangerous_user_acl_modification_filter`'
how_to_implement: See link in references for how to configure logging for these eventcodes. Include lookups for SID resolution if evt_resolve_ad_obj is set to 0.
known_false_positives: Unknown
references:
- https://learn.microsoft.com/en-us/windows/win32/secauthz/ace-strings
- https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1522b774-6464-41a3-87a5-1e5633c3fbbb
- https://trustedsec.com/blog/a-hitchhackers-guide-to-dacl-based-detections-part-1-a
tags:
analytic_story:
- Sneaky Active Directory Persistence Tricks
asset_type: Endpoint
confidence: 100
impact: 100
message: $src_user$ has added ACL rights to grant $user$ $aceControlAccessRights$ $aceAccessRights$ to user $ObjectDN$
mitre_attack_id:
- T1484
- T1222
- T1222.001
observable:
- name: user
type: User
role:
- Victim
- name: src_user
type: User
role:
- Victim
product:
- Splunk Enterprise
- Splunk Enterprise Security
- Splunk Cloud
risk_score: 100
required_fields:
- _time
- OperationType
- ObjectDN
- OpCorrelationID
- src_user
- AttributeLDAPDisplayName
- AttributeValue
- ObjectClass
- SubjectLogonId
- DSName
security_domain: endpoint
tests:
- name: True Positive Test
attack_data:
- data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1484/DCShadowPermissions/windows-security-xml.log
source: XmlWinEventLog:Security
sourcetype: xmlwineventlog
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,28 @@ type: TTP
data_source:
- Windows Security 5136
description: Detect ACL modification event applying the minimum required extended rights to perform a DCShadow attack.
search: '`wineventlog_security` EventCode=5136 OperationType="%%14674" ObjectClass=domainDNS
| rex field=AttributeValue max_match=10000 "OA(;|;CI);CR;9923a32a-3607-11d2-b9be-0000f87a36b2;;(?P<DSInstallReplica_user>.*?)\)"
| rex field=AttributeValue max_match=10000 "OA(;|;CI);CR;1131f6ab-9c07-11d1-f79f-00c04fc2dcd2;;(?P<DSReplSync_user>.*?)\)"
| rex field=AttributeValue max_match=10000 "OA(;|;CI);CR;1131f6ac-9c07-11d1-f79f-00c04fc2dcd2;;(?P<DSReplManageTopology_user>.*?)\)"
| mvexpand DSInstallReplica_user
| eval DCShadowPermissions=if(DSInstallReplica_user=DSReplSync_user AND DSInstallReplica_user=DSReplManageTopology_user,"true","false"), permissions_applied=mvappend("DS-Install-Replica","DS-Replication-Synchronize","DS-Replication-Manage-Topology")
| where DCShadowPermissions="true"
| stats min(_time) as _time by src_user DSInstallReplica_user permissions_applied, SubjectLogonId, DSName
| rename SubjectLogonId as TargetLogonId, src_user as initiator, DSInstallReplica_user as target_user
| appendpipe [| map search="search `wineventlog_security` EventCode=4624 TargetLogonId=$TargetLogonId$"]
| stats min(_time) as _time values(initiator) as src_user, values(DSName) as targetDomain, values(target_user) as user, values(Computer) as dest, values(permissions_applied) as permissions_applied, values(src_category) as src_category, values(src_ip) as src_ip values(LogonType) as LogonType by TargetLogonId
``` uncomment to enable SID lookups as required
| lookup identity_lookup_expanded objectSid as user OUTPUT downLevelDomainName as translated_user
| lookup admon_groups_def objectSid as user OUTPUT cn as group_user
| eval user=if(match(user, "S-1-[ 0-59]-\d{2}-\d{8,10}-\d{8,10}-\d{8,10}-[ 1-9]\d{3}") AND translated_user like "%" OR group_user like "%",coalesce(translated_user,group_user),user)
| fields - translated_user group_user
```
| eval comment=mvappend(if(isnull(src_ip),"Finding: Rerun search over longer time-range to locate src_ip from the captured TargetLogonId",null),if(match(user, "S-1-[ 0-59]-\d{2}-\d{8,10}-\d{8,10}-\d{8,10}-[ 1-9]\d{3}"),"Finding: Captured SID could not be found in A&I lookup, ensure A&I lookup is configured, also check potential group SIDs for a match",null))
search: '`wineventlog_security` EventCode=5136 ObjectClass=domainDNS
| eval old_value=if(OperationType=="%%14675",AttributeValue,null), new_value=if(OperationType=="%%14674",AttributeValue,null)
| stats min(_time) as _time values(old_value) as old_value values(new_value) as new_value values(OperationType) as OperationType by ObjectClass ObjectDN OpCorrelationID src_user SubjectLogonId
| rex field=old_value max_match=10000 "\((?P<old_values>.*?)\)"
| rex field=new_value max_match=10000 "\((?P<new_ace>.*?)\)"
| mvexpand new_ace
| where NOT new_ace IN (old_values)
| rex field=new_ace "(?P<aceType>.*?);(?P<aceFlags>.*?);(?P<aceAccessRights>.*?);(?P<aceObjectGuid>.*?);;(?P<aceSid>.*?)$"
| search aceObjectGuid IN ("9923a32a-3607-11d2-b9be-0000f87a36b2","1131f6ab-9c07-11d1-f79f-00c04fc2dcd2","1131f6ac-9c07-11d1-f79f-00c04fc2dcd2")
| rex max_match=100 field=aceAccessRights "(?P<AccessRights>[A-Z]{2})"
| rex max_match=100 field=aceFlags "(?P<aceFlags>[A-Z]{2})"
| lookup msad_guid_lookup guid as aceObjectGuid OUTPUT displayName as ControlAccessRights
| lookup ace_access_rights_lookup.csv access_rights_string as AccessRights OUTPUT access_rights_value
| lookup ace_type_lookup.csv ace_type_string as aceType OUTPUT ace_type_value
| lookup ace_flag_lookup.csv flag_string as aceFlags OUTPUT flag_value as ace_flag_value
``` Optional SID resolution lookups
| lookup identity_lookup_expanded objectSid as aceSid OUTPUT downLevelDomainName as user
| lookup admon_groups_def objectSid as aceSid OUTPUT cn as group ```
| lookup builtin_groups_lookup.csv builtin_group_string as aceSid OUTPUT builtin_group_name as builtin_group
| eval aceType=coalesce(ace_type_value,aceType), aceFlags=coalesce(ace_flag_value,"This object only"), aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",coalesce(access_rights_value,AccessRights)), aceControlAccessRights=coalesce(ControlAccessRights,aceObjectGuid), user=coalesce(user, group, builtin_group, aceSid)
| stats min(_time) as _time values(aceType) as aceType values(aceFlags) as aceFlags(inheritance) values(aceControlAccessRights) as aceControlAccessRights values(aceAccessRights) as aceAccessRights values(new_ace) as new_ace values(SubjectLogonId) as SubjectLogonId by ObjectClass ObjectDN src_user user
| search (aceControlAccessRights="DS-Install-Replica" AND aceControlAccessRights="DS-Replication-Manage-Topology" AND aceControlAccessRights="DS-Replication-Synchronize") OR (aceControlAccessRights="9923a32a-3607-11d2-b9be-0000f87a36b2" AND aceControlAccessRights="1131f6ab-9c07-11d1-f79f-00c04fc2dcd2" AND aceControlAccessRights="1131f6ac-9c07-11d1-f79f-00c04fc2dcd2")
| `windows_ad_dcshadow_acl_addition_filter`'
how_to_implement: See link in references for how to configure logging for these eventcodes.
known_false_positives: Unknown
Expand All @@ -52,10 +56,6 @@ tags:
type: User
role:
- Victim
- name: dest
type: Hostname
role:
- Victim
- name: src_ip
type: Hostname
role:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ search: '`wineventlog_security` EventCode=5136 ObjectClass=domainDNS
| rex field=old_values "(?P<aceType>.*?);(?P<aceFlags>.*?);(?P<aceAccessRights>.*?);(?P<aceObjectGuid>.*?);;(?P<aceSid>.*?)$"
| rex max_match=100 field=aceAccessRights "(?P<AccessRights>[A-Z]{2})"
| rex max_match=100 field=aceFlags "(?P<aceFlags>[A-Z]{2})"
| lookup ace_control_access_rights_lookup.csv control_access_rights_guid as aceObjectGuid OUTPUT control_access_rights_value as ControlAccessRights
| lookup msad_guid_lookup guid as aceObjectGuid OUTPUT displayName as ControlAccessRights
| lookup ace_access_rights_lookup.csv access_rights_string as AccessRights OUTPUT access_rights_value
| lookup ace_type_lookup.csv ace_type_string as aceType OUTPUT ace_type_value
| lookup ace_flag_lookup.csv flag_string as aceFlags OUTPUT flag_value as ace_flag_value
``` Optional SID resolution lookups
| lookup identity_lookup_expanded objectSid as aceSid OUTPUT downLevelDomainName as user
| lookup admon_groups_def objectSid as aceSid OUTPUT cn as group ```
| lookup builtin_groups_lookup.csv builtin_group_string as aceSid OUTPUT builtin_group_name as builtin_group
| eval aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",'access_rights_value'), aceType=ace_type_value, aceFlags=coalesce(ace_flag_value,"This object only"), aceControlAccessRights=ControlAccessRights, user=coalesce(user, group, builtin_group, aceSid)
| eval aceType=coalesce(ace_type_value,aceType), aceFlags=coalesce(ace_flag_value,"This object only"), aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",coalesce(access_rights_value,AccessRights)), aceControlAccessRights=coalesce(ControlAccessRights,aceObjectGuid), user=coalesce(user, group, builtin_group, aceSid)
| stats values(aceType) as aceType values(aceFlags) as aceFlags(inheritance) values(aceControlAccessRights) as aceControlAccessRights values(aceAccessRights) as aceAccessRights values(old_values) as old_values by _time ObjectClass ObjectDN src_user SubjectLogonId user OpCorrelationID
| eval ControlAccessRights=if(mvcount(ControlAccessRights)=1 AND ControlAccessRights="","All rights",'ControlAccessRights')
| eval aceControlAccessRights=if(mvcount(aceControlAccessRights)=1 AND aceControlAccessRights="","All rights",'aceControlAccessRights')
| `windows_ad_domain_root_acl_deletion_filter`'
how_to_implement: See link in references for how to configure logging for these eventcodes. Include lookups for SID resolution if evt_resolve_ad_obj is set to 0.
known_false_positives: Unknown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ search: '`wineventlog_security` EventCode=5136 ObjectClass=domainDNS
| rex field=new_ace "(?P<aceType>.*?);(?P<aceFlags>.*?);(?P<aceAccessRights>.*?);(?P<aceObjectGuid>.*?);;(?P<aceSid>.*?)$"
| rex max_match=100 field=aceAccessRights "(?P<AccessRights>[A-Z]{2})"
| rex max_match=100 field=aceFlags "(?P<aceFlags>[A-Z]{2})"
| lookup ace_control_access_rights_lookup.csv control_access_rights_guid as aceObjectGuid OUTPUT control_access_rights_value as ControlAccessRights
| lookup msad_guid_lookup guid as aceObjectGuid OUTPUT displayName as ControlAccessRights
| lookup ace_access_rights_lookup.csv access_rights_string as AccessRights OUTPUT access_rights_value
| lookup ace_type_lookup.csv ace_type_string as aceType OUTPUT ace_type_value
| lookup ace_flag_lookup.csv flag_string as aceFlags OUTPUT flag_value as ace_flag_value
``` Optional SID resolution lookups
| lookup identity_lookup_expanded objectSid as aceSid OUTPUT downLevelDomainName as user
| lookup admon_groups_def objectSid as aceSid OUTPUT cn as group ```
| eval aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",'access_rights_value'), aceType=ace_type_value, aceFlags=coalesce(ace_flag_value,"This object only"), aceControlAccessRights=ControlAccessRights, user=coalesce(user, group, aceSid)
| stats values(user) as user values(aceType) as aceType values(aceFlags) as aceFlags(inheritance) values(aceControlAccessRights) as aceControlAccessRights values(aceAccessRights) as aceAccessRights values(new_ace) as new_ace by _time ObjectClass ObjectDN src_user SubjectLogonId aceSid OpCorrelationID
| lookup builtin_groups_lookup.csv builtin_group_string as aceSid OUTPUT builtin_group_name as builtin_group
| eval aceAccessRights=if(aceAccessRights="CCDCLCSWRPWPDTLOCRSDRCWDWO","Full control",'access_rights_value'), aceType=ace_type_value, aceFlags=coalesce(ace_flag_value,"This object only"), aceControlAccessRights=ControlAccessRights, user=coalesce(user, group, builtin_group, aceSid)
| stats values(aceType) as aceType values(aceFlags) as aceFlags(inheritance) values(aceControlAccessRights) as aceControlAccessRights values(aceAccessRights) as aceAccessRights values(new_ace) as new_ace by _time ObjectClass ObjectDN src_user SubjectLogonId user OpCorrelationID
| eval aceControlAccessRights=if(mvcount(aceControlAccessRights)=1 AND aceControlAccessRights="","All rights",'aceControlAccessRights')
| `windows_ad_domain_root_acl_modification_filter`'
how_to_implement: See link in references for how to configure logging for these eventcodes. Include lookups for SID resolution if evt_resolve_ad_obj is set to 0.
known_false_positives: Unknown
Expand Down
Loading

0 comments on commit cea88ac

Please sign in to comment.