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

Log4j vulnerability exploit aka Log4Shell IP IOC

Back
Id6e575295-a7e6-464c-8192-3e1d8fd6a990
RulenameLog4j vulnerability exploit aka Log4Shell IP IOC
DescriptionIdentifies a match across various data feeds for IP IOCs related to the Log4j vulnerability exploit aka Log4Shell described in CVE-2021-44228.

References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=2021-44228
SeverityHigh
TacticsCommandAndControl
TechniquesT1071
Required data connectorsAWS
AzureActiveDirectory
AzureActivity
AzureFirewall
AzureMonitor(IIS)
AzureMonitor(VMInsights)
AzureMonitor(WireData)
CiscoASA
CiscoAsaAma
DNS
MicrosoftThreatProtection
Office365
PaloAltoNetworks
SecurityEvents
KindScheduled
Query frequency1h
Query period1h
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Apache Log4j Vulnerability Detection/Analytic Rules/Log4J_IPIOC_Dec112021.yaml
Version2.0.6
Arm template6e575295-a7e6-464c-8192-3e1d8fd6a990.json
Deploy To Azure
let IPList = externaldata(IPAddress:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Log4j_IOC_List.csv"] with (format="csv", ignoreFirstRecord=True);
let IPRegex = '[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}';
//Network logs
let CSlogSourceIP = CommonSecurityLog | summarize by IPAddress = SourceIP, Type;
let CSlogDestIP = CommonSecurityLog | summarize by IPAddress = DestinationIP, Type;
let CSlogMsgIP = CommonSecurityLog | extend MessageIP = extract(IPRegex, 0, Message) | summarize by IPAddress = MessageIP, Type;
let DnsIP = DnsEvents | summarize by IPAddress = IPAddresses, Type;
// If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workspace, you can uncomment one or both below.  Reference - https://docs.microsoft.com/azure/sentinel/normalization
//let imDnsIP = _Im_Dns (response_has_any_prefix=IPList) | summarize by IPAddress = ResponseName, Type;
//let imNetSessIP = imNetworkSession (dstipaddr_has_any_prefix=IPList) | summarize by IPAddress = DstIpAddr, Type;
//Cloud service logs
let officeIP = OfficeActivity | summarize by IPAddress = ClientIP, Type;
let signinIP = SigninLogs | summarize by IPAddress, Type;
let nonintSigninIP = AADNonInteractiveUserSignInLogs | summarize by IPAddress, Type;
let azureActIP = AzureActivity | summarize by IPAddress = CallerIpAddress, Type;
let awsCtIP = AWSCloudTrail | summarize by IPAddress = SourceIpAddress, Type;
//Device logs
let vmConnSourceIP = VMConnection | summarize by IPAddress = SourceIp, Type;
let vmConnDestIP = VMConnection | summarize by IPAddress = DestinationIp, Type;
let iisLogIP = W3CIISLog | summarize by IPAddress = cIP, Type;
let devNetIP = DeviceNetworkEvents | summarize by IPAddress = RemoteIP, Type;
//need to parse to get IP
let azureDiagIP = AzureDiagnostics | where ResourceType == "AZUREFIREWALLS" | where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
| where msg_s has_any (IPList) | parse msg_s with Protocol 'request from ' SourceHost ':' SourcePort 'to ' DestinationHost ':' DestinationPort '. Action:' Action | summarize by IPAddress = DestinationHost, Type;
let sysEvtIP = Event | where Source == "Microsoft-Windows-Sysmon" | where EventID == 3 | where EventData has_any (IPList) | extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
| where SourceIP in (IPList) or DestinationIP in (IPList) | extend IPAddress = iff(SourceIP in (IPList), SourceIP, DestinationIP) | summarize by IPAddress, Type;
// If you have enabled the _Im_DNS and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization
//let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP, imDnsIP, imNetSessIP
// If you uncomment above, then comment out the line below
let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP
| summarize by IPAddress
| where isnotempty(IPAddress) | where not(ipv4_is_private(IPAddress)) and IPAddress !in ('0.0.0.0','127.0.0.1');
let ipMatch = ipsort | where IPAddress in (IPList);
(union isfuzzy=true
(CommonSecurityLog
| where SourceIP in (ipMatch) or DestinationIP in (ipMatch) or Message has_any (ipMatch)
| project TimeGenerated, SourceIP, DestinationIP, Message, SourceUserID, RequestURL, Type
| extend MessageIP = extract(IPRegex, 0, Message)
| extend IPMatch = case(SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", MessageIP in (ipMatch), "Message", "No Match")
| extend timestamp = TimeGenerated, IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, IPMatch == "Message", MessageIP, "No Match")
),
(OfficeActivity
| where  ClientIP in (ipMatch)
| project TimeGenerated, UserAgent, Operation, RecordType, UserId, ClientIP, Type
| extend SourceIPAddress = ClientIP, Account = UserId
| extend timestamp = TimeGenerated , IPEntity = SourceIPAddress , AccountEntity = Account
),
(DnsEvents
| where  IPAddresses has_any (ipMatch)
| project TimeGenerated, Computer, IPAddresses, Name, ClientIP, Type
| extend DestinationIPAddress = IPAddresses,  Host = Computer
| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host
),
(VMConnection
| where SourceIp in (ipMatch) or DestinationIp in (ipMatch)
| project TimeGenerated, Computer, SourceIp, DestinationIp, Type
| extend IPMatch = case( SourceIp in (ipMatch), "SourceIP", DestinationIp in (ipMatch), "DestinationIP", "None")
| extend timestamp = TimeGenerated , IPEntity = case(IPMatch == "SourceIP", SourceIp, IPMatch == "DestinationIP", DestinationIp, "None"), Host = Computer
),
(Event
| where Source =~ "Microsoft-Windows-Sysmon"
| where EventID == 3
| where EventData has_any (ipMatch)
| project TimeGenerated, EventData, UserName, Computer, Type
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
| where SourceIP in (ipMatch) or DestinationIP in (ipMatch)
| extend IPMatch = case( SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", "None")
| extend timestamp = TimeGenerated, AccountEntity = UserName, HostEntity = Computer , IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, "None")
),
(SigninLogs
| where IPAddress in (ipMatch)
| project TimeGenerated, UserPrincipalName, IPAddress, Type
| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
),
(AADNonInteractiveUserSignInLogs
| where IPAddress in (ipMatch)
| project TimeGenerated, UserPrincipalName, IPAddress, Type
| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
),
(W3CIISLog
| where cIP in (ipMatch)
| project TimeGenerated, Computer, cIP, csUserName, Type
| extend timestamp = TimeGenerated, IPEntity = cIP, HostEntity = Computer, AccountEntity = csUserName
),
(AzureActivity
| where CallerIpAddress in (ipMatch)
| project TimeGenerated, CallerIpAddress, Caller, Type
| extend timestamp = TimeGenerated, IPEntity = CallerIpAddress, AccountEntity = Caller
),
(
AWSCloudTrail
| where SourceIpAddress in (ipMatch)
| project TimeGenerated, SourceIpAddress, UserIdentityUserName, Type
| extend timestamp = TimeGenerated, IPEntity = SourceIpAddress, AccountEntity = UserIdentityUserName
),
(
DeviceNetworkEvents
| where RemoteIP in (ipMatch)
| where ActionType =~ "InboundConnectionAccepted"
| project TimeGenerated, RemoteIP, DeviceName, Type
| extend timestamp = TimeGenerated, IPEntity = RemoteIP, HostEntity = DeviceName
),
(
AzureDiagnostics
| where ResourceType =~ "AZUREFIREWALLS"
| where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
| where msg_s has_any (ipMatch)
| project TimeGenerated, msg_s, Type
| parse msg_s with Protocol 'request from ' SourceIP ':' SourcePort 'to ' DestinationIP ':' DestinationPort '. Action:' Action
| where DestinationIP has_any (ipMatch)
| extend timestamp = TimeGenerated, IPEntity = DestinationIP
)
// If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization
//,
//(_Im_Dns (response_has_any_prefix=IPList)
//| project TimeGenerated, ResponseName, SrcIpAddr, Type
//| extend DestinationIPAddress = ResponseName,  Host = SrcIpAddr
//| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host
//),
//(imNetworkSession (dstipaddr_has_any_prefix=IPList)
//| project TimeGenerated, DstIpAddr, SrcIpAddr, Type
//| extend timestamp = TimeGenerated, IPEntity = DstIpAddr, HostEntity = SrcIpAddr
//)
)
| extend Name = tostring(split(AccountEntity, '@', 0)[0]), UPNSuffix = tostring(split(AccountEntity, '@', 1)[0])
| extend HostName = tostring(split(HostEntity, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(HostEntity, '.'), 1, -1), '.'))
relevantTechniques:
- T1071
name: Log4j vulnerability exploit aka Log4Shell IP IOC
requiredDataConnectors:
- dataTypes:
  - OfficeActivity
  connectorId: Office365
