Brand impersonation: Microsoft Planner with suspicious link

Impersonation of Microsoft Planner, a component of the Microsoft 365 software suite.

Sublime rule (View on GitHub)

  1name: "Brand impersonation: Microsoft Planner with suspicious link"
  2description: "Impersonation of Microsoft Planner, a component of the Microsoft 365 software suite."
  3type: "rule"
  4severity: "medium"
  5source: |
  6   type.inbound
  7   // suspicious link
  8   and any(body.links,
  9           (
 10             .href_url.domain.root_domain not in $tranco_1m
 11             or .href_url.domain.domain in $free_file_hosts
 12             or .href_url.domain.root_domain in $free_file_hosts
 13             or .href_url.domain.root_domain in $free_subdomain_hosts
 14             or .href_url.domain.domain in $url_shorteners
 15             or .href_url.domain.domain in $social_landing_hosts
 16             or .href_url.domain.root_domain in $social_landing_hosts
 17             or 
 18   
 19             // mass mailer link, masks the actual URL
 20             .href_url.domain.root_domain in (
 21               "hubspotlinks.com",
 22               "mandrillapp.com",
 23               "sendgrid.net",
 24               "rs6.net"
 25             )
 26   
 27             // Google AMP redirect
 28             or (
 29               .href_url.domain.sld == "google"
 30               and strings.starts_with(.href_url.path, "/amp/")
 31             )
 32   
 33             // Recipient email address in link
 34             or any(body.links,
 35                    any(recipients.to,
 36                        strings.icontains(..href_url.url, .email.email)
 37                        and .email.domain.valid
 38                    )
 39             )
 40             or .href_url.domain.root_domain == "beehiiv.com"
 41           )
 42   
 43           // exclude sources of potential FPs
 44           and (
 45             .href_url.domain.root_domain not in (
 46               "svc.ms",
 47               "sharepoint.com",
 48               "1drv.ms",
 49               "microsoft.com",
 50               "aka.ms",
 51               "msftauthimages.net",
 52               "mimecastprotect.com",
 53               "office.com",
 54               "microsoftproject.com"
 55             )
 56             or any(body.links, .href_url.domain.domain in $free_file_hosts)
 57           )
 58           and .href_url.domain.root_domain not in $org_domains
 59           and .href_url.domain.valid
 60           and regex.icontains(.display_text,
 61                               "(?:go.?to|view|show|display|access|open.?in|review.?on) (teams?|planner|group|task|intranet|discussions?)"
 62           )
 63   )
 64   
 65   // not a reply
 66   and (length(headers.references) == 0 or headers.in_reply_to is null)
 67   
 68   // Planner logo
 69   // LogoDetect coming soon
 70   and (
 71     all(attachments,
 72         .file_type in $file_types_images
 73         and 
 74         // small, relatively square image
 75         //
 76         // This rule makes use of a beta feature and is subject to change without notice
 77         // using the beta feature in custom rules is not suggested until it has been formally released
 78         //
 79         (
 80           beta.parse_exif(.).image_height / beta.parse_exif(.).image_width
 81         ) > 0.9
 82         and (beta.parse_exif(.).image_height + beta.parse_exif(.).image_width) < 500
 83     )
 84   )
 85   
 86   // suspicious content
 87   and (
 88     2 of (
 89       strings.ilike(body.current_thread.text, "*assigned*new team*"),
 90       strings.ilike(body.current_thread.text, "*Microsoft Office 365*"),
 91       strings.ilike(body.current_thread.text, "*internal planner*"),
 92       strings.ilike(body.current_thread.text, "*internal task*"),
 93       any(recipients.to,
 94           strings.icontains(body.current_thread.text, .email.domain.sld)
 95       )
 96     )
 97     or (
 98       any(ml.nlu_classifier(body.current_thread.text).intents,
 99           .name == "cred_theft" and .confidence in~ ("medium", "high")
100       )
101     )
102     // multiple links, but all the same root domain
103     or (
104       length(distinct(body.links, .href_url.domain.root_domain)) == 1
105       and 2 < length(body.links) < 10
106       and all(body.links,
107               .href_url.domain.root_domain != sender.email.domain.root_domain
108       )
109     )
110   )
111   // skip senders 
112   and not (
113     headers.auth_summary.dmarc.pass
114     and sender.email.domain.root_domain in (
115       "bing.com",
116       "microsoft.com",
117       "microsoftonline.com",
118       "microsoftproject.com",
119       "microsoftstoreemail.com",
120       "microsoftsupport.com",
121       "microsoft365.com",
122       "office.com",
123       "office365.com",
124       "onedrive.com",
125       "sharepointonline.com",
126       "yammer.com",
127       "outlign.co"
128     )
129   )
130   
131   // negate highly trusted sender domains unless they fail DMARC authentication
132   and (
133     (
134       sender.email.domain.root_domain in $high_trust_sender_root_domains
135       and not headers.auth_summary.dmarc.pass
136     )
137     or sender.email.domain.root_domain not in $high_trust_sender_root_domains
138   )
139   and (
140     not profile.by_sender().solicited
141     or (
142       profile.by_sender().any_messages_malicious_or_spam
143       and not profile.by_sender().any_messages_benign
144     )
145   )
146   and not profile.by_sender().any_messages_benign
147   
148   // exclude marketing jargon from ms partners
149   and not regex.icontains(body.current_thread.text,
150                           '(schedul(e|ing)|set up).{0,20}(call|meeting|demo|zoom|conversation|time|tool|discussion)|book.{0,10}(meeting|demo|call|slot|time)|connect.{0,12}(with me|phone|email)|my.{0,10}(calendar|cal)|reserve.{0,10}s[pl]ot|break the ice|want to know more?|miss your chance|if you no longer wish|if you no longer want|if you wish to opt out|low-code (development|approach|solution|journey|platform)|invite.{0,30}(webinar|presentation)'
151   )   
152attack_types:
153  - "Credential Phishing"
154tactics_and_techniques:
155  - "Evasion"
156  - "Image as content"
157  - "Impersonation: Brand"
158  - "Social engineering"
159detection_methods:
160  - "Content analysis"
161  - "Header analysis"
162  - "Natural Language Understanding"
163  - "Sender analysis"
164  - "URL analysis"
165id: "ea363c08-479f-5437-9b5d-3d9e07098200"
to-top