Detection rules › Sublime MQL

Attachment: Suspicious PDF created with headless browser

Severity
high
Type
rule
Source
github.com/sublime-security/sublime-rules

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).

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, PDF

Event coverage

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.

  1. inbound message
  2. 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.strings where:
            • any of ['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal'] where:
              • . is .
          • any of .scan.url.urls where 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(.).fields where all hold:
            • .key is 'Creator'
            • any of:
              • .value is ''
              • .value starts with 'wkhtmltopdf'
          • any of beta.parse_exif(.).fields where 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.strings where:
              • any of ['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal'] where:
                • . is .
            • any of .scan.url.urls where 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(.).fields where all hold:
              • .key is 'Creator'
              • any of:
                • .value is ''
                • .value starts with 'wkhtmltopdf'
            • any of beta.parse_exif(.).fields where 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)

FieldMatchValue
attachments[].file_typeequalspdf
strings.containssubstringTABLE OF CONTEN
regex.icontainsregex(?:[\r\n]|^)+(?:\s*1\s*(?:\.|:))?\s*Introduction
strings.icontainssubstringmarked in red
strings.icontainssubstringHeadlessChrome
strings.icontainssubstringChromium
strings.icontainssubstringSkia/PDF
beta.parse_exif(filter(attachments)[]).fields[].keyequalsCreator
beta.parse_exif(filter(attachments)[]).fields[].valueequals
strings.istarts_withprefixwkhtmltopdf
beta.parse_exif(filter(attachments)[]).fields[].keyequalsTitle
beta.parse_exif(filter(attachments)[]).fields[].valuememberCompany HandBook
9 more
strings.icontainssubstringEmployee Performance Appraisal
strings.istarts_withprefixQT
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionequalseml
file.parse_eml(filter(attachments)[]).attachments[].file_typeequalspdf
beta.parse_exif(filter(...)[]).fields[].keyequalsCreator
beta.parse_exif(filter(...)[]).fields[].valueequals
beta.parse_exif(filter(...)[]).fields[].keyequalsTitle
beta.parse_exif(filter(...)[]).fields[].valuememberCompany HandBook