Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

AD FS Remote Auth Sync Connection

Back
Id2f4165a6-c4fb-4e94-861e-37f1b4d6c0e6
RulenameAD FS Remote Auth Sync Connection
DescriptionThis detection uses Security events from the “AD FS Auditing” provider to detect suspicious authentication events on an AD FS server. The results then get

correlated with events from the Windows Filtering Platform (WFP) to detect suspicious incoming network traffic on port 80 on the AD FS server.

This could be a sign of a threat actor trying to use replication services on the AD FS server to get its configuration settings and extract

sensitive information such as AD FS certificates.

In order to use this query you need to enable AD FS auditing on the AD FS Server.

References:

https://docs.microsoft.com/windows-server/identity/ad-fs/troubleshooting/ad-fs-tshoot-logging

https://twitter.com/OTR_Community/status/1387038995016732672
SeverityMedium
TacticsCollection
TechniquesT1005
Required data connectorsSecurityEvents
WindowsSecurityEvents
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Windows Security Events/Analytic Rules/ADFSRemoteAuthSyncConnection.yaml
Version1.0.2
Arm template2f4165a6-c4fb-4e94-861e-37f1b4d6c0e6.json
Deploy To Azure
// Adjust this to use a longer timeframe to identify ADFS servers
//let lookback = 0d;
// Adjust this to adjust detection timeframe
//let timeframe = 1d;
// SamAccountName of AD FS Service Account. Filter on the use of a specific AD FS user account
//let adfsuser = 'adfsadmin';
// Identify ADFS Servers
let ADFS_Servers = (
    SecurityEvent
    //| where TimeGenerated > ago(timeframe+lookback)
    | where EventSourceName == 'AD FS Auditing'
    | distinct Computer
);
SecurityEvent
    //| where TimeGenerated > ago(timeframe)
    | where Computer in~ (ADFS_Servers)
    // A token of type 'http://schemas.microsoft.com/ws/2006/05/servicemodel/tokens/SecureConversation'
    // for relying party '-' was successfully authenticated.
    | where EventID == 412
    | extend EventData = parse_xml(EventData).EventData.Data
    | extend InstanceId = tostring(EventData[0])
| join kind=inner
(
    SecurityEvent
    //| where TimeGenerated > ago(timeframe)
    | where Computer in~ (ADFS_Servers)
    // Events to identify caller identity from event 412
    | where EventID == 501
    | extend EventData = parse_xml(EventData).EventData.Data
    | where tostring(EventData[1]) contains 'identity/claims/name'
    | extend InstanceId = tostring(EventData[0])
    | extend ClaimsName = tostring(EventData[2])
    // Filter on the use of a specific AD FS user account
    //| where ClaimsName contains adfsuser
)
on $left.InstanceId == $right.InstanceId
| join kind=inner
(
    SecurityEvent
    | where EventID == 5156
    | where Computer in~ (ADFS_Servers)
    | 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, Computer, EventID)
    | extend DestPort = column_ifexists("DestPort", ""),
          Direction = column_ifexists("Direction", ""),
          Application = column_ifexists("Application", ""),
          DestAddress = column_ifexists("DestAddress", ""),
          SourceAddress = column_ifexists("SourceAddress", ""),
          SourcePort = column_ifexists("SourcePort", "")
    // Look for inbound connections from endpoints on port 80
    | where DestPort == 80 and Direction == '%%14592' and Application == 'System'
    | where DestAddress !in ('::1','0:0:0:0:0:0:0:1') 
)
on $left.Computer == $right.Computer
| project TimeGenerated, Computer, ClaimsName, SourceAddress, SourcePort
| 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])
name: AD FS Remote Auth Sync Connection
query: |
  // Adjust this to use a longer timeframe to identify ADFS servers
  //let lookback = 0d;
  // Adjust this to adjust detection timeframe
  //let timeframe = 1d;
  // SamAccountName of AD FS Service Account. Filter on the use of a specific AD FS user account
  //let adfsuser = 'adfsadmin';
  // Identify ADFS Servers
  let ADFS_Servers = (
      SecurityEvent
      //| where TimeGenerated > ago(timeframe+lookback)
      | where EventSourceName == 'AD FS Auditing'
      | distinct Computer
  );
  SecurityEvent
      //| where TimeGenerated > ago(timeframe)
      | where Computer in~ (ADFS_Servers)
      // A token of type 'http://schemas.microsoft.com/ws/2006/05/servicemodel/tokens/SecureConversation'
      // for relying party '-' was successfully authenticated.
      | where EventID == 412
      | extend EventData = parse_xml(EventData).EventData.Data
      | extend InstanceId = tostring(EventData[0])
  | join kind=inner
  (
      SecurityEvent
      //| where TimeGenerated > ago(timeframe)
      | where Computer in~ (ADFS_Servers)
      // Events to identify caller identity from event 412
      | where EventID == 501
      | extend EventData = parse_xml(EventData).EventData.Data
      | where tostring(EventData[1]) contains 'identity/claims/name'
      | extend InstanceId = tostring(EventData[0])
      | extend ClaimsName = tostring(EventData[2])
      // Filter on the use of a specific AD FS user account
      //| where ClaimsName contains adfsuser
  )
  on $left.InstanceId == $right.InstanceId
  | join kind=inner
  (
      SecurityEvent
      | where EventID == 5156
      | where Computer in~ (ADFS_Servers)
      | 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, Computer, EventID)
      | extend DestPort = column_ifexists("DestPort", ""),
            Direction = column_ifexists("Direction", ""),
            Application = column_ifexists("Application", ""),
            DestAddress = column_ifexists("DestAddress", ""),
            SourceAddress = column_ifexists("SourceAddress", ""),
            SourcePort = column_ifexists("SourcePort", "")
      // Look for inbound connections from endpoints on port 80
      | where DestPort == 80 and Direction == '%%14592' and Application == 'System'
      | where DestAddress !in ('::1','0:0:0:0:0:0:0:1') 
  )
  on $left.Computer == $right.Computer
  | project TimeGenerated, Computer, ClaimsName, SourceAddress, SourcePort
  | 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])  
