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 any(recipients.to, .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|browser)"
 62            )
 63    )
 64    
 65    // not a reply
 66    and (
 67      length(headers.references) == 0
 68      or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To")))
 69    )
 70    
 71    // Planner logo
 72    // LogoDetect coming soon
 73    and (
 74      all(attachments,
 75          .file_type in $file_types_images
 76          and any(file.explode(.),
 77                  // small, relatively square image
 78                  (
 79                    .scan.exiftool.image_height / .scan.exiftool.image_width
 80                  ) > 0.9
 81                  and (.scan.exiftool.image_height + .scan.exiftool.image_width) < 500
 82          )
 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, .href_url.domain.root_domain != sender.email.domain.root_domain)
107      )
108    )
109    and sender.email.domain.root_domain not in (
110      "bing.com",
111      "microsoft.com",
112      "microsoftonline.com",
113      "microsoftproject.com",
114      "microsoftstoreemail.com",
115      "microsoftsupport.com",
116      "microsoft365.com",
117      "office.com",
118      "office365.com",
119      "onedrive.com",
120      "sharepointonline.com",
121      "yammer.com",
122    )
123    
124    // negate highly trusted sender domains unless they fail DMARC authentication
125    and (
126      (
127        sender.email.domain.root_domain in $high_trust_sender_root_domains
128        and not headers.auth_summary.dmarc.pass
129      )
130      or sender.email.domain.root_domain not in $high_trust_sender_root_domains
131    )
132    and (
133      not profile.by_sender().solicited
134      or (
135        profile.by_sender().any_messages_malicious_or_spam
136        and not profile.by_sender().any_messages_benign
137      )
138    )
139    and not profile.by_sender().any_messages_benign
140    
141    // exclude marketing jargon from ms partners
142    and not regex.icontains(body.current_thread.text,
143                            '(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)'
144    )    
145
146attack_types:
147  - "Credential Phishing"
148tactics_and_techniques:
149  - "Evasion"
150  - "Image as content"
151  - "Impersonation: Brand"
152  - "Social engineering"
153detection_methods:
154  - "Content analysis"
155  - "Header analysis"
156  - "Natural Language Understanding"
157  - "Sender analysis"
158  - "URL analysis"
159id: "ea363c08-479f-5437-9b5d-3d9e07098200"
to-top