Detection rules › Sublime MQL
Link: Multistage landing - Microsoft Forms abuse
The detection rule matches on message groups which make use of Microsoft Forms as a landing page. The landing page contains links which are newly registered, use free file or subdomain hosts, URL shorteners or when visited are phishing pages, lead to a captcha or redirect to a top website.
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
| Message attribute |
|---|
| body |
| body.links (collection) |
| sender.email |
| type |
Rule body MQL
type.inbound
and any(filter(body.links, .href_url.domain.domain == "forms.office.com"),
// avoid doing Link Analysis if the display-text has strong indications of phishing
(
// replace confusables - observed ITW
regex.icontains(strings.replace_confusables(.display_text),
'review|proposal|document|efax|restore|[o0]pen|secure|messaging|reset|account|verify|login|notification|alert|urgent|immediate|access|support|\bupdate\b|download|attachment|service|payment|remittance|invoice'
)
and not regex.icontains(strings.replace_confusables(.display_text),
'customer service'
)
// add confidence to these strings by using profile.by_sender()
and (
not profile.by_sender().solicited
and profile.by_sender().prevalence in ('new', 'outlier')
)
)
or
// look at the final_dom.raw
// if the page has been taken down, match
strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
'This form was blocked due to privacy or safety concerns.'
)
// this error has been shown before with the text "Phishing form from content scan. Inner Message: This form has been flagged for potential phishing."
or any(ml.link_analysis(., mode="aggressive").additional_responses,
strings.icontains(.json["error"]["message"], "phishing")
)
// or MS thinks there are phishing keywords
or any(ml.link_analysis(., mode="aggressive").additional_responses,
any(.json["form"]["questions"],
.["subtitleHasPhishingKeywords"] == true
)
or any(.json["form"]["questions"],
.["titleHasPhishingKeywords"] == true
)
or any(.json["form"]["descriptiveQuestions"],
.["titleHasPhishingKeywords"] == true
)
or any(.json["form"]["descriptiveQuestions"],
.["titleHasPhishingKeywords"] == true
)
)
// this logic checks for three abnormal cases
// 1) no questions
// 2) questions, but no inputs
// 3) a bunch of new lines (used to push down the submit button of the form)
// AND
// // there is one or two links that isn't "standard" on the form
or (
(
// 1) doesn't contain any sections or questions
any(ml.link_analysis(., mode="aggressive").additional_responses,
length(.json["form"]["descriptiveQuestions"]) == 0
and length(.json["form"]["questions"]) == 0
)
or
// 2) Contains a form section header, but no actual inputs
// possible question types are .Choice, .TextField, .Rating, .DateTime, .Ranking, .MatrixChoiceGroup, .MatrixChoice, and .NPS
any(ml.link_analysis(., mode="aggressive").additional_responses,
length(.json["form"]["descriptiveQuestions"]) > 0
and length(.json["form"]["questions"]) == 0
)
or
// 3) a bunch of new lines (used to push down the submit button of the form)
(
strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
'<br><br>'
) > 20
or strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
'\n\n'
) > 20
or strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
'<span><span>'
) > 20
or any(ml.link_analysis(., mode="aggressive").additional_responses,
any(.json["form"]["questions"],
strings.icount(.["formsProRTQuestionTitle"],
'<br><br>'
) > 20
or strings.icount(.["formsProRTQuestionTitle"], '\n\n') > 20
or strings.icount(.["formsProRTQuestionTitle"],
'<span><span>'
) > 20
)
)
)
)
// AND
and
// there is one or two links to another page
0 < length(filter(ml.link_analysis(.).final_dom.links,
not (
(
(
.display_text =~ "Privacy and cookies"
or .display_text =~ "terms of use"
or .display_text =~ "report abuse"
)
and .href_url.domain.root_domain =~ 'microsoft.com'
)
or .href_url.domain.root_domain =~ sender.email.domain.root_domain
or (
.href_url.domain.tld == "ms"
// Microsoft does not own the .ms TLD, this checks to ensure it is one of their domains
and (
network.whois(.href_url.domain).registrant_company == "Microsoft Corporation"
or strings.ilike(network.whois(.href_url.domain
).registrar_name,
"*MarkMonitor*",
"*CSC Corporate*",
"*com laude*"
)
)
)
)
)
) <= 2
and (
not strings.contains(ml.link_analysis(., mode="aggressive").final_dom.raw,
'role="progressbar" aria-label="Page 1 of '
)
or any(ml.link_analysis(., mode="aggressive").additional_responses,
.json["form"]["progressBarEnabled"] == false
)
)
)
)
Detection logic
Scope: inbound message.
The detection rule matches on message groups which make use of Microsoft Forms as a landing page. The landing page contains links which are newly registered, use free file or subdomain hosts, URL shorteners or when visited are phishing pages, lead to a captcha or redirect to a top website.
- inbound message
any of
filter(body.links)where any holds:all of:
- strings.replace_confusables(.display_text) matches 'review|proposal|document|efax|restore|[o0]pen|secure|messaging|reset|account|verify|login|notification|alert|urgent|immediate|access|support|\\bupdate\\b|download|attachment|service|payment|remittance|invoice'
not:
- strings.replace_confusables(.display_text) matches 'customer service'
all of:
not:
- profile.by_sender().solicited
- profile.by_sender().prevalence in ('new', 'outlier')
- ml.link_analysis(., mode='aggressive').final_dom.raw contains 'This form was blocked due to privacy or safety concerns.'
any of
ml.link_analysis(., mode='aggressive').additional_responseswhere:- .json['error']['message'] contains 'phishing'
any of
ml.link_analysis(., mode='aggressive').additional_responseswhere any holds:any of
.json['form']['questions']where:- .['subtitleHasPhishingKeywords'] is True
any of
.json['form']['questions']where:- .['titleHasPhishingKeywords'] is True
any of
.json['form']['descriptiveQuestions']where:- .['titleHasPhishingKeywords'] is True
any of
.json['form']['descriptiveQuestions']where:- .['titleHasPhishingKeywords'] is True
all of:
any of:
any of
ml.link_analysis(., mode='aggressive').additional_responseswhere all hold:- length(.json['form']['descriptiveQuestions']) is 0
- length(.json['form']['questions']) is 0
any of
ml.link_analysis(., mode='aggressive').additional_responseswhere all hold:- length(.json['form']['descriptiveQuestions']) > 0
- length(.json['form']['questions']) is 0
any of:
- strings.icount(ml.link_analysis(., mode='aggressive').final_dom.raw, '<br><br>') > 20
- strings.icount(ml.link_analysis(., mode='aggressive').final_dom.raw, '\\n\\n') > 20
- strings.icount(ml.link_analysis(., mode='aggressive').final_dom.raw, '<span><span>') > 20
any of
ml.link_analysis(., mode='aggressive').additional_responseswhere:any of
.json['form']['questions']where any holds:- strings.icount(.['formsProRTQuestionTitle'], '<br><br>') > 20
- strings.icount(.['formsProRTQuestionTitle'], '\\n\\n') > 20
- strings.icount(.['formsProRTQuestionTitle'], '<span><span>') > 20
all of:
- length(filter(ml.link_analysis(.).final_dom.links, not .display_text =~ 'Privacy and cookies' or .display_text =~ 'terms of use' or .display_text =~ 'report abuse' and .href_url.domain.root_domain =~ 'microsoft.com' or .href_url.domain.root_domain =~ sender.email.domain.root_domain or .href_url.domain.tld == 'ms' and network.whois(.href_url.domain).registrant_company == 'Microsoft Corporation' or strings.ilike(network.whois(.href_url.domain).registrar_name, '*MarkMonitor*', '*CSC Corporate*', '*com laude*'))) > 0
- length(filter(ml.link_analysis(.).final_dom.links, not .display_text =~ 'Privacy and cookies' or .display_text =~ 'terms of use' or .display_text =~ 'report abuse' and .href_url.domain.root_domain =~ 'microsoft.com' or .href_url.domain.root_domain =~ sender.email.domain.root_domain or .href_url.domain.tld == 'ms' and network.whois(.href_url.domain).registrant_company == 'Microsoft Corporation' or strings.ilike(network.whois(.href_url.domain).registrar_name, '*MarkMonitor*', '*CSC Corporate*', '*com laude*'))) ≤ 2
any of:
not:
- ml.link_analysis(., mode='aggressive').final_dom.raw contains 'role="progressbar" aria-label="Page 1 of '
any of
ml.link_analysis(., mode='aggressive').additional_responseswhere:- .json['form']['progressBarEnabled'] is False
Inspects: body.links, body.links[].href_url.domain.domain, sender.email.domain.root_domain, type.inbound. Sensors: ml.link_analysis, network.whois, profile.by_sender, regex.icontains, strings.contains, strings.icontains, strings.icount, strings.ilike, strings.replace_confusables.
Indicators matched (14)
| Field | Match | Value |
|---|---|---|
body.links[].href_url.domain.domain | equals | forms.office.com |
regex.icontains | regex | review|proposal|document|efax|restore|[o0]pen|secure|messaging|reset|account|verify|login|notification|alert|urgent|immediate|access|support|\bupdate\b|download|attachment|service|payment|remittance|invoice |
regex.icontains | regex | customer service |
strings.icontains | substring | This form was blocked due to privacy or safety concerns. |
strings.icontains | substring | phishing |
ml.link_analysis(filter(body.links)[]).final_dom.links[].display_text | equals | Privacy and cookies |
ml.link_analysis(filter(body.links)[]).final_dom.links[].display_text | equals | terms of use |
ml.link_analysis(filter(body.links)[]).final_dom.links[].display_text | equals | report abuse |
ml.link_analysis(filter(body.links)[]).final_dom.links[].href_url.domain.root_domain | equals | microsoft.com |
ml.link_analysis(filter(body.links)[]).final_dom.links[].href_url.domain.tld | equals | ms |
strings.ilike | substring | *MarkMonitor* |
strings.ilike | substring | *CSC Corporate* |
2 more
strings.ilike | substring | *com laude* |
strings.contains | substring | role="progressbar" aria-label="Page 1 of |