Detection rules › Kusto

ADWS Connection from Unexpected Binary

Author
FalconForce
Source
github.com/FalconForceTeam/FalconFriday

This query first collects the IP addresses of all machines that have the Active Directory Web Services (ADWS) service running. It then searches for network connections to these IP addresses from processes that are not expected to connect to ADWS.

MITRE ATT&CK coverage

References

Event coverage

Rule body kusto

let timeframe = 2*1h;
let ADWSIPs=(
    DeviceNetworkEvents
    | where ingestion_time() >= ago(timeframe)
    | where InitiatingProcessFolderPath == @"c:\windows\adws\microsoft.activedirectory.webservices.exe"
    | where LocalPort == 9389
    | distinct LocalIP
);
DeviceNetworkEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType == "ConnectionSuccess"
| where RemotePort == 9389
| where RemoteIP in (ADWSIPs)
| where not(isempty(InitiatingProcessFileName))
| where not(InitiatingProcessFolderPath in~ (@"c:\windows\system32\dsac.exe", @"c:\program files\powershell\7\pwsh.exe"))
| where not(InitiatingProcessFolderPath startswith @"c:\windows\system32\windowspowershell\")
| where not(InitiatingProcessFolderPath startswith @"c:\windows\syswow64\windowspowershell\")
| where not(InitiatingProcessFolderPath startswith @"c:\program files\microsoft monitoring agent\")
// Begin environment-specific filter.
// End environment-specific filter.

Stages and Predicates

Parameters

let timeframe = 2*1h;

Let binding: ADWSIPs

let ADWSIPs = (
    DeviceNetworkEvents
    | where ingestion_time() >= ago(timeframe)
    | where InitiatingProcessFolderPath == @"c:\windows\adws\microsoft.activedirectory.webservices.exe"
    | where LocalPort == 9389
    | distinct LocalIP
);

Derived from timeframe.

Stage 1: source

DeviceNetworkEvents

Stage 2: where

| where ingestion_time() >= ago(timeframe)

Stage 3: where

| where ActionType == "ConnectionSuccess"

Stage 4: where

| where RemotePort == 9389

Stage 5: where

| where RemoteIP in (ADWSIPs)

References ADWSIPs (defined above).

Stage 6: where

| where not(isempty(InitiatingProcessFileName))

Stage 7: where

| where not(InitiatingProcessFolderPath in~ (@"c:\windows\system32\dsac.exe", @"c:\program files\powershell\7\pwsh.exe"))

Stage 8: where

| where not(InitiatingProcessFolderPath startswith @"c:\windows\system32\windowspowershell\")

Stage 9: where

| where not(InitiatingProcessFolderPath startswith @"c:\windows\syswow64\windowspowershell\")

Stage 10: where

| where not(InitiatingProcessFolderPath startswith @"c:\program files\microsoft monitoring agent\")

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
InitiatingProcessFileNameis_null(no value, null check)
InitiatingProcessFolderPathinc:\program files\powershell\7\pwsh.exe, c:\windows\system32\dsac.exe
InitiatingProcessFolderPathstarts_withc:\windows\system32\windowspowershell\
InitiatingProcessFolderPathstarts_withc:\windows\syswow64\windowspowershell\
InitiatingProcessFolderPathstarts_withc:\program files\microsoft monitoring agent\

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
ActionTypeeq
  • ConnectionSuccess transforms: cased corpus 9 (kusto 9)
RemoteIPin
  • ADWSIPs transforms: cased
RemotePorteq
  • 9389 transforms: cased corpus 5 (kusto 2, sigma 1, elastic 1, splunk 1)