top of page

Unmasking Phishing Hidden in Google Links With KQL

  • Writer: Damien van der Linden
    Damien van der Linden
  • Dec 5, 2024
  • 4 min read

Updated: Dec 9, 2024

Phishing campaigns are evolving, with attackers constantly finding new ways to exploit trusted platforms. One such exploit involves Google's open redirect feature—a vulnerability long abused by scammers to mask malicious links under the guise of Google’s trusted domain.


Open redirects occur when a legitimate service allows attackers to insert their own malicious URL as part of a legitimate link, redirecting unsuspecting users to harmful sites. For years, Google's search redirect mechanism has been an attractive tool for attackers, as users inherently trust links beginning with "google.com." This trust makes phishing campaigns significantly more effective, bypassing most security measures.


Sophos highlighted this problem in a 2020 article, detailing how attackers manipulate Google's redirect feature to launch convincing phishing campaigns. Instead of directly linking to a malicious site, scammers embed their malicious URL within a Google link, which then redirects the victim. To the casual observer, the link appears legitimate, originating from a domain they trust. Sad but true, 4 years later this is still a problem and many phishing pages are accessed because of this.


This Sentinel query examines email data to identify suspicious URLs and determine whether any potentially harmful emails slipped through into users’ inboxes or junk folders, making them more likely to be clicked on by unsuspecting users.


The Query Breakdown


Here’s the query for reference:

EmailUrlInfo 
| where TimeGenerated >= ago(14d) 
| where Url has "google." and Url has "/url?" and UrlDomain has "google" 
| extend Domain = extract("google\\.([^/]+)", 1, Url) 
| where Domain !in ("com") 
| summarize Urls = make_list(Url) by NetworkMessageId 
| join kind=inner (EmailEvents) on NetworkMessageId 
| where DeliveryLocation has "Inbox" or DeliveryLocation has "Junk" and LatestDeliveryLocation != "Quarantine" 
| project NetworkMessageId, TimeGenerated, Urls, SenderFromAddress, RecipientEmailAddress, Subject, DeliveryLocation, DeliveryAction, LatestDeliveryLocation

Let’s break it down step by step.


1. Filter for Recent Data

| where TimeGenerated >= ago(14d)

The query begins by narrowing down the data to URLs from the last 14 days. Adjust the time range as needed depending on your investigation window.


2. Look for Google Redirect URLs

| where Url has "google." and Url has "/url?" and UrlDomain has "google"

This step targets URLs that include Google’s redirect pattern (e.g., https://www.google.com/url?) by ensuring the URL contains:

  • "google.": The prefix.

  • "/url?": The marker of a redirect.

  • UrlDomain has "google": This ensures the domain is Google-related.


We are not including a TLD (like .com) yet, in the next part you'll see why!


3. Extract the Redirect Domain

| extend Domain = extract("google\\.([^/]+)", 1, Url) 
| where Domain !in ("com")

The extract function pulls out the top level domain that follows https://www.google. in the URL. For example:


The second line excludes redirects to .com, as these are usually legitimate. This is to filter out false positives, if your company is from The Netherlands, exclude .nl etc. For full investigation, comment these out and look through all domains, but beware of a high chance for a lot of false positives this way. You can modify this exclusion list to fit your organization’s needs.


4. Group URLs by Email Message

| summarize Urls = make_list(Url) by NetworkMessageId

This step groups all the URLs found within the same email (NetworkMessageId) into a list, allowing you to see the full picture of links in one record, instead of multiple. This way you keep your results clean.


5. Match Emails with Event Data

| join kind=inner (EmailEvents) on NetworkMessageId

The query joins the URL data with email event data using the unique NetworkMessageId. This brings in additional context, such as the sender, recipient, and delivery location.


6. Focus on Delivered Emails

| where DeliveryLocation has "Inbox" or DeliveryLocation has "Junk" and LatestDeliveryLocation != "Quarantine"

Now we focus on emails that ended up in the inbox or junk folder, ensuring quarantined messages are excluded. These are the emails users are most likely to interact with, so they require extra scrutiny.


7. Output Relevant Information

| project NetworkMessageId, TimeGenerated, Urls, SenderFromAddress, RecipientEmailAddress, Subject, DeliveryLocation, DeliveryAction, LatestDeliveryLocation

Finally, the query outputs useful details for analysis, such as:

  • Sender and recipient information

  • Subject line

  • Delivery location: Did it land in the inbox, junk folder, or elsewhere?

  • URLs: The extracted redirect URLs for further investigation.


Why This Matters

Phishing attacks often leverage Google’s trusted domain to bypass email security filters. By analyzing open redirects, this query helps security teams identify potentially malicious emails and URLs that could otherwise go unnoticed. Sadly, Google has their own stance on this issue, so we have to hunt for it ourselves.


Next Steps

If you’re running this query in a SOC environment, consider:


  1. Automating alerts for suspicious domains (after tuning to your needs, to filter out false-positives).

  2. Cross-referencing domains with threat intelligence feeds.

  3. Educating users about the dangers of clicking on unexpected Google redirect links.


By proactively hunting for these threats, you can better protect your organization from phishing attacks that abuse legitimate services like Google. These usually fly under the radar and bypass e-mail security. I often use this query myself and it allows me to take away many phishing e-mails from inboxes, before EDR does it.


If you want a more in-depth look into how attackers abuse this 'feature', make sure to read the Sophos article here!


Got questions or suggestions? Drop a comment or reach out—I’d love to hear how this query works for you!

1 comentario


Damien van der Linden
Damien van der Linden
09 dic 2024

EDIT: A reader pointed me towards something where you could miss hits. Which I have changed. The part of the query | where Url has "https://www.google." and Url has "/url?" and UrlDomain has "google"

| extend Domain = extract("https://www\\.google\\.([^/]+)", 1, Url) Was changed to | where Url has "google." and Url has "/url?" and UrlDomain has "google"

| extend Domain = extract("google\\.([^/]+)", 1, Url)


This way, both www.google and https://google are caught! Thanks for the feedback Anonymous!



Me gusta
2025-2026 LindenSec | ©
bottom of page