description: |
  'This detection uses Security events from the "AD FS Auditing" provider to detect suspicious authentication events on an AD FS server. The results then get
  correlated with events from the Windows Filtering Platform (WFP) to detect suspicious incoming network traffic on port 80 on the AD FS server.
  This could be a sign of a threat actor trying to use replication services on the AD FS server to get its configuration settings and extract
  sensitive information such as AD FS certificates.
  In order to use this query you need to enable AD FS auditing on the AD FS Server.
  References: 
  https://docs.microsoft.com/windows-server/identity/ad-fs/troubleshooting/ad-fs-tshoot-logging
  https://twitter.com/OTR_Community/status/1387038995016732672
  '  
tactics:
- Collection
requiredDataConnectors:
- dataTypes:
  - SecurityEvent
  connectorId: SecurityEvents
- dataTypes:
  - SecurityEvent
  connectorId: WindowsSecurityEvents
queryPeriod: 1d
queryFrequency: 1d
status: Available
triggerThreshold: 0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Windows Security Events/Analytic Rules/ADFSRemoteAuthSyncConnection.yaml
id: 2f4165a6-c4fb-4e94-861e-37f1b4d6c0e6
triggerOperator: gt
version: 1.0.2
relevantTechniques:
- T1005
severity: Medium
kind: Scheduled
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: FullName
    columnName: ClaimsName
  - identifier: Name
    columnName: AccountName
  - identifier: NTDomain
    columnName: AccountNTDomain
