id: faf1a6ff-53b5-4f92-8c55-4b20e9957594 name: Exchange OAB Virtual Directory Attribute Containing Potential Webshell description: | 'This query uses Windows Event ID 5136 in order to detect potential webshell deployment by exploitation of CVE-2021-27065. This query looks for changes to the InternalHostName or ExternalHostName properties of Exchange OAB Virtual Directory objects in AD Directory Services where the new objects contain potential webshell objects.' severity: High requiredDataConnectors: - connectorId: SecurityEvents dataTypes: - SecurityEvent - connectorId: WindowsSecurityEvents dataTypes: - SecurityEvent queryFrequency: 1h queryPeriod: 1h triggerOperator: gt triggerThreshold: 0 status: Available tactics: - InitialAccess relevantTechniques: - T1190 query: | SecurityEvent // Look for specific Directory Service Changes and parse data | where EventID == 5136 | extend EventData = parse_xml(EventData).EventData.Data | mv-expand bagexpansion = array EventData | evaluate bag_unpack(EventData) | extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "") | evaluate pivot(Key, any(Value),TimeGenerated, EventID, Computer, Account, AccountType, EventSourceName, Activity, SubjectAccount) // Where changes relate to Exchange OAB | extend ObjectClass = column_ifexists("ObjectClass", "") | where ObjectClass =~ "msExchOABVirtualDirectory" // Look for InternalHostName or ExternalHostName properties being changed | extend AttributeLDAPDisplayName = column_ifexists("AttributeLDAPDisplayName", "") | where AttributeLDAPDisplayName in~ ("msExchExternalHostName", "msExchInternalHostName") // Look for suspected webshell activity | extend AttributeValue = column_ifexists("AttributeValue", "") | where AttributeValue has "script" | project-rename LastSeen = TimeGenerated | extend ObjectDN = column_ifexists("ObjectDN", "") | project-reorder LastSeen, Computer, Account, ObjectDN, AttributeLDAPDisplayName, AttributeValue | extend timestamp = LastSeen | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.')) | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer) | extend AccountName = tostring(split(Account, @'\')[1]), AccountNTDomain = tostring(split(Account, @'\')[0]) entityMappings: - entityType: Account fieldMappings: - identifier: FullName columnName: Account - identifier: Name columnName: AccountName - identifier: NTDomain columnName: AccountNTDomain - entityType: Host fieldMappings: - identifier: FullName columnName: Computer - identifier: HostName columnName: HostName - identifier: DnsDomain columnName: HostNameDomain version: 1.0.4 kind: Scheduled