Skip to content

Commit 6eb5360

Browse files
author
Sergio Garcia Albea
committed
New KQL Query URL Redirections Hunting Query
1 parent 56e5417 commit 6eb5360

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
id: 7f2c9a4e-8d61-4b6e-9e33-4d2a7c5e91af
3+
name: Hunt for email URL Redirections
4+
description: |
5+
This KQL Query helps to understand all the URL Redirections from URLs received by Email.
6+
description-detailed: |
7+
This KQL Query helps to understand all the URL Redirections from URLs received by Email using the UrlChainId identifier on KQL that groups together all URLs that belong to the same “click/redirect chain”. When an message contains a URL, that URL may redirect through several intermediate URLs (trackers, shorteners, phishing, etc.) before land on the final site. KQL builds a URL chain from the original URL in the email through each redirect hop. All URLs that are part of a single chain share the same UrlChainId and for each hop. On the other hand, UrlChainPosition register the position of every URL, the original one = value 0 and the other redirections tagged with next numbers(1, 2, etc. ) The following query includes different options to classify the insights into four categories:
8+
- Tracking Domains
9+
- Redirecting to Different Countries
10+
- Redirecting to Different Domains
11+
- Number of Redirections
12+
requiredDataConnectors:
13+
- connectorId: MicrosoftThreatProtection
14+
dataTypes:
15+
- EmailEvents
16+
tactics:
17+
- PHishing
18+
relevantTechniques:
19+
- T1566
20+
query: |
21+
let TrackingDomains = dynamic(["click/","bit.ly","bitly.com","tinyurl.com","goo.gl","t.co","ow.ly","is.gd","buff.ly","lnk.click","lnk.to","mjt.lu","mailjet.com","list-manage.com","mailchimp.com","mcsv.net","mailgun.org","sendgrid.net","sendgrid.com","createsend.com","createsend1.com","rs6.net","campaignsapp.com","mlsend.com","sendinblue.com","sibautomation.com","mailerlite.com","hs-sites.com","hscta.net","hubspot.com","hubspotlinks.com","mkto.com","mktg.com","pardot.com","eloqua.com","eloquaservice.com","activehosted.com","acems.ac","getvero.com","iterable.com","inflection.io","bnc.lt","app.link","substack.com","substackcdn.com","getrevue.co","shop.app","shopifyemail.com","klaviyo-mail.com","klaviyo.com","knowbe4.com","kb4.io","phishme.com","cofense.com"]);
22+
EmailEvents
23+
| where Timestamp > ago(1d)
24+
| extend IPSender = iff(isnotempty(SenderIPv4),SenderIPv4,SenderIPv6)
25+
| extend GeoIPData = tostring(geo_info_from_ip_address(IPSender).country)
26+
| join kind=inner ( EmailUrlInfo | where isnotempty(UrlChainId)) on NetworkMessageId
27+
// Pivot URLs by position
28+
| summarize
29+
UrlPos_0 = anyif(Url, UrlChainPosition == 0),UrlPos_1= anyif(Url, UrlChainPosition == 1),UrlPos_2= anyif(Url, UrlChainPosition == 2),UrlPos_3 = anyif(Url, UrlChainPosition == 3),
30+
IP_Url_0 = anyif(IPSender, UrlChainPosition == 0),IP_Url_1= anyif(IPSender, UrlChainPosition == 1),IP_Url_2= anyif(IPSender, UrlChainPosition == 2),IP_Url_3= anyif(IPSender, UrlChainPosition == 3),
31+
C_Url_0 = anyif(GeoIPData, UrlChainPosition == 0),C_Url_1= anyif(GeoIPData, UrlChainPosition == 1),C_Url_2= anyif(GeoIPData, UrlChainPosition == 2),C_Url_3= anyif(GeoIPData, UrlChainPosition == 3),
32+
URL_Redirections = dcount(UrlChainPosition),Senders=dcount(SenderFromAddress),Recipients = dcount(RecipientEmailAddress),IP_Country= make_set(strcat(SenderIPv4, " ", GeoIPData)) by UrlChainId,ThreatTypes
33+
| where isnotempty(UrlPos_0)
34+
| extend Tracking_Marketing_URL0 = (iff(UrlPos_0 has_any (TrackingDomains),"Yes","Not")),Tracking_Marketing_URL1 =(iff(UrlPos_1 has_any (TrackingDomains),"Yes","Not")),Tracking_Marketing_URL2 = (iff(UrlPos_2 has_any (TrackingDomains),"Yes","Not")),Tracking_Marketing_URL3 = (iff(UrlPos_3 has_any (TrackingDomains),"Yes","Not"))
35+
| summarize by Senders,URL_Redirections,UrlPos_0,IP_Url_0,C_Url_0,Tracking_Marketing_URL0, UrlPos_1,IP_Url_1,C_Url_1,Tracking_Marketing_URL1, UrlPos_2,IP_Url_2,C_Url_2,Tracking_Marketing_URL2, UrlPos_3,IP_Url_3,C_Url_3,Tracking_Marketing_URL3,Recipients,tostring(IP_Country),UrlChainId,ThreatTypes
36+
| extend Domain_URL0 = tostring(parse_url(UrlPos_0).Host), Domain_URL1 = tostring(parse_url(UrlPos_1).Host), Domain_URL2 = tostring(parse_url(UrlPos_2).Host), Domain_URL3 = tostring(parse_url(UrlPos_3).Host)
37+
| extend Info="ℹ️",0_ = "0️⃣",1_ = "1️⃣",2_ = "2️⃣",3_ ="3️⃣" //Icons
38+
//Search for specific URL | extend URL = "office" | where UrlPos_0 contains URL or UrlPos_1 contains URL or UrlPos_2 contains URL or UrlPos_3 contains URL
39+
//Search for URL on distinct countries | where (C_Url_0 !has C_Url_1 or C_Url_0 !has C_Url_2 or C_Url_0 !has C_Url_3 or C_Url_1 !has C_Url_2 or C_Url_1 !has C_Url_3 or C_Url_2 !has C_Url_3)
40+
//Search for URL that contains specific countries | where (C_Url_0 !in ("Switzerland","Germany")) or (C_Url_1 in ("Russia","Singapore"))
41+
//Search for URL on distinct domains | where (Domain_URL0 !has Domain_URL1 or Domain_URL0 !has Domain_URL1 or Domain_URL0 !has Domain_URL3 or Domain_URL1 !has Domain_URL2 or Domain_URL1 !has Domain_URL3 or Domain_URL2 !has Domain_URL3)
42+
//Search for number of redirections | where URL_Redirections > 2
43+
| project Info,URL_Redirections,ThreatTypes,Senders, Recipients,0_,Domain_URL0,UrlPos_0,IP_Url_0,C_Url_0, Tracking_Marketing_URL0,1_,Domain_URL1,UrlPos_1,IP_Url_1,C_Url_1,Tracking_Marketing_URL1,2_,Domain_URL2,UrlPos_2,IP_Url_2,C_Url_2, Tracking_Marketing_URL2,3_,Domain_URL3,UrlPos_3,IP_Url_3,C_Url_3,Tracking_Marketing_URL3
44+
version: 1.0.0
45+
46+

0 commit comments

Comments
 (0)