Detection rules › Kusto
Log4j vulnerability exploit aka Log4Shell IP IOC
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
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
Telemetry coverage
Rules detecting the same action
These rules filter on the same operation.
Rule body
id: 6e575295-a7e6-464c-8192-3e1d8fd6a990
name: Log4j vulnerability exploit aka Log4Shell IP IOC
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'
severity: High
status: Available
tags:
- Log4j
- Log4Shell
- CVE-2021-44228
- Schema: ASIMDns
SchemaVersion: 0.1.1
- Schema: ASIMNetworkSession
SchemaVersion: 0.2.0
requiredDataConnectors:
- connectorId: Office365
dataTypes:
- OfficeActivity
- connectorId: DNS
dataTypes:
- DnsEvents
- connectorId: AzureMonitor(VMInsights)
dataTypes:
- VMConnection
- connectorId: CiscoASA
dataTypes:
- CommonSecurityLog
- connectorId: CiscoAsaAma
dataTypes:
- CommonSecurityLog
- connectorId: PaloAltoNetworks
dataTypes:
- CommonSecurityLog
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
- connectorId: AzureActiveDirectory
dataTypes:
- AADNonInteractiveUserSignInLogs
- connectorId: AzureMonitor(WireData)
dataTypes:
- WireData
- connectorId: AzureMonitor(IIS)
dataTypes:
- W3CIISLog
- connectorId: AzureActivity
dataTypes:
- AzureActivity
- connectorId: AWS
dataTypes:
- AWSCloudTrail
- connectorId: MicrosoftThreatProtection
dataTypes:
- DeviceNetworkEvents
- connectorId: AzureFirewall
dataTypes:
- AzureDiagnostics
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1071
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), '.'))
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPEntity
version: 2.0.6
kind: Scheduled
Stages and Predicates
Stage 0: let
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}';
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;
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;
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;
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;
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);
Stage 1: source
let sysEvtIP
Stage 2: source
let ipsort
Stage 3: source
let ipMatch
Stage 4: union
union of 12 branches
Stage 5: source
CommonSecurityLog
Stage 6: where
where (DestinationIP =~ "ipMatch" or Message contains "ipMatch" or SourceIP =~ "ipMatch")
Stage 7: project
project DestinationIP, Message, RequestURL, SourceIP, SourceUserID, TimeGenerated, Type
Stage 8: extend (3 consecutive steps)
extend IPEntity, IPMatch, MessageIP, timestamp
Stage 9: source
OfficeActivity
Stage 10: where
where ClientIP =~ "ipMatch"
Stage 11: project
project ClientIP, Operation, RecordType, TimeGenerated, Type, UserAgent, UserId
Stage 12: extend
extend Account, SourceIPAddress
Stage 13: extend
extend AccountEntity, IPEntity, timestamp
Stage 14: source
DnsEvents
Stage 15: where
where IPAddresses contains "ipMatch"
Stage 16: project
project ClientIP, Computer, IPAddresses, Name, TimeGenerated, Type
Stage 17: extend
extend DestinationIPAddress, Host
Stage 18: extend
extend HostEntity, IPEntity, timestamp
Stage 19: source
VMConnection
Stage 20: where
where (DestinationIp =~ "ipMatch" or SourceIp =~ "ipMatch")
Stage 21: project
project Computer, DestinationIp, SourceIp, TimeGenerated, Type
Stage 22: extend
extend IPMatch
IPMatch =if
SourceIp in ("ipMatch")"SourceIP"elif
DestinationIp in ("ipMatch")"DestinationIP"else
"None"Stage 23: extend
extend Host, IPEntity, timestamp
IPEntity =if
IPMatch == "SourceIP"SourceIpelif
IPMatch == "DestinationIP"DestinationIpelse
"None"Stage 24: source
Event
Stage 25: where
where Source =~ "Microsoft-Windows-Sysmon"
Stage 26: where
where EventID == 3
Stage 27: where
where EventData contains "ipMatch"
Stage 28: project
project Computer, EventData, TimeGenerated, Type, UserName
Stage 29: extend (3 consecutive steps)
extend DestinationIP, EvData, EventDetail, SourceIP
Stage 30: where
where (DestinationIP =~ "ipMatch" or SourceIP =~ "ipMatch")
Stage 31: extend
extend IPMatch
IPMatch =if
SourceIP in ("ipMatch")"SourceIP"elif
DestinationIP in ("ipMatch")"DestinationIP"else
"None"Stage 32: extend
extend AccountEntity, HostEntity, IPEntity, timestamp
IPEntity =if
IPMatch == "SourceIP"SourceIPelif
IPMatch == "DestinationIP"DestinationIPelse
"None"Stage 33: source
SigninLogs
Stage 34: where
where IPAddress =~ "ipMatch"
Stage 35: project
project IPAddress, TimeGenerated, Type, UserPrincipalName
Stage 36: extend
extend AccountEntity, IPEntity, timestamp
Stage 37: source
AADNonInteractiveUserSignInLogs
Stage 38: where
where IPAddress =~ "ipMatch"
Stage 39: project
project IPAddress, TimeGenerated, Type, UserPrincipalName
Stage 40: extend
extend AccountEntity, IPEntity, timestamp
Stage 41: source
W3CIISLog
Stage 42: where
where cIP =~ "ipMatch"
Stage 43: project
project Computer, TimeGenerated, Type, cIP, csUserName
Stage 44: extend
extend AccountEntity, HostEntity, IPEntity, timestamp
Stage 45: source
AzureActivity
Stage 46: where
where CallerIpAddress =~ "ipMatch"
Stage 47: project
project Caller, CallerIpAddress, TimeGenerated, Type
Stage 48: extend
extend AccountEntity, IPEntity, timestamp
Stage 49: source
AWSCloudTrail
Stage 50: where
where SourceIpAddress =~ "ipMatch"
Stage 51: project
project SourceIpAddress, TimeGenerated, Type, UserIdentityUserName
Stage 52: extend
extend AccountEntity, IPEntity, timestamp
Stage 53: source
DeviceNetworkEvents
Stage 54: where
where RemoteIP =~ "ipMatch"
Stage 55: where
where ActionType =~ "InboundConnectionAccepted"
Stage 56: project
project DeviceName, RemoteIP, TimeGenerated, Type
Stage 57: extend
extend HostEntity, IPEntity, timestamp
Stage 58: source
AzureDiagnostics
Stage 59: where
where ResourceType =~ "AZUREFIREWALLS"
Stage 60: where
where Category in~ ("AzureFirewallApplicationRule", "AzureFirewallNetworkRule")
Stage 61: where
where msg_s contains "ipMatch"
Stage 62: project
project TimeGenerated, Type, msg_s
Stage 63: parse
parse
Stage 64: where
where DestinationIP contains "ipMatch"
Stage 65: extend (3 consecutive steps)
extend DnsDomain, HostName, IPEntity, Name, UPNSuffix, timestamp
Indicators
These rows show field, operator, and value matches.
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
TimeGenerated | project |
Type | project |
msg_s | project |
IPEntity | extend |
timestamp | extend |
Name | extend |
UPNSuffix | extend |
DnsDomain | extend |
HostName | extend |