- dataTypes:
  - DnsEvents
  connectorId: DNS
- dataTypes:
  - VMConnection
  connectorId: AzureMonitor(VMInsights)
- dataTypes:
  - CommonSecurityLog
  connectorId: CiscoASA
- dataTypes:
  - CommonSecurityLog
  connectorId: CiscoAsaAma
- dataTypes:
  - CommonSecurityLog
  connectorId: PaloAltoNetworks
- dataTypes:
  - SecurityEvent
  connectorId: SecurityEvents
- dataTypes:
  - SigninLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - AADNonInteractiveUserSignInLogs
  connectorId: AzureActiveDirectory
- dataTypes:
  - WireData
  connectorId: AzureMonitor(WireData)
- dataTypes:
  - W3CIISLog
  connectorId: AzureMonitor(IIS)
- dataTypes:
  - AzureActivity
  connectorId: AzureActivity
- dataTypes:
  - AWSCloudTrail
  connectorId: AWS
- dataTypes:
  - DeviceNetworkEvents
  connectorId: MicrosoftThreatProtection
- dataTypes:
  - AzureDiagnostics
  connectorId: AzureFirewall
entityMappings:
- fieldMappings:
  - identifier: Name
    columnName: Name
  - identifier: UPNSuffix
    columnName: UPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: HostName
    columnName: HostName
  - identifier: DnsDomain
    columnName: DnsDomain
  entityType: Host
