Brand impersonation: Microsoft Teams invitation

Detects messages impersonating a Microsoft Teams invites by matching known invite text patterns while containing join links that do not resolve to Microsoft domains. Additional verification includes checking for absent phone dial-in options and missing standard Teams help text or HTML meeting components.

Sublime rule (View on GitHub)

  1name: "Brand impersonation: Microsoft Teams invitation"
  2description: "Detects messages impersonating a Microsoft Teams invites by matching known invite text patterns while containing join links that do not resolve to Microsoft domains. Additional verification includes checking for absent phone dial-in options and missing standard Teams help text or HTML meeting components."
  3type: "rule"
  4severity: "high"
  5source: |
  6  type.inbound
  7  and (
  8    (
  9      strings.icontains(body.current_thread.text, 'Microsoft Teams')
 10      and strings.icontains(body.current_thread.text, 'join the meeting')
 11      and strings.contains(body.current_thread.text, 'Meeting ID:')
 12      and strings.contains(body.current_thread.text, 'Passcode:')
 13    )
 14    or (
 15      strings.icontains(body.current_thread.text, "teams")
 16      // strings that give us confidence it's teams
 17      and 2 of (
 18        strings.icontains(body.current_thread.text, "internal"),
 19        strings.icontains(body.current_thread.text, "message"),
 20        strings.icontains(body.current_thread.text, "meeting"),
 21        strings.icontains(body.current_thread.text, "Download Teams")
 22      )
 23    )
 24    // either the subject or sender.display name containt Microsoft Teams and Meeting
 25    or (
 26      any([subject.base, sender.display_name],
 27          strings.icontains(., 'Microsoft Teams')
 28          and strings.icontains(., 'meeting')
 29      )
 30    )
 31  )
 32  // not a reply
 33  and length(headers.references) == 0
 34  and headers.in_reply_to is null
 35  // few links
 36  and length(distinct(body.links, .href_url.url)) < 10
 37  // short body
 38  and length(body.current_thread.text) < 600
 39  // no unsubscribe links
 40  // common in newsletters which link to a webinar style event
 41  and not any(body.links, strings.icontains(.display_text, "unsub"))
 42  
 43  // one of the links contains is a CTA that doesn't link to MS
 44  and any(body.current_thread.links,
 45          (
 46            .display_text =~ "join the meeting"
 47            or strings.icontains(.display_text, "join the meeting")
 48            or strings.icontains(.display_text, "play recording")
 49          )
 50          and .href_url.domain.root_domain not in (
 51            "microsoft.com",
 52            "microsoft.us",
 53            "microsoft.cn",
 54            "live.com"
 55          )
 56          and not (
 57            .href_url.domain.root_domain == "mimecastprotect.com"
 58            and strings.parse_domain(.href_url.query_params_decoded["domain"][0]).root_domain in (
 59              "microsoft.com",
 60              "microsoft.us",
 61              "microsoft.cn",
 62              "live.com"
 63            )
 64          )
 65          // rewriters often abstract the link
 66          and .href_url.domain.root_domain not in $bulk_mailer_url_root_domains
 67  )
 68  // missing the dial by phone element
 69  and not strings.icontains(body.current_thread.text, 'Dial in by phone')
 70  
 71  // any of these suspicious elements from the body
 72  and (
 73    // malicious samples leveraged recipient domain branding here
 74    not strings.icontains(body.current_thread.text, 'Microsoft Teams Need help?')
 75    // malicious samples contained unique html elements not present in legit ones
 76    or strings.icontains(body.html.raw, '<div class="meeting-title">')
 77    or strings.icontains(body.html.raw, '<div class="meeting-time">')
 78    or strings.icontains(body.html.raw, '<div class="meeting-location">')
 79    or strings.icontains(body.html.raw, '<span class="conflict-badge">')
 80    or strings.icontains(body.html.raw, 'class="join-button"')
 81  )
 82  
 83  // negate highly trusted sender domains unless they fail DMARC authentication
 84  and (
 85    (
 86      sender.email.domain.root_domain in $high_trust_sender_root_domains
 87      and not headers.auth_summary.dmarc.pass
 88    )
 89    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
 90  )  
 91attack_types:
 92  - "Credential Phishing"
 93tactics_and_techniques:
 94  - "Impersonation: Brand"
 95  - "Social engineering"
 96detection_methods:
 97  - "Content analysis"
 98  - "Header analysis"
 99  - "HTML analysis"
100  - "URL analysis"
101id: "46410ad8-3465-505f-a78e-f77704910a91"
to-top