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"