Detection rules › Sublime MQL
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.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Impersonation: Brand, Social engineering |
Event coverage
Rule body MQL
type.inbound
and (
(
strings.icontains(body.current_thread.text, 'Microsoft Teams')
and strings.icontains(body.current_thread.text, 'join the meeting')
and strings.contains(body.current_thread.text, 'Meeting ID:')
and strings.contains(body.current_thread.text, 'Passcode:')
)
or (
strings.icontains(body.current_thread.text, "teams")
// strings that give us confidence it's teams
and 2 of (
strings.icontains(body.current_thread.text, "internal"),
strings.icontains(body.current_thread.text, "message"),
strings.icontains(body.current_thread.text, "meeting"),
strings.icontains(body.current_thread.text, "Download Teams")
)
)
// either the subject or sender.display name containt Microsoft Teams and Meeting
or (
any([subject.base, sender.display_name],
strings.icontains(., 'Microsoft Teams')
and strings.icontains(., 'meeting')
)
)
)
// not a reply
and length(headers.references) == 0
and headers.in_reply_to is null
// few links
and length(distinct(body.links, .href_url.url)) < 10
// short body
and length(body.current_thread.text) < 600
// no unsubscribe links
// common in newsletters which link to a webinar style event
and not any(body.links, strings.icontains(.display_text, "unsub"))
// one of the links contains is a CTA that doesn't link to MS
and any(body.current_thread.links,
(
.display_text =~ "join the meeting"
or strings.icontains(.display_text, "join the meeting")
or strings.icontains(.display_text, "play recording")
)
and .href_url.domain.root_domain not in (
"microsoft.com",
"microsoft.us",
"microsoft.cn",
"live.com"
)
and not (
.href_url.domain.root_domain == "mimecastprotect.com"
and strings.parse_domain(.href_url.query_params_decoded["domain"][0]).root_domain in (
"microsoft.com",
"microsoft.us",
"microsoft.cn",
"live.com"
)
)
// rewriters often abstract the link
and .href_url.domain.root_domain not in $bulk_mailer_url_root_domains
)
// missing the dial by phone element
and not strings.icontains(body.current_thread.text, 'Dial in by phone')
// any of these suspicious elements from the body
and (
// malicious samples leveraged recipient domain branding here
not strings.icontains(body.current_thread.text, 'Microsoft Teams Need help?')
// malicious samples contained unique html elements not present in legit ones
or strings.icontains(body.html.raw, '<div class="meeting-title">')
or strings.icontains(body.html.raw, '<div class="meeting-time">')
or strings.icontains(body.html.raw, '<div class="meeting-location">')
or strings.icontains(body.html.raw, '<span class="conflict-badge">')
or strings.icontains(body.html.raw, 'class="join-button"')
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
(
sender.email.domain.root_domain in $high_trust_sender_root_domains
and not headers.auth_summary.dmarc.pass
)
or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
Detection logic
Scope: inbound message.
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.
- inbound message
any of:
body.current_thread.text contains any of 4 patterns
Microsoft Teamsjoin the meetingMeeting ID:Passcode:
all of:
- body.current_thread.text contains 'teams'
at least 2 of 4: body.current_thread.text contains any of 4 patterns
internalmessagemeetingDownload Teams
any of
[subject.base, sender.display_name]where all hold:- . contains 'Microsoft Teams'
- . contains 'meeting'
- length(headers.references) is 0
- headers.in_reply_to is missing
- length(distinct(body.links, .href_url.url)) < 10
- length(body.current_thread.text) < 600
not:
any of
body.linkswhere:- .display_text contains 'unsub'
any of
body.current_thread.linkswhere all hold:any of:
- .display_text is 'join the meeting'
- .display_text contains 'join the meeting'
- .display_text contains 'play recording'
- .href_url.domain.root_domain not in ('microsoft.com', 'microsoft.us', 'microsoft.cn', 'live.com')
not:
all of:
- .href_url.domain.root_domain is 'mimecastprotect.com'
- strings.parse_domain(.href_url.query_params_decoded['domain'][0]).root_domain in ('microsoft.com', 'microsoft.us', 'microsoft.cn', 'live.com')
- .href_url.domain.root_domain not in $bulk_mailer_url_root_domains
not:
- body.current_thread.text contains 'Dial in by phone'
any of:
not:
- body.current_thread.text contains 'Microsoft Teams Need help?'
- body.html.raw contains '<div class="meeting-title">'
- body.html.raw contains '<div class="meeting-time">'
- body.html.raw contains '<div class="meeting-location">'
- body.html.raw contains '<span class="conflict-badge">'
- body.html.raw contains 'class="join-button"'
any of:
all of:
- sender.email.domain.root_domain in $high_trust_sender_root_domains
not:
- headers.auth_summary.dmarc.pass
- sender.email.domain.root_domain not in $high_trust_sender_root_domains
Inspects: body.current_thread.links, body.current_thread.links[].display_text, body.current_thread.links[].href_url.domain.root_domain, body.current_thread.links[].href_url.query_params_decoded['domain'][0], body.current_thread.text, body.html.raw, body.links, body.links[].display_text, body.links[].href_url.url, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, sender.display_name, sender.email.domain.root_domain, subject.base, type.inbound. Sensors: strings.contains, strings.icontains, strings.parse_domain. Reference lists: $bulk_mailer_url_root_domains, $high_trust_sender_root_domains.
Indicators matched (24)
| Field | Match | Value |
|---|---|---|
strings.icontains | substring | Microsoft Teams |
strings.icontains | substring | join the meeting |
strings.contains | substring | Meeting ID: |
strings.contains | substring | Passcode: |
strings.icontains | substring | teams |
strings.icontains | substring | internal |
strings.icontains | substring | message |
strings.icontains | substring | meeting |
strings.icontains | substring | Download Teams |
strings.icontains | substring | unsub |
body.current_thread.links[].display_text | equals | join the meeting |
strings.icontains | substring | play recording |
12 more
body.current_thread.links[].href_url.domain.root_domain | member | microsoft.com |
body.current_thread.links[].href_url.domain.root_domain | member | microsoft.us |
body.current_thread.links[].href_url.domain.root_domain | member | microsoft.cn |
body.current_thread.links[].href_url.domain.root_domain | member | live.com |
body.current_thread.links[].href_url.domain.root_domain | equals | mimecastprotect.com |
strings.icontains | substring | Dial in by phone |
strings.icontains | substring | Microsoft Teams Need help? |
strings.icontains | substring | <div class="meeting-title"> |
strings.icontains | substring | <div class="meeting-time"> |
strings.icontains | substring | <div class="meeting-location"> |
strings.icontains | substring | <span class="conflict-badge"> |
strings.icontains | substring | class="join-button" |