- fieldMappings:
  - identifier: Address
    columnName: IPEntity
  entityType: IP
triggerThreshold: 0
id: 6e575295-a7e6-464c-8192-3e1d8fd6a990
tactics:
- CommandAndControl
version: 2.0.6
queryPeriod: 1h
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Apache Log4j Vulnerability Detection/Analytic Rules/Log4J_IPIOC_Dec112021.yaml
triggerOperator: gt
kind: Scheduled
tags:
- Log4j
- Log4Shell
- CVE-2021-44228
- Schema: ASIMDns
  SchemaVersion: 0.1.1
- Schema: ASIMNetworkSession
  SchemaVersion: 0.2.0
queryFrequency: 1h
severity: High
status: Available
description: |
  'Identifies a match across various data feeds for IP IOCs related to the Log4j vulnerability exploit aka Log4Shell described in CVE-2021-44228.
   References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=2021-44228'  
query: |
  let IPList = externaldata(IPAddress:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Log4j_IOC_List.csv"] with (format="csv", ignoreFirstRecord=True);
  let IPRegex = '[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}';
  //Network logs
  let CSlogSourceIP = CommonSecurityLog | summarize by IPAddress = SourceIP, Type;
  let CSlogDestIP = CommonSecurityLog | summarize by IPAddress = DestinationIP, Type;
  let CSlogMsgIP = CommonSecurityLog | extend MessageIP = extract(IPRegex, 0, Message) | summarize by IPAddress = MessageIP, Type;
  let DnsIP = DnsEvents | summarize by IPAddress = IPAddresses, Type;
  // If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workspace, you can uncomment one or both below.  Reference - https://docs.microsoft.com/azure/sentinel/normalization
  //let imDnsIP = _Im_Dns (response_has_any_prefix=IPList) | summarize by IPAddress = ResponseName, Type;
  //let imNetSessIP = imNetworkSession (dstipaddr_has_any_prefix=IPList) | summarize by IPAddress = DstIpAddr, Type;
  //Cloud service logs
  let officeIP = OfficeActivity | summarize by IPAddress = ClientIP, Type;
  let signinIP = SigninLogs | summarize by IPAddress, Type;
  let nonintSigninIP = AADNonInteractiveUserSignInLogs | summarize by IPAddress, Type;
  let azureActIP = AzureActivity | summarize by IPAddress = CallerIpAddress, Type;
  let awsCtIP = AWSCloudTrail | summarize by IPAddress = SourceIpAddress, Type;
  //Device logs
  let vmConnSourceIP = VMConnection | summarize by IPAddress = SourceIp, Type;
  let vmConnDestIP = VMConnection | summarize by IPAddress = DestinationIp, Type;
  let iisLogIP = W3CIISLog | summarize by IPAddress = cIP, Type;
  let devNetIP = DeviceNetworkEvents | summarize by IPAddress = RemoteIP, Type;
  //need to parse to get IP
  let azureDiagIP = AzureDiagnostics | where ResourceType == "AZUREFIREWALLS" | where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
  | where msg_s has_any (IPList) | parse msg_s with Protocol 'request from ' SourceHost ':' SourcePort 'to ' DestinationHost ':' DestinationPort '. Action:' Action | summarize by IPAddress = DestinationHost, Type;
  let sysEvtIP = Event | where Source == "Microsoft-Windows-Sysmon" | where EventID == 3 | where EventData has_any (IPList) | extend EvData = parse_xml(EventData)
  | extend EventDetail = EvData.DataItem.EventData.Data
  | extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
  | where SourceIP in (IPList) or DestinationIP in (IPList) | extend IPAddress = iff(SourceIP in (IPList), SourceIP, DestinationIP) | summarize by IPAddress, Type;
  // If you have enabled the _Im_DNS and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization
  //let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP, imDnsIP, imNetSessIP
  // If you uncomment above, then comment out the line below
  let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP
  | summarize by IPAddress
  | where isnotempty(IPAddress) | where not(ipv4_is_private(IPAddress)) and IPAddress !in ('0.0.0.0','127.0.0.1');
  let ipMatch = ipsort | where IPAddress in (IPList);
  (union isfuzzy=true
  (CommonSecurityLog
  | where SourceIP in (ipMatch) or DestinationIP in (ipMatch) or Message has_any (ipMatch)
  | project TimeGenerated, SourceIP, DestinationIP, Message, SourceUserID, RequestURL, Type
  | extend MessageIP = extract(IPRegex, 0, Message)
  | extend IPMatch = case(SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", MessageIP in (ipMatch), "Message", "No Match")
  | extend timestamp = TimeGenerated, IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, IPMatch == "Message", MessageIP, "No Match")
  ),
  (OfficeActivity
  | where  ClientIP in (ipMatch)
  | project TimeGenerated, UserAgent, Operation, RecordType, UserId, ClientIP, Type
  | extend SourceIPAddress = ClientIP, Account = UserId
  | extend timestamp = TimeGenerated , IPEntity = SourceIPAddress , AccountEntity = Account
  ),
  (DnsEvents
  | where  IPAddresses has_any (ipMatch)
  | project TimeGenerated, Computer, IPAddresses, Name, ClientIP, Type
  | extend DestinationIPAddress = IPAddresses,  Host = Computer
  | extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host
  ),
  (VMConnection
  | where SourceIp in (ipMatch) or DestinationIp in (ipMatch)
  | project TimeGenerated, Computer, SourceIp, DestinationIp, Type
  | extend IPMatch = case( SourceIp in (ipMatch), "SourceIP", DestinationIp in (ipMatch), "DestinationIP", "None")
  | extend timestamp = TimeGenerated , IPEntity = case(IPMatch == "SourceIP", SourceIp, IPMatch == "DestinationIP", DestinationIp, "None"), Host = Computer
  ),
  (Event
  | where Source =~ "Microsoft-Windows-Sysmon"
  | where EventID == 3
  | where EventData has_any (ipMatch)
  | project TimeGenerated, EventData, UserName, Computer, Type
  | extend EvData = parse_xml(EventData)
  | extend EventDetail = EvData.DataItem.EventData.Data
  | extend SourceIP = tostring(EventDetail.[9].["#text"]), DestinationIP = tostring(EventDetail.[14].["#text"])
  | where SourceIP in (ipMatch) or DestinationIP in (ipMatch)
  | extend IPMatch = case( SourceIP in (ipMatch), "SourceIP", DestinationIP in (ipMatch), "DestinationIP", "None")
  | extend timestamp = TimeGenerated, AccountEntity = UserName, HostEntity = Computer , IPEntity = case(IPMatch == "SourceIP", SourceIP, IPMatch == "DestinationIP", DestinationIP, "None")
  ),
  (SigninLogs
  | where IPAddress in (ipMatch)
  | project TimeGenerated, UserPrincipalName, IPAddress, Type
  | extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
  ),
  (AADNonInteractiveUserSignInLogs
  | where IPAddress in (ipMatch)
  | project TimeGenerated, UserPrincipalName, IPAddress, Type
  | extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress
  ),
  (W3CIISLog
  | where cIP in (ipMatch)
  | project TimeGenerated, Computer, cIP, csUserName, Type
  | extend timestamp = TimeGenerated, IPEntity = cIP, HostEntity = Computer, AccountEntity = csUserName
  ),
  (AzureActivity
  | where CallerIpAddress in (ipMatch)
  | project TimeGenerated, CallerIpAddress, Caller, Type
  | extend timestamp = TimeGenerated, IPEntity = CallerIpAddress, AccountEntity = Caller
  ),
  (
  AWSCloudTrail
  | where SourceIpAddress in (ipMatch)
  | project TimeGenerated, SourceIpAddress, UserIdentityUserName, Type
  | extend timestamp = TimeGenerated, IPEntity = SourceIpAddress, AccountEntity = UserIdentityUserName
  ),
  (
  DeviceNetworkEvents
  | where RemoteIP in (ipMatch)
  | where ActionType =~ "InboundConnectionAccepted"
  | project TimeGenerated, RemoteIP, DeviceName, Type
  | extend timestamp = TimeGenerated, IPEntity = RemoteIP, HostEntity = DeviceName
  ),
  (
  AzureDiagnostics
  | where ResourceType =~ "AZUREFIREWALLS"
  | where Category in ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
  | where msg_s has_any (ipMatch)
  | project TimeGenerated, msg_s, Type
  | parse msg_s with Protocol 'request from ' SourceIP ':' SourcePort 'to ' DestinationIP ':' DestinationPort '. Action:' Action
  | where DestinationIP has_any (ipMatch)
  | extend timestamp = TimeGenerated, IPEntity = DestinationIP
  )
  // If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization
  //,
  //(_Im_Dns (response_has_any_prefix=IPList)
  //| project TimeGenerated, ResponseName, SrcIpAddr, Type
  //| extend DestinationIPAddress = ResponseName,  Host = SrcIpAddr
  //| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host
  //),
  //(imNetworkSession (dstipaddr_has_any_prefix=IPList)
  //| project TimeGenerated, DstIpAddr, SrcIpAddr, Type
  //| extend timestamp = TimeGenerated, IPEntity = DstIpAddr, HostEntity = SrcIpAddr
  //)
  )
  | extend Name = tostring(split(AccountEntity, '@', 0)[0]), UPNSuffix = tostring(split(AccountEntity, '@', 1)[0])
  | extend HostName = tostring(split(HostEntity, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(HostEntity, '.'), 1, -1), '.'))  
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2024-01-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/6e575295-a7e6-464c-8192-3e1d8fd6a990')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/6e575295-a7e6-464c-8192-3e1d8fd6a990')]",
      "properties": {
        "alertRuleTemplateName": "6e575295-a7e6-464c-8192-3e1d8fd6a990",
        "customDetails": null,
        "description": "'Identifies a match across various data feeds for IP IOCs related to the Log4j vulnerability exploit aka Log4Shell described in CVE-2021-44228.\n References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=2021-44228'\n",
        "displayName": "Log4j vulnerability exploit aka Log4Shell IP IOC",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "HostName",
                "identifier": "HostName"
              },
              {
                "columnName": "DnsDomain",
                "identifier": "DnsDomain"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "IPEntity",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Apache Log4j Vulnerability Detection/Analytic Rules/Log4J_IPIOC_Dec112021.yaml",
        "query": "let IPList = externaldata(IPAddress:string)[@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/Log4j_IOC_List.csv\"] with (format=\"csv\", ignoreFirstRecord=True);\nlet IPRegex = '[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}';\n//Network logs\nlet CSlogSourceIP = CommonSecurityLog | summarize by IPAddress = SourceIP, Type;\nlet CSlogDestIP = CommonSecurityLog | summarize by IPAddress = DestinationIP, Type;\nlet CSlogMsgIP = CommonSecurityLog | extend MessageIP = extract(IPRegex, 0, Message) | summarize by IPAddress = MessageIP, Type;\nlet DnsIP = DnsEvents | summarize by IPAddress = IPAddresses, Type;\n// If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workspace, you can uncomment one or both below.  Reference - https://docs.microsoft.com/azure/sentinel/normalization\n//let imDnsIP = _Im_Dns (response_has_any_prefix=IPList) | summarize by IPAddress = ResponseName, Type;\n//let imNetSessIP = imNetworkSession (dstipaddr_has_any_prefix=IPList) | summarize by IPAddress = DstIpAddr, Type;\n//Cloud service logs\nlet officeIP = OfficeActivity | summarize by IPAddress = ClientIP, Type;\nlet signinIP = SigninLogs | summarize by IPAddress, Type;\nlet nonintSigninIP = AADNonInteractiveUserSignInLogs | summarize by IPAddress, Type;\nlet azureActIP = AzureActivity | summarize by IPAddress = CallerIpAddress, Type;\nlet awsCtIP = AWSCloudTrail | summarize by IPAddress = SourceIpAddress, Type;\n//Device logs\nlet vmConnSourceIP = VMConnection | summarize by IPAddress = SourceIp, Type;\nlet vmConnDestIP = VMConnection | summarize by IPAddress = DestinationIp, Type;\nlet iisLogIP = W3CIISLog | summarize by IPAddress = cIP, Type;\nlet devNetIP = DeviceNetworkEvents | summarize by IPAddress = RemoteIP, Type;\n//need to parse to get IP\nlet azureDiagIP = AzureDiagnostics | where ResourceType == \"AZUREFIREWALLS\" | where Category in (\"AzureFirewallApplicationRule\", \"AzureFirewallNetworkRule\")\n| where msg_s has_any (IPList) | parse msg_s with Protocol 'request from ' SourceHost ':' SourcePort 'to ' DestinationHost ':' DestinationPort '. Action:' Action | summarize by IPAddress = DestinationHost, Type;\nlet sysEvtIP = Event | where Source == \"Microsoft-Windows-Sysmon\" | where EventID == 3 | where EventData has_any (IPList) | extend EvData = parse_xml(EventData)\n| extend EventDetail = EvData.DataItem.EventData.Data\n| extend SourceIP = tostring(EventDetail.[9].[\"#text\"]), DestinationIP = tostring(EventDetail.[14].[\"#text\"])\n| where SourceIP in (IPList) or DestinationIP in (IPList) | extend IPAddress = iff(SourceIP in (IPList), SourceIP, DestinationIP) | summarize by IPAddress, Type;\n// If you have enabled the _Im_DNS and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization\n//let ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP, imDnsIP, imNetSessIP\n// If you uncomment above, then comment out the line below\nlet ipsort = union isfuzzy=true CSlogDestIP, CSlogMsgIP, CSlogSourceIP, DnsIP, officeIP, signinIP, nonintSigninIP, azureActIP, awsCtIP, vmConnDestIP, vmConnSourceIP, azureDiagIP, sysEvtIP\n| summarize by IPAddress\n| where isnotempty(IPAddress) | where not(ipv4_is_private(IPAddress)) and IPAddress !in ('0.0.0.0','127.0.0.1');\nlet ipMatch = ipsort | where IPAddress in (IPList);\n(union isfuzzy=true\n(CommonSecurityLog\n| where SourceIP in (ipMatch) or DestinationIP in (ipMatch) or Message has_any (ipMatch)\n| project TimeGenerated, SourceIP, DestinationIP, Message, SourceUserID, RequestURL, Type\n| extend MessageIP = extract(IPRegex, 0, Message)\n| extend IPMatch = case(SourceIP in (ipMatch), \"SourceIP\", DestinationIP in (ipMatch), \"DestinationIP\", MessageIP in (ipMatch), \"Message\", \"No Match\")\n| extend timestamp = TimeGenerated, IPEntity = case(IPMatch == \"SourceIP\", SourceIP, IPMatch == \"DestinationIP\", DestinationIP, IPMatch == \"Message\", MessageIP, \"No Match\")\n),\n(OfficeActivity\n| where  ClientIP in (ipMatch)\n| project TimeGenerated, UserAgent, Operation, RecordType, UserId, ClientIP, Type\n| extend SourceIPAddress = ClientIP, Account = UserId\n| extend timestamp = TimeGenerated , IPEntity = SourceIPAddress , AccountEntity = Account\n),\n(DnsEvents\n| where  IPAddresses has_any (ipMatch)\n| project TimeGenerated, Computer, IPAddresses, Name, ClientIP, Type\n| extend DestinationIPAddress = IPAddresses,  Host = Computer\n| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host\n),\n(VMConnection\n| where SourceIp in (ipMatch) or DestinationIp in (ipMatch)\n| project TimeGenerated, Computer, SourceIp, DestinationIp, Type\n| extend IPMatch = case( SourceIp in (ipMatch), \"SourceIP\", DestinationIp in (ipMatch), \"DestinationIP\", \"None\")\n| extend timestamp = TimeGenerated , IPEntity = case(IPMatch == \"SourceIP\", SourceIp, IPMatch == \"DestinationIP\", DestinationIp, \"None\"), Host = Computer\n),\n(Event\n| where Source =~ \"Microsoft-Windows-Sysmon\"\n| where EventID == 3\n| where EventData has_any (ipMatch)\n| project TimeGenerated, EventData, UserName, Computer, Type\n| extend EvData = parse_xml(EventData)\n| extend EventDetail = EvData.DataItem.EventData.Data\n| extend SourceIP = tostring(EventDetail.[9].[\"#text\"]), DestinationIP = tostring(EventDetail.[14].[\"#text\"])\n| where SourceIP in (ipMatch) or DestinationIP in (ipMatch)\n| extend IPMatch = case( SourceIP in (ipMatch), \"SourceIP\", DestinationIP in (ipMatch), \"DestinationIP\", \"None\")\n| extend timestamp = TimeGenerated, AccountEntity = UserName, HostEntity = Computer , IPEntity = case(IPMatch == \"SourceIP\", SourceIP, IPMatch == \"DestinationIP\", DestinationIP, \"None\")\n),\n(SigninLogs\n| where IPAddress in (ipMatch)\n| project TimeGenerated, UserPrincipalName, IPAddress, Type\n| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress\n),\n(AADNonInteractiveUserSignInLogs\n| where IPAddress in (ipMatch)\n| project TimeGenerated, UserPrincipalName, IPAddress, Type\n| extend timestamp = TimeGenerated, AccountEntity = UserPrincipalName, IPEntity = IPAddress\n),\n(W3CIISLog\n| where cIP in (ipMatch)\n| project TimeGenerated, Computer, cIP, csUserName, Type\n| extend timestamp = TimeGenerated, IPEntity = cIP, HostEntity = Computer, AccountEntity = csUserName\n),\n(AzureActivity\n| where CallerIpAddress in (ipMatch)\n| project TimeGenerated, CallerIpAddress, Caller, Type\n| extend timestamp = TimeGenerated, IPEntity = CallerIpAddress, AccountEntity = Caller\n),\n(\nAWSCloudTrail\n| where SourceIpAddress in (ipMatch)\n| project TimeGenerated, SourceIpAddress, UserIdentityUserName, Type\n| extend timestamp = TimeGenerated, IPEntity = SourceIpAddress, AccountEntity = UserIdentityUserName\n),\n(\nDeviceNetworkEvents\n| where RemoteIP in (ipMatch)\n| where ActionType =~ \"InboundConnectionAccepted\"\n| project TimeGenerated, RemoteIP, DeviceName, Type\n| extend timestamp = TimeGenerated, IPEntity = RemoteIP, HostEntity = DeviceName\n),\n(\nAzureDiagnostics\n| where ResourceType =~ \"AZUREFIREWALLS\"\n| where Category in (\"AzureFirewallApplicationRule\", \"AzureFirewallNetworkRule\")\n| where msg_s has_any (ipMatch)\n| project TimeGenerated, msg_s, Type\n| parse msg_s with Protocol 'request from ' SourceIP ':' SourcePort 'to ' DestinationIP ':' DestinationPort '. Action:' Action\n| where DestinationIP has_any (ipMatch)\n| extend timestamp = TimeGenerated, IPEntity = DestinationIP\n)\n// If you have enabled the _Im_Dns and/or imNetworkSession normalization in your workdspace, you can uncomment below and include. Reference - https://docs.microsoft.com/azure/sentinel/normalization\n//,\n//(_Im_Dns (response_has_any_prefix=IPList)\n//| project TimeGenerated, ResponseName, SrcIpAddr, Type\n//| extend DestinationIPAddress = ResponseName,  Host = SrcIpAddr\n//| extend timestamp = TimeGenerated, IPEntity = DestinationIPAddress, HostEntity = Host\n//),\n//(imNetworkSession (dstipaddr_has_any_prefix=IPList)\n//| project TimeGenerated, DstIpAddr, SrcIpAddr, Type\n//| extend timestamp = TimeGenerated, IPEntity = DstIpAddr, HostEntity = SrcIpAddr\n//)\n)\n| extend Name = tostring(split(AccountEntity, '@', 0)[0]), UPNSuffix = tostring(split(AccountEntity, '@', 1)[0])\n| extend HostName = tostring(split(HostEntity, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(HostEntity, '.'), 1, -1), '.'))\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "PT1H",
        "severity": "High",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "tags": [
          "Log4j",
          "Log4Shell",
          "CVE-2021-44228",
          {
            "Schema": "ASIMDns",
            "SchemaVersion": "0.1.1"
          },
          {
            "Schema": "ASIMNetworkSession",
            "SchemaVersion": "0.2.0"
          }
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "2.0.6",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}