Detection rules › Sublime MQL
Attachment: PDF proposal with credential theft indicators
PDF attachment with 'proposal' in filename contains sender or recipient domain, credential theft language detected via OCR, and includes a single URL link.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | PDF, Social engineering, Evasion |
Event coverage
Rule body MQL
type.inbound
and not (
(subject.is_reply or subject.is_forward)
and (length(headers.references) > 0 or headers.in_reply_to is not null)
)
// a single PDFs
and length(filter(attachments, .file_type == "pdf")) == 1
and any(attachments,
.file_type == "pdf"
and regex.icontains(.file_name, '(?:proposal|bid|document|rf[pq])\b')
and beta.parse_exif(.).page_count == 1
// OCR is cred_theft
and any(ml.nlu_classifier(beta.ocr(.).text).intents,
.name == "cred_theft"
)
and length(beta.ocr(.).text) < 2000
and beta.ocr(.).success
// contains exactly one link on the root pdf
and any(file.explode(.),
.depth == 0
and length(.scan.url.urls) == 1
and all(.scan.url.urls,
.domain.root_domain not in (
'iso.org',
'w3.org',
'bfo.com', // pdf producer
'camscanner.com', // pdf producer
)
and not strings.istarts_with(.url, 'mailto')
)
)
)
// negate highly trusted sender domains unless they fail DMARC authentication
and not (
sender.email.domain.root_domain in $high_trust_sender_root_domains
and coalesce(headers.auth_summary.dmarc.pass, false)
)
Detection logic
Scope: inbound message.
PDF attachment with 'proposal' in filename contains sender or recipient domain, credential theft language detected via OCR, and includes a single URL link.
- inbound message
not:
all of:
any of:
- subject.is_reply
- subject.is_forward
any of:
- length(headers.references) > 0
- headers.in_reply_to is set
- length(filter(attachments, .file_type == 'pdf')) is 1
any of
attachmentswhere all hold:- .file_type is 'pdf'
- .file_name matches '(?:proposal|bid|document|rf[pq])\\b'
- beta.parse_exif(.).page_count is 1
any of
ml.nlu_classifier(beta.ocr(.).text).intentswhere:- .name is 'cred_theft'
- length(beta.ocr(.).text) < 2000
- beta.ocr(.).success
any of
file.explode(.)where all hold:- .depth is 0
- length(.scan.url.urls) is 1
all of
.scan.url.urlswhere all hold:- .domain.root_domain not in ('iso.org', 'w3.org', 'bfo.com', 'camscanner.com')
not:
- .url starts with 'mailto'
not:
all of:
- sender.email.domain.root_domain in $high_trust_sender_root_domains
- coalesce(headers.auth_summary.dmarc.pass)
Inspects: attachments[].file_name, attachments[].file_type, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, sender.email.domain.root_domain, subject.is_forward, subject.is_reply, type.inbound. Sensors: beta.ocr, beta.parse_exif, file.explode, ml.nlu_classifier, regex.icontains, strings.istarts_with. Reference lists: $high_trust_sender_root_domains.
Indicators matched (8)
| Field | Match | Value |
|---|---|---|
attachments[].file_type | equals | pdf |
regex.icontains | regex | (?:proposal|bid|document|rf[pq])\b |
ml.nlu_classifier(beta.ocr(attachments[]).text).intents[].name | equals | cred_theft |
file.explode(attachments[])[].scan.url.urls[].domain.root_domain | member | iso.org |
file.explode(attachments[])[].scan.url.urls[].domain.root_domain | member | w3.org |
file.explode(attachments[])[].scan.url.urls[].domain.root_domain | member | bfo.com |
file.explode(attachments[])[].scan.url.urls[].domain.root_domain | member | camscanner.com |
strings.istarts_with | prefix | mailto |