Detection rules › Sublime MQL

Sublime MQL rules: fictitious

Attachment: Fictitious invoice using LinkedIn's address

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

Detects PDF attachments created with wkhtmltopdf or Qt that contain LinkedIn's headquarters address (1000 W Maude Ave) in financial communications context, but do not mention LinkedIn itself.

Threat Classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • type

Rule Body

type.inbound
and 0 < length(filter(attachments, .file_type == "pdf")) < 3
and any(filter(attachments,
               .file_type == "pdf"
               // creator and producer of PDF seen in malicious content
               and (
                 strings.starts_with(beta.parse_exif(.).creator, "wkhtmltopdf")
                 or strings.starts_with(beta.parse_exif(.).producer, "Qt ")
               )
        ),
        any(filter(file.explode(.), .scan.ocr.raw is not null),
            // contains LinkedIn HQ address but not from LinkedIn
            (
              strings.icontains(.scan.ocr.raw, "1000 W Maude Ave")
              and not strings.icontains(.scan.ocr.raw, "linkedin")
            )
        )
)
and any(ml.nlu_classifier(body.current_thread.text).topics,
        .name == "Financial Communications" and .confidence != "low"
)

Detection Logic

Scope: inbound message.

Detects PDF attachments created with wkhtmltopdf or Qt that contain LinkedIn's headquarters address (1000 W Maude Ave) in financial communications context, but do not mention LinkedIn itself.

  1. inbound message
  2. all of:
    • (0) < (length(filter(attachments, .file_type == "pdf")))
    • (length(filter(attachments, .file_type == "pdf"))) < (3)
  3. any(filter(attachments, .file_type == "pdf" // creator and producer of PDF seen in malicious content and ( strings.starts_with(beta.parse_exif(.).creator, "wkhtmltopdf") or strings.starts_with(beta.parse_exif(.).producer, "Qt ") ) ), any(filter(file.explode(.), .scan.ocr.raw is not null), // contains LinkedIn HQ address but not from LinkedIn ( strings.icontains(.scan.ocr.raw, "1000 W Maude Ave") and not strings.icontains(.scan.ocr.raw, "linkedin") ) ) )
  4. any(ml.nlu_classifier(body.current_thread.text).topics, .name == "Financial Communications" and .confidence != "low" )

Inspects: attachments[].file_type, body.current_thread.text, type.inbound. Sensors: beta.parse_exif, file.explode, ml.nlu_classifier, strings.icontains, strings.starts_with.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalspdf
strings.starts_withprefixwkhtmltopdf
strings.starts_withprefixQt
strings.icontainssubstring1000 W Maude Ave
ml.nlu_classifier(body.current_thread.text).topics[].nameequalsFinancial Communications

Stages and Predicates

Stage 1: mql_rule

and
  length func_call "(0) < (length(filter(attachments, .file_type == \"pdf\")))"
  length func_call "(length(filter(attachments, .file_type == \"pdf\"))) < (3)"
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .file_type == \"pdf\"\n               // creator and producer of PDF seen in malicious content\n               and (\n                 strings.starts_with(beta.parse_exif(.).creator, \"wkhtmltopdf\")\n                 or strings.starts_with(beta.parse_exif(.).producer, \"Qt \")\n               )\n        ),\n        any(filter(file.explode(.), .scan.ocr.raw is not null),\n            // contains LinkedIn HQ address but not from LinkedIn\n            (\n              strings.icontains(.scan.ocr.raw, \"1000 W Maude Ave\")\n              and not strings.icontains(.scan.ocr.raw, \"linkedin\")\n            )\n        )\n)"
   macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n        .name == \"Financial Communications\" and .confidence != \"low\"\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Back to all Sublime MQL rules