Detection rules › Sublime MQL
Attachment: Suspicious PDF created with headless browser
Detects PDF documents containing a table of contents that were generated using HeadlessChrome, Chromium with Skia/PDF, or QT with empty metadata fields - common characteristics of automated malicious document creation.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Evasion, PDF |
Event coverage
| Message attribute |
|---|
| attachments (collection) |
| type |
Rule body MQL
type.inbound
and (
// directly attached PDF
any(filter(attachments, .file_type == "pdf"),
(
// table of contents detection
(
any(file.explode(.),
strings.contains(.scan.ocr.raw, 'TABLE OF CONTEN')
)
// the Table of contents can be on another page
and any(file.explode(.),
regex.icontains(.scan.ocr.raw,
'(?:[\r\n]|^)+(?:\s*1\s*(?:\.|:))?\s*Introduction'
)
or strings.icontains(.scan.ocr.raw, 'marked in red')
)
)
or (
any(file.explode(.),
any(.scan.strings.strings,
// heading of sections within observed documents
any([
'Employee Acknowledgement',
'Document Summary',
'appraisal overview',
'accessing full appraisal',
],
.. =~ .
)
)
// or links to free subdomain host
or any(.scan.url.urls,
.domain.root_domain in $free_subdomain_hosts
and .domain.subdomain is not null
)
)
)
)
and (
(
(
strings.icontains(beta.parse_exif(.).creator, 'HeadlessChrome')
or strings.icontains(beta.parse_exif(.).creator, 'Chromium')
)
and strings.icontains(beta.parse_exif(.).producer, 'Skia/PDF')
)
or (
any(beta.parse_exif(.).fields,
.key == "Creator"
and (.value == "" or strings.istarts_with(.value, 'wkhtmltopdf'))
)
and any(beta.parse_exif(.).fields,
.key == "Title"
and (
.value == ""
// company handbook
or .value in ('Company HandBook')
// appraisal themes
or strings.icontains(.value,
'Employee Performance Appraisal'
)
)
)
and strings.istarts_with(beta.parse_exif(.).producer, 'QT ')
)
)
)
// or within an attached EML
or any(filter(attachments,
.content_type == "message/rfc822" or .file_extension == "eml"
),
any(filter(file.parse_eml(.).attachments, .file_type == "pdf"),
(
// table of contents detection
(
any(file.explode(.),
strings.contains(.scan.ocr.raw, 'TABLE OF CONTEN')
)
// the Table of contents can be on another page
and any(file.explode(.),
regex.icontains(.scan.ocr.raw,
'(?:[\r\n]|^)+(?:\s*1\s*(?:\.|:))?\s*Introduction'
)
or strings.icontains(.scan.ocr.raw, 'marked in red')
)
)
or (
any(file.explode(.),
any(.scan.strings.strings,
// heading of sections within observed documents
any([
'Employee Acknowledgement',
'Document Summary',
'appraisal overview',
'accessing full appraisal',
],
.. =~ .
)
)
// or links to free subdomain host
or any(.scan.url.urls,
.domain.root_domain in $free_subdomain_hosts
and .domain.subdomain is not null
)
)
)
)
and (
(
(
strings.icontains(beta.parse_exif(.).creator,
'HeadlessChrome'
)
or strings.icontains(beta.parse_exif(.).creator, 'Chromium')
)
and strings.icontains(beta.parse_exif(.).producer, 'Skia/PDF')
)
or (
any(beta.parse_exif(.).fields,
.key == "Creator"
and (
.value == ""
or strings.istarts_with(.value, 'wkhtmltopdf')
)
)
and any(beta.parse_exif(.).fields,
.key == "Title"
and (
.value == ""
// company handbook
or .value in ('Company HandBook')
// appraisal themes
or strings.icontains(.value,
'Employee Performance Appraisal'
)
)
)
and strings.istarts_with(beta.parse_exif(.).producer, 'QT ')
)
)
)
)
)
Detection logic
Scope: inbound message.
Detects PDF documents containing a table of contents that were generated using HeadlessChrome, Chromium with Skia/PDF, or QT with empty metadata fields - common characteristics of automated malicious document creation.
- inbound message
any of:
any of
filter(attachments)where all hold:any of:
all of:
any of
file.explode(.)where:- .scan.ocr.raw contains 'TABLE OF CONTEN'
any of
file.explode(.)where any holds:- .scan.ocr.raw matches '(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction'
- .scan.ocr.raw contains 'marked in red'
any of
file.explode(.)where any holds:any of
.scan.strings.stringswhere:any of
['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal']where:- . is .
any of
.scan.url.urlswhere all hold:- .domain.root_domain in $free_subdomain_hosts
- .domain.subdomain is set
any of:
all of:
any of:
- beta.parse_exif(.).creator contains 'HeadlessChrome'
- beta.parse_exif(.).creator contains 'Chromium'
- beta.parse_exif(.).producer contains 'Skia/PDF'
all of:
any of
beta.parse_exif(.).fieldswhere all hold:- .key is 'Creator'
any of:
- .value is ''
- .value starts with 'wkhtmltopdf'
any of
beta.parse_exif(.).fieldswhere all hold:- .key is 'Title'
any of:
- .value is ''
- .value in ('Company HandBook')
- .value contains 'Employee Performance Appraisal'
- beta.parse_exif(.).producer starts with 'QT '
any of
filter(attachments)where:any of
filter(...)where all hold:any of:
all of:
any of
file.explode(.)where:- .scan.ocr.raw contains 'TABLE OF CONTEN'
any of
file.explode(.)where any holds:- .scan.ocr.raw matches '(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction'
- .scan.ocr.raw contains 'marked in red'
any of
file.explode(.)where any holds:any of
.scan.strings.stringswhere:any of
['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal']where:- . is .
any of
.scan.url.urlswhere all hold:- .domain.root_domain in $free_subdomain_hosts
- .domain.subdomain is set
any of:
all of:
any of:
- beta.parse_exif(.).creator contains 'HeadlessChrome'
- beta.parse_exif(.).creator contains 'Chromium'
- beta.parse_exif(.).producer contains 'Skia/PDF'
all of:
any of
beta.parse_exif(.).fieldswhere all hold:- .key is 'Creator'
any of:
- .value is ''
- .value starts with 'wkhtmltopdf'
any of
beta.parse_exif(.).fieldswhere all hold:- .key is 'Title'
any of:
- .value is ''
- .value in ('Company HandBook')
- .value contains 'Employee Performance Appraisal'
- beta.parse_exif(.).producer starts with 'QT '
Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: beta.parse_exif, file.explode, file.parse_eml, regex.icontains, strings.contains, strings.icontains, strings.istarts_with. Reference lists: $free_subdomain_hosts.
Indicators matched (21)
| Field | Match | Value |
|---|---|---|
attachments[].file_type | equals | pdf |
strings.contains | substring | TABLE OF CONTEN |
regex.icontains | regex | (?:[\r\n]|^)+(?:\s*1\s*(?:\.|:))?\s*Introduction |
strings.icontains | substring | marked in red |
strings.icontains | substring | HeadlessChrome |
strings.icontains | substring | Chromium |
strings.icontains | substring | Skia/PDF |
beta.parse_exif(filter(attachments)[]).fields[].key | equals | Creator |
beta.parse_exif(filter(attachments)[]).fields[].value | equals | |
strings.istarts_with | prefix | wkhtmltopdf |
beta.parse_exif(filter(attachments)[]).fields[].key | equals | Title |
beta.parse_exif(filter(attachments)[]).fields[].value | member | Company HandBook |
9 more
strings.icontains | substring | Employee Performance Appraisal |
strings.istarts_with | prefix | QT |
attachments[].content_type | equals | message/rfc822 |
attachments[].file_extension | equals | eml |
file.parse_eml(filter(attachments)[]).attachments[].file_type | equals | pdf |
beta.parse_exif(filter(...)[]).fields[].key | equals | Creator |
beta.parse_exif(filter(...)[]).fields[].value | equals | |
beta.parse_exif(filter(...)[]).fields[].key | equals | Title |
beta.parse_exif(filter(...)[]).fields[].value | member | Company HandBook |