Detection rules › Sublime MQL
Request for Quote or Purchase (RFQ|RFP) with HTML smuggling attachment
RFQ/RFP scams involve fraudulent emails posing as legitimate requests for quotations or purchases, often sent by scammers impersonating reputable organizations. These scams aim to deceive recipients into providing sensitive information or conducting unauthorized transactions, often leading to financial loss, or data leakage.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Evasion |
Event coverage
| Message attribute |
|---|
| attachments (collection) |
| body.current_thread |
| subject |
| type |
Rule body MQL
type.inbound
// RFP/RFQ language
and 1 of (
regex.icontains(body.current_thread.text, '(discuss.{0,15}purchas(e|ing))'),
regex.icontains(body.current_thread.text,
'(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)'
),
regex.icontains(body.current_thread.text, '(please|kindly).{0,30}quote'),
regex.icontains(subject.subject,
'(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)'
),
any(attachments,
regex.icontains(.file_name, "(purchase.?order|Quot(e|ation))")
),
any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request")
and any(ml.nlu_classifier(body.current_thread.text).entities,
.name == "urgency"
),
any(ml.nlu_classifier(body.current_thread.text).tags,
.name == "purchase_order" and .confidence == "high"
)
)
// HTML smuggling
and any(attachments,
(
.file_extension in~ ("html", "htm", "shtml", "dhtml")
or .file_extension in~ $file_extensions_common_archives
or .file_type == "html"
)
and any(file.explode(.),
(
length(filter(.scan.javascript.identifiers,
strings.like(., "document", "write", "atob")
)
) == 3
// usage: document['write'](atob)
or any(.scan.strings.strings,
strings.ilike(., "*document*write*atob*")
)
// usage: some_var = atob();
or any(.scan.strings.strings, strings.ilike(., "*=*atob*;"))
// usage: obfuscating "atob"
or any(.scan.javascript.identifiers,
strings.ilike(., '*ato\u0062*')
)
// usage: document.head.insertAdjacentHTML("beforeend", atob(...
or any(.scan.strings.strings,
strings.ilike(.,
"*document*write*atob*",
"*document*insertAdjacentHTML*atob*"
)
)
)
)
)
Detection logic
Scope: inbound message.
RFQ/RFP scams involve fraudulent emails posing as legitimate requests for quotations or purchases, often sent by scammers impersonating reputable organizations. These scams aim to deceive recipients into providing sensitive information or conducting unauthorized transactions, often leading to financial loss, or data leakage.
- inbound message
at least 1 of:
- body.current_thread.text matches '(discuss.{0,15}purchas(e|ing))'
- body.current_thread.text matches '(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)'
- body.current_thread.text matches '(please|kindly).{0,30}quote'
- subject.subject matches '(request for (purchase|quot(e|ation))|\\bRFQ\\b|\\bRFP\\b)'
any of
attachmentswhere:- .file_name matches '(purchase.?order|Quot(e|ation))'
all of:
any of
ml.nlu_classifier(body.current_thread.text).entitieswhere:- .name is 'request'
any of
ml.nlu_classifier(body.current_thread.text).entitieswhere:- .name is 'urgency'
any of
ml.nlu_classifier(body.current_thread.text).tagswhere all hold:- .name is 'purchase_order'
- .confidence is 'high'
any of
attachmentswhere all hold:any of:
- .file_extension in ('html', 'htm', 'shtml', 'dhtml')
- .file_extension in $file_extensions_common_archives
- .file_type is 'html'
any of
file.explode(.)where any holds:- length(filter(.scan.javascript.identifiers, strings.like(., 'document', 'write', 'atob'))) is 3
any of
.scan.strings.stringswhere:- . matches '*document*write*atob*'
any of
.scan.strings.stringswhere:- . matches '*=*atob*;'
any of
.scan.javascript.identifierswhere:- . matches '*ato\\u0062*'
any of
.scan.strings.stringswhere:. matches any of 2 patterns
*document*write*atob**document*insertAdjacentHTML*atob*
Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, body.current_thread.text, subject.subject, type.inbound. Sensors: file.explode, ml.nlu_classifier, regex.icontains, strings.ilike, strings.like. Reference lists: $file_extensions_common_archives.
Indicators matched (21)
| Field | Match | Value |
|---|---|---|
regex.icontains | regex | (discuss.{0,15}purchas(e|ing)) |
regex.icontains | regex | (sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation) |
regex.icontains | regex | (please|kindly).{0,30}quote |
regex.icontains | regex | (request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b) |
regex.icontains | regex | (purchase.?order|Quot(e|ation)) |
ml.nlu_classifier(body.current_thread.text).entities[].name | equals | request |
ml.nlu_classifier(body.current_thread.text).entities[].name | equals | urgency |
ml.nlu_classifier(body.current_thread.text).tags[].name | equals | purchase_order |
ml.nlu_classifier(body.current_thread.text).tags[].confidence | equals | high |
attachments[].file_extension | member | html |
attachments[].file_extension | member | htm |
attachments[].file_extension | member | shtml |
9 more
attachments[].file_extension | member | dhtml |
attachments[].file_type | equals | html |
strings.like | substring | document |
strings.like | substring | write |
strings.like | substring | atob |
strings.ilike | substring | *document*write*atob* |
strings.ilike | substring | *=*atob*; |
strings.ilike | substring | *ato\u0062* |
strings.ilike | substring | *document*insertAdjacentHTML*atob* |