- entityType: Host
  fieldMappings:
  - identifier: FullName
    columnName: Computer
  - identifier: HostName
    columnName: HostName
  - identifier: DnsDomain
    columnName: HostNameDomain
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: SourceAddress
tags:
- SimuLand
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/2f4165a6-c4fb-4e94-861e-37f1b4d6c0e6')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/2f4165a6-c4fb-4e94-861e-37f1b4d6c0e6')]",
      "properties": {
        "alertRuleTemplateName": "2f4165a6-c4fb-4e94-861e-37f1b4d6c0e6",
        "customDetails": null,
        "description": "'This detection uses Security events from the \"AD FS Auditing\" provider to detect suspicious authentication events on an AD FS server. The results then get\ncorrelated with events from the Windows Filtering Platform (WFP) to detect suspicious incoming network traffic on port 80 on the AD FS server.\nThis could be a sign of a threat actor trying to use replication services on the AD FS server to get its configuration settings and extract\nsensitive information such as AD FS certificates.\nIn order to use this query you need to enable AD FS auditing on the AD FS Server.\nReferences: \nhttps://docs.microsoft.com/windows-server/identity/ad-fs/troubleshooting/ad-fs-tshoot-logging\nhttps://twitter.com/OTR_Community/status/1387038995016732672\n'\n",
        "displayName": "AD FS Remote Auth Sync Connection",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "ClaimsName",
                "identifier": "FullName"
              },
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "AccountNTDomain",
                "identifier": "NTDomain"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "Computer",
                "identifier": "FullName"
              },
              {
                "columnName": "HostName",
                "identifier": "HostName"
              },
              {
                "columnName": "HostNameDomain",
                "identifier": "DnsDomain"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Windows Security Events/Analytic Rules/ADFSRemoteAuthSyncConnection.yaml",
        "query": "// Adjust this to use a longer timeframe to identify ADFS servers\n//let lookback = 0d;\n// Adjust this to adjust detection timeframe\n//let timeframe = 1d;\n// SamAccountName of AD FS Service Account. Filter on the use of a specific AD FS user account\n//let adfsuser = 'adfsadmin';\n// Identify ADFS Servers\nlet ADFS_Servers = (\n    SecurityEvent\n    //| where TimeGenerated > ago(timeframe+lookback)\n    | where EventSourceName == 'AD FS Auditing'\n    | distinct Computer\n);\nSecurityEvent\n    //| where TimeGenerated > ago(timeframe)\n    | where Computer in~ (ADFS_Servers)\n    // A token of type 'http://schemas.microsoft.com/ws/2006/05/servicemodel/tokens/SecureConversation'\n    // for relying party '-' was successfully authenticated.\n    | where EventID == 412\n    | extend EventData = parse_xml(EventData).EventData.Data\n    | extend InstanceId = tostring(EventData[0])\n| join kind=inner\n(\n    SecurityEvent\n    //| where TimeGenerated > ago(timeframe)\n    | where Computer in~ (ADFS_Servers)\n    // Events to identify caller identity from event 412\n    | where EventID == 501\n    | extend EventData = parse_xml(EventData).EventData.Data\n    | where tostring(EventData[1]) contains 'identity/claims/name'\n    | extend InstanceId = tostring(EventData[0])\n    | extend ClaimsName = tostring(EventData[2])\n    // Filter on the use of a specific AD FS user account\n    //| where ClaimsName contains adfsuser\n)\non $left.InstanceId == $right.InstanceId\n| join kind=inner\n(\n    SecurityEvent\n    | where EventID == 5156\n    | where Computer in~ (ADFS_Servers)\n    | extend EventData = parse_xml(EventData).EventData.Data\n    | mv-expand bagexpansion=array EventData\n    | evaluate bag_unpack(EventData)\n    | extend Key = tostring(column_ifexists('@Name', \"\")), Value = column_ifexists('#text', \"\")\n    | evaluate pivot(Key, any(Value), TimeGenerated, Computer, EventID)\n    | extend DestPort = column_ifexists(\"DestPort\", \"\"),\n          Direction = column_ifexists(\"Direction\", \"\"),\n          Application = column_ifexists(\"Application\", \"\"),\n          DestAddress = column_ifexists(\"DestAddress\", \"\"),\n          SourceAddress = column_ifexists(\"SourceAddress\", \"\"),\n          SourcePort = column_ifexists(\"SourcePort\", \"\")\n    // Look for inbound connections from endpoints on port 80\n    | where DestPort == 80 and Direction == '%%14592' and Application == 'System'\n    | where DestAddress !in ('::1','0:0:0:0:0:0:0:1') \n)\non $left.Computer == $right.Computer\n| project TimeGenerated, Computer, ClaimsName, SourceAddress, SourcePort\n| extend HostName = tostring(split(Computer, \".\")[0]), DomainIndex = toint(indexof(Computer, '.'))\n| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)\n| extend AccountName = tostring(split(Account, @'\\')[1]), AccountNTDomain = tostring(split(Account, @'\\')[0])\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "status": "Available",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Collection"
        ],
        "tags": [
          "SimuLand"
        ],
        "techniques": [
          "T1005"
        ],
        "templateVersion": "1.0.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}