Detections/SecurityEvent/UserAccountAdd-Removed.yaml (129 lines of code) (raw):

id: 7efc75ce-e2a4-400f-a8b1-283d3b0f2c60 name: Account added and removed from privileged groups description: | 'Identifies accounts that are added to a privileged group and then quickly removed, which could be a sign of compromise.' severity: Low requiredDataConnectors: - connectorId: SecurityEvents dataTypes: - SecurityEvent - connectorId: WindowsSecurityEvents dataTypes: - SecurityEvent - connectorId: WindowsForwardedEvents dataTypes: - WindowsEvent queryFrequency: 1d queryPeriod: 1d triggerOperator: gt triggerThreshold: 0 tactics: - Persistence - PrivilegeEscalation relevantTechniques: - T1098 - T1078 query: | let WellKnownLocalSID = "S-1-5-32-5[0-9][0-9]$"; let WellKnownGroupSID = "S-1-5-21-[0-9]*-[0-9]*-[0-9]*-5[0-9][0-9]$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1102$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1103$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-498$|S-1-5-21-[0-9]*-[0-9]*-[0-9]*-1000$"; let AC_Add = (union isfuzzy=true (SecurityEvent // Event ID related to member addition. | where EventID in (4728, 4732,4756) | where TargetSid matches regex WellKnownLocalSID or TargetSid matches regex WellKnownGroupSID | parse EventData with * '"MemberName">' * '=' AccountAdded ",OU" * | where isnotempty(AccountAdded) | extend GroupAddedTo = TargetUserName, AddingAccount = Account | extend AccountAdded_GroupAddedTo_AddingAccount = strcat(AccountAdded, "||", GroupAddedTo, "||", AddingAccount ) | project AccountAdded_GroupAddedTo_AddingAccount, AccountAddedTime = TimeGenerated ), (WindowsEvent // Event ID related to member addition. | where EventID in (4728, 4732,4756) | extend TargetSid = tostring(EventData.TargetSid) | where TargetSid matches regex WellKnownLocalSID or TargetSid matches regex WellKnownGroupSID | parse EventData.MemberName with * '"MemberName">' * '=' AccountAdded ",OU" * | where isnotempty(AccountAdded) | extend TargetUserName = tostring(EventData.TargetUserName) | extend AddingAccount = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName)) | extend GroupAddedTo = TargetUserName | extend AccountAdded_GroupAddedTo_AddingAccount = strcat(AccountAdded, "||", GroupAddedTo, "||", AddingAccount ) | project AccountAdded_GroupAddedTo_AddingAccount, AccountAddedTime = TimeGenerated ) ); let AC_Remove = ( union isfuzzy=true (SecurityEvent // Event IDs related to member removal. | where EventID in (4729,4733,4757) | where TargetSid matches regex WellKnownLocalSID or TargetSid matches regex WellKnownGroupSID | parse EventData with * '"MemberName">' * '=' AccountRemoved ",OU" * | where isnotempty(AccountRemoved) | extend GroupRemovedFrom = TargetUserName, RemovingAccount = Account | extend AccountRemoved_GroupRemovedFrom_RemovingAccount = strcat(AccountRemoved, "||", GroupRemovedFrom, "||", RemovingAccount) | project AccountRemoved_GroupRemovedFrom_RemovingAccount, AccountRemovedTime = TimeGenerated, Computer, AccountRemoved = tolower(AccountRemoved), RemovingAccount, RemovingAccountLogonId = SubjectLogonId, GroupRemovedFrom = TargetUserName, TargetDomainName ), (WindowsEvent // Event IDs related to member removal. | where EventID in (4729,4733,4757) | extend TargetSid = tostring(EventData.TargetSid) | where TargetSid matches regex WellKnownLocalSID or TargetSid matches regex WellKnownGroupSID | parse EventData.MemberName with * '"MemberName">' * '=' AccountRemoved ",OU" * | where isnotempty(AccountRemoved) | extend TargetUserName = tostring(EventData.TargetUserName) | extend RemovingAccount = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName)) | extend GroupRemovedFrom = TargetUserName | extend AccountRemoved_GroupRemovedFrom_RemovingAccount = strcat(AccountRemoved, "||", GroupRemovedFrom, "||", RemovingAccount) | extend RemovedAccountLogonId= tostring(EventData.SubjectLogonId) | extend TargetDomainName = tostring(EventData.TargetDomainName) | project AccountRemoved_GroupRemovedFrom_RemovingAccount, AccountRemovedTime = TimeGenerated, Computer, AccountRemoved = tolower(AccountRemoved), RemovingAccount, RemovedAccountLogonId, GroupRemovedFrom = TargetUserName, TargetDomainName )); AC_Add | join kind = inner AC_Remove on $left.AccountAdded_GroupAddedTo_AddingAccount == $right.AccountRemoved_GroupRemovedFrom_RemovingAccount | extend DurationinSecondAfter_Removed = datetime_diff ('second', AccountRemovedTime, AccountAddedTime) | where DurationinSecondAfter_Removed > 0 | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.')) | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer) | extend RemovedAccountName = tostring(split(AccountRemoved, @"\")[1]), RemovedAccountNTDomain = tostring(split(AccountRemoved, @"\")[0]) | extend RemovingAccountName = tostring(split(RemovingAccount, @"\")[1]), RemovingAccountNTDomain = tostring(split(RemovingAccount, @"\")[0]) | project-away DomainIndex entityMappings: - entityType: Account fieldMappings: - identifier: FullName columnName: AccountRemoved - identifier: Name columnName: RemovedAccountName - identifier: NTDomain columnName: RemovedAccountNTDomain - entityType: Account fieldMappings: - identifier: FullName columnName: RemovingAccount - identifier: Name columnName: RemovingAccountName - identifier: NTDomain columnName: RemovingAccountNTDomain - entityType: Host fieldMappings: - identifier: FullName columnName: Computer - identifier: HostName columnName: HostName - identifier: NTDomain columnName: HostNameDomain version: 1.1.5 kind: Scheduled metadata: source: kind: Community author: name: Microsoft Security Research support: tier: Community categories: domains: [ "Security - Others", "Identity" ]