Last active
December 13, 2021 14:15
-
-
Save TheCloudScout/9919554171f8f1498ce7f165882cc624 to your computer and use it in GitHub Desktop.
Azure Firewall | Check log4j IoCs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let timeWindow = datetime("2021-12-09"); | |
let intel = ((externaldata (URL:string,values: dynamic) [@"https://gist.githubusercontent.com/superducktoes/9b742f7b44c71b4a0d19790228ce85d8/raw/f1751cc072bd33256c0005021f33348c22aa76fc/Callback%2520Domains%2520log4j"])); | |
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 domains = intel | extend domains=extract(@"([0-9a-z]+\.[0-9a-z]+\.[a-z]+)",0,URL)| distinct domains| where domains != "" | project domains; | |
let ips = intel | extend ips=extract(@"([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})",0,URL) | distinct ips | where ips != "" | project ips; | |
let ports = intel | extend ports=extract(@":([0-9]{2,5})\/",1,URL) | distinct ports | where ports != "" | project ports; | |
// to parse Azure Firewall logs with "AzureFirewallApplicationRule" category, we need several different parsing methods based on the type of entries | |
let applicationRuleAllowsHttp = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallApplicationRule" | |
| parse msg_s with * " request from " ip_source ":" port_source " to " ip_destination ":" port_destination ". Url: " url ". Action: " action ". Policy: " policy ". Rule Collection Group: " rulecollectiongroup "Rule Collection: " rulecollection ". Rule: " rule | |
| where action == "Allow"; | |
let applicationRuleAllowsHttps = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallApplicationRule" | |
| parse msg_s with * " request from " ip_source ":" port_source " to " ip_destination ":" port_destination ". Action: " action ". Policy: " policy ". Rule Collection Group: " rulecollectiongroup "Rule Collection: " rulecollection ". Rule: " rule | |
| where action == "Allow" and port_destination !hasprefix "80" and rule !has "Web Category"; | |
let applicationRuleAllowsHttpsWebCategory = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallApplicationRule" | |
| parse msg_s with * " request from " ip_source ":" port_source " to " ip_destination ":" port_destination ". Action: " action ". Policy: " policy ". Rule Collection Group: " rulecollectiongroup "Rule Collection: " rulecollection ". Rule: " rule ". Web Category: " webcategory | |
| where action == "Allow"; | |
let applicationRuleDeniesHttp = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallApplicationRule" | |
| parse msg_s with * " request from " ip_source ":" port_source " to " ip_destination ":" port_destination ". Url: " url ". Action: " action ". " rule ". " * | |
| where action == "Deny" and port_destination == 80; | |
let applicationRuleDeniesHttps = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallApplicationRule" | |
| parse msg_s with * " request from " ip_source ":" port_source " to " ip_destination ":" port_destination ". Action: " action ". " rule ". " * | |
| where action == "Deny" and port_destination !hasprefix "80"; | |
let applicationRuleDenies = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallApplicationRule" | |
| parse msg_s with * " request from " ip_source ":" port_source ". Action: " action ". Reason: " rule "." * | |
| where isnotempty(ip_source); | |
let azureFirewallApplicationRules = applicationRuleAllowsHttp | |
| union applicationRuleAllowsHttps, applicationRuleAllowsHttpsWebCategory, applicationRuleDeniesHttp, applicationRuleDeniesHttps, applicationRuleDenies | |
| project-away msg_s; | |
// Only TCP traffic is needed so we only parse those | |
let azureFirewallNetworkRules = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallNetworkRule" | |
| extend protocol = case( msg_s hasprefix 'TCP', 'TCP', | |
msg_s hasprefix 'UDP', 'UDP', | |
msg_s hasprefix 'ICMP', 'ICMP', | |
'Unknown') // else | |
| where protocol == "TCP" | |
| parse msg_s with * " request from " ip_source ":" port_source " to " ip_destination ":" port_destination ". Action: " action "." * | |
| project-away msg_s; | |
// Azure Firewall DNS proxy events are quite straightforward | |
let azureFirewallDnsProxy = AzureDiagnostics | |
| where ResourceType == "AZUREFIREWALLS" | |
| where Category == "AzureFirewallDnsProxy" | |
| parse msg_s with * "DNS Request: " clientip ":" clientport " - " queryid " " recordtype " " requestclass " " lookupname ". " protocol " " requestsizebytes " " dnssecflag " "buffersize " " response " " responseflags " "responsesize " " responseduration | |
| project-away msg_s; | |
// Query start | |
azureFirewallDnsProxy | |
| where TimeGenerated > timeWindow | |
| where lookupname has_any (domains) | |
// combine alle three log categories in a single view | |
| union (azureFirewallNetworkRules | |
| where TimeGenerated > timeWindow | |
| where ip_destination has_any (ips) or | |
ip_destination has_any (IPList)), | |
(azureFirewallApplicationRules | |
| where TimeGenerated > timeWindow | |
| where ip_destination has_any (ips) or | |
ip_destination has_any (IPList) or | |
ip_destination has_any (domains)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment