Users may have clicked on phishing links, leading to potential compromise through network traffic exfiltration, as adversaries often use this method to establish initial access and deploy further malicious payloads. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify and mitigate early-stage phishing attacks before they lead to deeper network infiltration.
KQL Query
//Finding MDO Security alerts and extracting the Entities user, Domain, Ip, and URL.
let Alert_List= dynamic([
"Phishing link click observed in Network Traffic",
"Phish delivered due to an IP allow policy",
"A potentially malicious URL click was detected",
"High Risk Sign-in Observed in Network Traffic",
"A user clicked through to a potentially malicious URL",
"Suspicious network connection to AitM phishing site",
"Messages containing malicious entity not removed after delivery",
"Email messages containing malicious URL removed after delivery",
"Email reported by user as malware or phish",
"Phish delivered due to an ETR override",
"Phish not zapped because ZAP is disabled"]);
SecurityAlert
|where ProviderName in~ ("Office 365 Advanced Threat Protection", "OATP")
| where AlertName in~ (Alert_List)
//extracting Alert Entities
| extend Entities = parse_json(Entities)
| mv-apply Entity = Entities on
(
where Entity.Type == 'account'
| extend EntityUPN = iff(isempty(Entity.UserPrincipalName), tostring(strcat(Entity.Name, "@", tostring (Entity.UPNSuffix))), tostring(Entity.UserPrincipalName))
)
| mv-apply Entity = Entities on
(
where Entity.Type == 'url'
| extend EntityUrl = tostring(Entity.Url)
)
| summarize AccountUpn=tolower(tostring(take_any(EntityUPN))),Url=tostring(tolower(take_any(EntityUrl))),AlertTime= min(TimeGenerated)by SystemAlertId, ProductName
// filtering 3pnetwork devices
| join kind= inner (CommonSecurityLog
| where DeviceVendor has_any ("Palo Alto Networks", "Fortinet", "Check Point", "Zscaler")
| where DeviceAction != "Block"
| where DeviceProduct startswith "FortiGate" or DeviceProduct startswith "PAN" or DeviceProduct startswith "VPN" or DeviceProduct startswith "FireWall" or DeviceProduct startswith "NSSWeblog" or DeviceProduct startswith "URL"
| where isnotempty(RequestURL)
| where isnotempty(SourceUserName)
| extend SourceUserName = tolower(SourceUserName)
| project
3plogTime=TimeGenerated,
DeviceVendor,
DeviceProduct,
Activity,
DestinationHostName,
DestinationIP,
RequestURL=tostring(tolower(RequestURL)),
MaliciousIP,
Name = tostring(split(SourceUserName,"@")[0]),
UPNSuffix =tostring(split(SourceUserName,"@")[1]),
SourceUserName,
IndicatorThreatType,
ThreatSeverity,AdditionalExtensions,
ThreatConfidence)on $left.Url == $right.RequestURL and $left.AccountUpn == $right.SourceUserName
// Applied the condition where alert trigger 1st and then the 3p Network activity execution
| where AlertTime between ((3plogTime - 1h) .. (3plogTime + 1h))
id: 2fed0668-6d43-4c78-87e6-510f96f12145
name: Phishing link click observed in Network Traffic
description: |
'The purpose of this content is to identify successful phishing links accessed by users. Once a user clicks on a phishing link, we observe successful network activity originating from non-Microsoft network devices. These devices may include Palo Alto Networks, Fortinet, Check Point, and Zscaler devices.'
severity: Medium
requiredDataConnectors:
- connectorId: OfficeATP
dataTypes:
- SecurityAlert
- connectorId: PaloAltoNetworks
dataTypes:
- CommonSecurityLog (PaloAlto)
- connectorId: Fortinet
dataTypes:
- CommonSecurityLog (Fortinet)
- connectorId: CheckPoint
dataTypes:
- CommonSecurityLog (CheckPoint)
- connectorId: Zscaler
dataTypes:
- CommonSecurityLog (Zscaler)
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1566
query: |
//Finding MDO Security alerts and extracting the Entities user, Domain, Ip, and URL.
let Alert_List= dynamic([
"Phishing link click observed in Network Traffic",
"Phish delivered due to an IP allow policy",
"A potentially malicious URL click was detected",
"High Risk Sign-in Observed in Network Traffic",
"A user clicked through to a potentially malicious URL",
"Suspicious network connection to AitM phishing site",
"Messages containing malicious entity not removed after delivery",
"Email messages containing malicious URL removed after delivery",
"Email reported by user as malware or phish",
"Phish delivered due to an ETR override",
"Phish not zapped because ZAP is disabled"]);
SecurityAlert
|where ProviderName in~ ("Office 365 Advanced Threat Protection", "OATP")
| where AlertName in~ (Alert_List)
//extracting Alert Entities
| extend Entities = parse_json(Entities)
| mv-apply Entity = Entities on
(
where Entity.Type == 'account'
| extend EntityUPN = iff(isempty(Entity.UserPrincipalName), tostring(strcat(Entity.Name, "@", tostring (Entity.UPNSuffix))), tostring(Entity.UserPrincipalName))
)
| mv-apply Entity = Entities on
(
where Entity.Type == 'url'
| extend EntityUrl = tostring(Entity.Url)
)
| summarize AccountUpn=tolower(tostring(take_any(EntityUPN))),Url=tostring(tolower(take_any(EntityUrl))),AlertTime= min(TimeGenerated)by SystemAlertId, ProductName
// filtering 3pnetwork devices
| join kind= inner (CommonSecurityLog
| where DeviceVendor has_any ("Palo Alto Networks", "Fortinet", "Check Point", "Zscaler")
| where DeviceAction != "Block"
| where DeviceProduct startswith "FortiGate" or DeviceProduct startswith "PAN" or DeviceProduct startswith "VPN" or DeviceProduct startswith "FireWall" or DeviceProduct startswith "NSSWeblog" or DeviceProduct startswith "URL"
| where isnotempty(RequestURL)
| where isnotempty(SourceUserName)
| extend
| Sentinel Table | Notes |
|---|---|
CommonSecurityLog | Ensure this data connector is enabled |
SecurityAlert | Ensure this data connector is enabled |
Scenario: A system administrator clicks on a legitimate support link from Microsoft’s official portal during a scheduled maintenance task.
Filter/Exclusion: Exclude traffic originating from known admin workstations or IP ranges associated with internal IT infrastructure. Example: src_ip in (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) or user_agent contains "Microsoft Support".
Scenario: A user accesses a legitimate cloud storage link (e.g., OneDrive or Google Drive) as part of a file transfer process.
Filter/Exclusion: Exclude traffic to known cloud storage endpoints (e.g., dest_url contains "onedrive.com" or "drive.google.com").
Scenario: A scheduled job runs a script that downloads a dependency from a public repository (e.g., GitHub or npm).
Filter/Exclusion: Exclude traffic to known package managers or public code repositories (e.g., dest_url contains "github.com" or "npmjs.com").
Scenario: A user clicks on a phishing link that redirects to a legitimate internal portal (e.g., internal login page) as part of a security test.
Filter/Exclusion: Exclude traffic to internal domains (e.g., dest_dns contains "internal.company.com" or dest_ip in (10.10.0.0/16)).
Scenario: A developer clicks on a link in an email from a trusted vendor (e.g., AWS or Salesforce) to access a documentation page.
Filter/Exclusion: Exclude traffic to known vendor documentation sites (e.g., dest_url contains "aws.amazon.com" or "salesforce.com/docs").