Detection rules › Sublime MQL

Sublime MQL rules: attachment

RuleSeverity
Adobe branded PDF file linking to a password-protected file from untrusted senderhigh
Attachment soliciting user to enable macroshigh
Attachment with auto-executing macro (unsolicited)medium
Attachment with auto-opening VBA macro (unsolicited)medium
Attachment with encrypted zip (unsolicited)medium
Attachment with high risk VBA macro (unsolicited)high
Attachment with macro calling executablehigh
Attachment with suspicious author (unsolicited)high
Attachment with unscannable encrypted zipmedium
Attachment with VBA macros from employee impersonation (unsolicited)high
Attachment: .csproj with suspicious commandshigh
Attachment: 7z Archive Containing RAR Filemedium
Attachment: Adobe image lure in body or attachment with suspicious linkmedium
Attachment: Adobe Sign lure PDF with embedded banner imagesmedium
Attachment: Any .sap file (unsolicited)low
Attachment: Any HTML file (unsolicited)low
Attachment: Any HTML file (untrusted sender)medium
Attachment: Any HTML file within archive (unsolicited)medium
Attachment: Archive containing disallowed file typelow
Attachment: Archive containing HTML file with file scheme linkhigh
Attachment: Archive contains DLL-loading macrohigh
Attachment: Archive with embedded CHM filemedium
Attachment: Archive with embedded EXE filehigh
Attachment: Archive with pdf, txt and wsf filesmedium
Attachment: Base64 encoded bash command in filenamehigh
Attachment: Calendar file with invisible Unicode charactershigh
Attachment: Calendar invite from recently registered domainhigh
Attachment: Calendar invite with Google redirect and invoice requestmedium
Attachment: Calendar invite with suspicious link leading to an open redirecthigh
Attachment: Callback phishing solicitation via image filehigh
Attachment: Callback phishing solicitation via pdf filehigh
Attachment: Callback phishing solicitation via text-based filemedium
Attachment: Canva PDF with susupicious author metadatahigh
Attachment: cmd file extensionlow
Attachment: Compensation review lure with QR codehigh
Attachment: Compensation-themed DOCX with QR code credential thefthigh
Attachment: Credit card application with WhatsApp contactmedium
Attachment: CVE-2023-21716 - Microsoft Office Remote Code Execution Vulnerabilityhigh
Attachment: Decoy PDF author (Julie P.)high
Attachment: DocuSign impersonation via PDF linking to new domainmedium
Attachment: DocX embedded binaryhigh
Attachment: DOCX with hyperlink targeting recipient addressmedium
Attachment: DOCX with malicious document template artifactsmedium
Attachment: Double base64-encoded zip file in HTML smuggling attachmenthigh
Attachment: Dropbox image lure with no Dropbox domains in linksmedium
Attachment: Duplicated header pages in fraudulent multi-page PDF Request for Quotationmedium
Attachment: EICAR string presentlow
Attachment: Embedded Javascript in SVG filehigh
Attachment: Embedded VBScript in MHT filemedium
Attachment: EML containing a base64 encoded scripthigh
Attachment: EML file contains HTML attachment with login portal indicatorshigh
Attachment: EML file with HTML attachment (unsolicited)medium
Attachment: EML file with IPFS linksmedium
Attachment: EML with embedded Javascript in SVG filehigh
Attachment: EML with Encrypted ZIPlow
Attachment: EML with link to credential phishing pagehigh
Attachment: EML with QR code redirecting to Cloudflare challengeslow
Attachment: EML with suspicious indicatorsmedium
Attachment: Emotet heavily padded doc in zip filehigh
Attachment: Employment contract update with suspicious file naminghigh
Attachment: Encrypted Microsoft Office file (unsolicited)medium
Attachment: Encrypted PDF With Credential Harvesting Indicatorsmedium
Attachment: Encrypted PDF with credential theft bodymedium
Attachment: Encrypted PDF with credential theft language in EMLmedium
Attachment: Encrypted ZIP containing VHDX filemedium
Attachment: Excel file with document sharing lure created by Go Excelizehigh
Attachment: Excel file with suspicious template identifierhigh
Attachment: Excel Web Query File (IQY)high
Attachment: Fake attachment image luremedium
Attachment: Fake lawyer & sports agent identitieshigh
Attachment: Fake PDF Invoices Yaramedium
Attachment: Fake research internship offermedium
Attachment: Fake scan-to-emailmedium
Attachment: Fake secure message and suspicious indicatorsmedium
Attachment: Fake Slack installerhigh
Attachment: Fake voicemail via PDFmedium
Attachment: Fake Zoom installerhigh
Attachment: File execution via Javascriptmedium
Attachment: Filename containing Unicode braille pattern blank characterhigh
Attachment: Filename containing Unicode right-to-left override characterhigh
Attachment: Finance themed PDF with observed phishing templatemedium
Attachment: GZ archive with credential theft contentmedium
Attachment: Gzip-archived with nested HTML file containing image and button linkhigh
Attachment: HTML attachment with Javascript locationhigh
Attachment: HTML attachment with login portal indicatorsmedium
Attachment: HTML file contains exclusively Javascriptmedium
Attachment: HTML file with excessive 'const' declarations and abnormally long timeoutshigh
Attachment: HTML file with excessive padding and suspicious patternshigh
Attachment: HTML file with reference to recipient and suspicious patternshigh
Attachment: HTML smuggling 'body onload' linking to suspicious destinationhigh
Attachment: HTML smuggling 'body onload' with high entropy and suspicious texthigh
Attachment: HTML smuggling - QR Code with suspicious linkshigh
Attachment: HTML smuggling Microsoft sign inhigh
Attachment: HTML smuggling with atob and high entropyhigh
Attachment: HTML smuggling with atob and high entropy via calendar invitehigh
Attachment: HTML smuggling with auto-downloaded filehigh
Attachment: HTML smuggling with base64 encoded JavaScript functionhigh
Attachment: HTML smuggling with base64 encoded ZIP filemedium
Attachment: HTML smuggling with concatenation obfuscationhigh
Attachment: HTML smuggling with decimal encodinghigh
Attachment: HTML smuggling with embedded base64 streamed file downloadhigh
Attachment: HTML smuggling with embedded base64-encoded executablehigh
Attachment: HTML smuggling with embedded base64-encoded ISOhigh
Attachment: HTML smuggling with eval and atobhigh
Attachment: HTML smuggling with eval and atob via calendar invitehigh
Attachment: HTML smuggling with excessive line break obfuscationhigh
Attachment: HTML smuggling with excessive string concatenation and suspicious patternsmedium
Attachment: HTML smuggling with fromCharCode and other signalshigh
Attachment: HTML smuggling with hex stringsmedium
Attachment: HTML smuggling with high entropy and other signalshigh
Attachment: HTML smuggling with raw array bufferhigh
Attachment: HTML smuggling with RC4 decryptionhigh
Attachment: HTML smuggling with ROT13high
Attachment: HTML smuggling with setTimeouthigh
Attachment: HTML smuggling with unescapehigh
Attachment: HTML with emoji-to-character maphigh
Attachment: HTML with hidden bodyhigh
Attachment: HTML with JavaScript functions for HTTP requestshigh
Attachment: HTML with obfuscation and recipient's email in JavaScript stringshigh
Attachment: ICS calendar file with base64 encoded recipient address in URL parametershigh
Attachment: ICS calendar file with QR code containing recipient email addresshigh
Attachment: ICS calendar file with recipient address in UID fieldhigh
Attachment: ICS calendar file with suspicious product identifiermedium
Attachment: ICS calendar file with suspicious UID domainmedium
Attachment: ICS calendar invite with bid/RFP lure and suspicious linkmedium
Attachment: ICS calendar invite with financial lure and suspicious linkmedium
Attachment: ICS calendar with embedded file from internal sender with SPF failurehigh
Attachment: ICS file with AWS Lambda URLmedium
Attachment: ICS file with credential theft indicatorsmedium
Attachment: ICS file with excessive custom propertiesmedium
Attachment: ICS file with links to newly registered domainsmedium
Attachment: ICS file with meeting prefixhigh
Attachment: ICS file with non-Gregorian calendar scalemedium
Attachment: ICS invite meeting luremedium
Attachment: ICS voicemail lure with suspicious linkmedium
Attachment: ICS with embedded documentlow
Attachment: ICS with embedded Javascript in SVG filehigh
Attachment: ICS with employee policy review lurehigh
Attachment: Identity Confirmation With Document Unlock Codemedium
Attachment: Image-only docx/pptx callback phishingmedium
Attachment: Invoice and W-9 PDFs with suspicious creatorshigh
Attachment: JavaScript file with suspicious base64-encoded executablehigh
Attachment: JPEG with gd-jpeg creator and suspicious file namehigh
Attachment: Legal themed message or PDF with suspicious indicatorsmedium
Attachment: Link file with UNC pathmedium
Attachment: Link to Doubleclick.net open redirectmedium
Attachment: LNK filehigh
Attachment: LNK with embedded contenthigh
Attachment: Macro files containing MHT contentmedium
Attachment: Macro with suspected use of COM ShellBrowserWindow object for process creationhigh
Attachment: Malformed OLE filehigh
Attachment: Malicious OneNote commandshigh
Attachment: Malicious zip file matching zipline campaignmedium
Attachment: Microsoft 365 credential phishinghigh
Attachment: Microsoft impersonation via PDF with link and suspicious languagehigh
Attachment: Microsoft OAuth credential harvesting via EML with embedded malicious linkshigh
Attachment: Microsoft SharePoint Impersonation via images in macro-enabled attachmenthigh
Attachment: MS Office or RTF file with Shell.Explorer.1 com object with embedded LNKmedium
Attachment: MS OOXML file created by Administrator with zero edit timehigh
Attachment: MSI installer filemedium
Attachment: Office document loads remote document templatemedium
Attachment: Office document with VSTO add-inhigh
Attachment: Office file contains OLE relationship to credential phishing pagehigh
Attachment: Office file with credential phishing URLsmedium
Attachment: Office file with document sharing and browser instruction lureshigh
Attachment: Office file with suspicious function calls or downloaded file pathhigh
Attachment: OLE external relationship containing file scheme link to executable filetypehigh
Attachment: OLE external relationship containing file scheme link to IP addresshigh
Attachment: Password-protected PDF with fake document indicatorsmedium
Attachment: PDF Attachment with links to workers.devmedium
Attachment: PDF bid/proposal lure with credential theft indicatorsmedium
Attachment: PDF contains W9 or invoice YARA signaturesmedium
Attachment: PDF credential phishing via wkhtmltopdf/Qt with suspicious linkhigh
Attachment: PDF file with link to fake Bitcoin exchangelow
Attachment: PDF file with low reputation link to ZIP file (unsolicited)medium
Attachment: PDF file with low reputation links to suspicious filetypes (unsolicited)medium
Attachment: PDF file with recipient domain and ATT eCheckRun patternmedium
Attachment: PDF generated with wkhtmltopdf tool and default titlelow
Attachment: PDF Grant Payment lure with embedded linkhigh
Attachment: PDF Object Hash - Encrypted PDFs with fake payment notificationmedium
Attachment: PDF Object Hash associated with a fake invoice and a W-9high
Attachment: PDF Object Hash associated with fake Canada Revenue Agency documentsmedium
Attachment: PDF Object Hash with Blue File Iconmedium
Attachment: PDF proposal with credential theft indicatorshigh
Attachment: PDF RFP luremedium
Attachment: PDF templated investment luremedium
Attachment: PDF with a suspicious string and single URLhigh
Attachment: PDF with base64 JavaScript and eval functionsmedium
Attachment: PDF with blurry lure imagemedium
Attachment: PDF with credential theft language and invalid reply-to domainmedium
Attachment: PDF with credential theft language and link to a free subdomain (unsolicited)medium
Attachment: PDF with CVE-2026-34621 lureshigh
Attachment: PDF with eCheckRun luresmedium
Attachment: PDF with embedded box-lure and javascriptmedium
Attachment: PDF with fake invoice using suspicious font sizingmedium
Attachment: PDF with JSFck obfuscationhigh
Attachment: PDF with link to DMG file downloadmedium
Attachment: PDF with link to zip containing a wsf filehigh
Attachment: PDF with localhost IP in EXIF title metadatamedium
Attachment: PDF with Microsoft Purview message impersonationmedium
Attachment: PDF with multistage landing - ClickUp abusehigh
Attachment: PDF with password in filename matching body textmedium
Attachment: PDF with personal Microsoft OneNote URLmedium
Attachment: PDF with QR code containing recipient-specific credential theft contenthigh
Attachment: PDF with quote luremedium
Attachment: PDF with recipient email in linkhigh
Attachment: PDF with ReportLab library and default metadatalow
Attachment: PDF With SAI Global ISO9001 Logohigh
Attachment: PDF with secure document acknowledgment promptmedium
Attachment: PDF with self-service platform links with self sender or blank recipientsmedium
Attachment: PDF with specific author metadatahigh
Attachment: PDF with specific W-9 luremedium
Attachment: PDF with split QR codemedium
Attachment: PDF with suspicious document view luremedium
Attachment: PDF with suspicious HeadlessChrome metadatamedium
Attachment: PDF with suspicious internal object reference identifiermedium
Attachment: PDF with suspicious language and redirect to suspicious file typehigh
Attachment: PDF with suspicious link and action-oriented languagehigh
Attachment: PDF with suspicious view document characteristicsmedium
Attachment: PDF with View RFP Document lure with external linkhigh
Attachment: PDF with W-9 form indicatorshigh
Attachment: Potential sandbox evasion in Office filehigh
Attachment: PowerPoint with suspicious hyperlinkhigh
Attachment: PowerShell contenthigh
Attachment: QR code link with base64-encoded recipient addresshigh
Attachment: QR code with credential phishing indicatorsmedium
Attachment: QR code with encoded recipient targeting and redirect indicatorshigh
Attachment: QR code with recipient targeting and special charactershigh
Attachment: QR code with suspicious URL patterns in EML filehigh
Attachment: QR code with userinfo portionhigh
Attachment: QuickBooks PDF luremedium
Attachment: RDP connection filemedium
Attachment: RFC822 containing suspicious file sharing language with links from untrusted sendermedium
Attachment: RFP/RFQ impersonating government entitieshigh
Attachment: Romance scam with image lure and advance-fee or suspicious link indicatorsmedium
Attachment: RTF file with suspicious linkmedium
Attachment: RTF with embedded contentmedium
Attachment: RTF with link to free-hosted Cloudflare Pageshigh
Attachment: Self-sender PDF with minimal content and view prompthigh
Attachment: SFX archive containing commandsmedium
Attachment: Single-page PDF with S3-hosted HTML linkmedium
Attachment: Small text file with link containing recipient email addressmedium
Attachment: Soda PDF producer with encryption themeshigh
Attachment: Suspicious employee policy update document luremedium
Attachment: Suspicious PDF created with headless browserhigh
Attachment: SVG file executionhigh
Attachment: SVG file with HTML entity encoded href attributesmedium
Attachment: SVG file with hyperlinks and cursor stylingmedium
Attachment: SVG files with evasion elementshigh
Attachment: TAR file with RAR typehigh
Attachment: Targeted DOCX with personalized recipient acknowledgement luremedium
Attachment: Uncommon compressed filelow
Attachment: USDA bid invitation impersonationmedium
Attachment: Web files with suspicious commentshigh
Attachment: WinRAR CVE-2025-8088 exploitationhigh
Attachment: XLSX file with suspicious print titles metadatahigh
Attachment: ZIP containing Office binary with embedded DLLmedium
Attachment: Zip exploiting CVE-2023-38831 (unsolicited)critical
Attachment: ZIP file with CVE-2026-0866 exploitmedium
Attachment: ZIP filename mismatchlow
Brand impersonation: Adobe (QR code)high
Brand impersonation: DocuSign (QR code)high
Brand impersonation: DocuSign branded attachment lure with no DocuSign linkshigh
Brand Impersonation: Google (QR Code)high
Brand impersonation: Microsoft (QR code)high
Credential phishing: Image as content, short or no body contentsmedium
EML attachment with credential theft language (unknown sender)high
Encrypted Microsoft Office files from untrusted sendermedium
Extortion / Sextortion - PDF attachment leveraging breach data from freemail senderhigh
Extortion / sextortion in attachment from untrusted senderlow
Free subdomain link with credential theft indicatorshigh
HTML smuggling containing recipient email addressmedium
Impersonation: Fake Gmail attachmenthigh
MalwareBazaar: Malicious attachment hash (trusted reporters)high
MalwareBazaar: Malicious attachment hash in archive (trusted reporters)high
Non-RFC compliant calendar files from unsolicited sendermedium
PDF attachment with Google (AE) redirecting to a php or zip filehigh
Suspicious attachment with unscannable Cloudflare linkmedium
Suspicious VBA macros from untrusted senderhigh

Adobe branded PDF file linking to a password-protected file from untrusted sender

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

Detects pdf files with links to a remotely hosted password-protected file. This is a common technique abused by Phishing actors as well as Malware actors (IcedID, Remcos, Async Rat)

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEncryption, Evasion, Impersonation: Brand, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension == "pdf"
        and any(file.explode(.),
                any(ml.nlu_classifier(.scan.ocr.raw).intents,
                    .name == "cred_theft" and .confidence == "high"
                )
                and strings.icontains(.scan.ocr.raw, "password-protected")
                and any(ml.nlu_classifier(.scan.ocr.raw).entities,
                        .name == "org" and .text == "Adobe"
                )
        )
)

Detection Logic

Scope: inbound message.

Detects pdf files with links to a remotely hosted password-protected file. This is a common technique abused by Phishing actors as well as Malware actors (IcedID, Remcos, Async Rat)

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any(file.explode(.), any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence == "high" ) and strings.icontains(.scan.ocr.raw, "password-protected") and any(ml.nlu_classifier(.scan.ocr.raw).entities, .name == "org" and .text == "Adobe" ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, ml.nlu_classifier, strings.icontains.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionequalspdf
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidenceequalshigh
strings.icontainssubstringpassword-protected
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).entities[].nameequalsorg
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).entities[].textequalsAdobe

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension eq "pdf"
       macro "any(file.explode(.),\n                any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                    .name == \"cred_theft\" and .confidence == \"high\"\n                )\n                and strings.icontains(.scan.ocr.raw, \"password-protected\")\n                and any(ml.nlu_classifier(.scan.ocr.raw).entities,\n                        .name == \"org\" and .text == \"Adobe\"\n                )\n        )"
  type.inbound eq "true"

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"

Attachment soliciting user to enable macros

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

Recursively scans files and archives to detect documents that ask the user to enable macros, including if that text appears within an embedded image.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesMacros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or .file_extension in~ $file_extensions_common_archives
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.),
                strings.ilike(.scan.ocr.raw, "*please*enable*macros")
                or any(.scan.strings.strings,
                       strings.ilike(., "*please enable macros*")
                )
        )
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect documents that ask the user to enable macros, including if that text appears within an embedded image.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), strings.ilike(.scan.ocr.raw, "*please*enable*macros") or any(.scan.strings.strings, strings.ilike(., "*please enable macros*") ) )
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, profile.by_sender, strings.ilike. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (4)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
strings.ilikesubstring*please*enable*macros
strings.ilikesubstring*please enable macros*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                strings.ilike(.scan.ocr.raw, \"*please*enable*macros\")\n                or any(.scan.strings.strings,\n                       strings.ilike(., \"*please enable macros*\")\n                )\n        )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

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"

Attachment with auto-executing macro (unsolicited)

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

Attachment from an unsolicited sender contains a macro that will auto-execute when the file is opened. Macros are a common phishing technique used to deploy malware.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesMacros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.oletools(.).macros.keywords, .type =~ "autoexec")
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

// negate replies
and (length(headers.references) == 0 or headers.in_reply_to is null)

Detection Logic

Scope: inbound message.

Attachment from an unsolicited sender contains a macro that will auto-execute when the file is opened. Macros are a common phishing technique used to deploy malware.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.oletools(.).macros.keywords, .type =~ "autoexec")
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  4. any of:
    • length(headers.references) == 0
    • headers.in_reply_to is missing

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, headers.in_reply_to, headers.references, type.inbound. Sensors: file.oletools, profile.by_sender. Reference lists: $file_extensions_macros.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
file.oletools(attachments[]).macros.keywords[].typeequalsautoexec

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.oletools(.).macros.keywords, .type =~ \"autoexec\")"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    headers.in_reply_to is_null
    headers.references length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
headers.in_reply_tois_null
  • (no value, null check)
field:"headers.in_reply_to" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment with auto-opening VBA macro (unsolicited)

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

Recursively scans files and archives to detect embedded VBA files with an auto open exec.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesMacros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or .file_extension in~ $file_extensions_common_archives
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.), any(.scan.vba.auto_exec, . == "AutoOpen"))
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect embedded VBA files with an auto open exec.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), any(.scan.vba.auto_exec, . == "AutoOpen"))
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, profile.by_sender. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
file.explode(attachments[])[].scan.vba.auto_exec[]equalsAutoOpen

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.), any(.scan.vba.auto_exec, . == \"AutoOpen\"))"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

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"

Attachment with encrypted zip (unsolicited)

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

Recursively scans files and archives to detect encrypted zip files.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Encryption

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (.file_type == "zip" or .file_extension == "zip")
        and any(file.explode(.), any(.flavors.yara, . == 'encrypted_zip'))
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().prevalence == "common"

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect encrypted zip files.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'zip'
      • .file_extension is 'zip'
    • any(file.explode(.), any(.flavors.yara, . == 'encrypted_zip'))
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  4. not:
    • profile.by_sender().prevalence == "common"

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, profile.by_sender.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalszip
attachments[].file_extensionequalszip
file.explode(attachments[])[].flavors.yara[]equalsencrypted_zip

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension eq "zip"
        attachments.file_type eq "zip"
       macro "any(file.explode(.), any(.flavors.yara, . == 'encrypted_zip'))"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  not
    profile.by_sender func_call "profile.by_sender().prevalence == \"common\""
  type.inbound eq "true"

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"

Attachment with high risk VBA macro (unsolicited)

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

Potentially malicious attachment containing a VBA macro. Oletools categorizes the macro risk as 'high'.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesMacros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and file.oletools(.).indicators.vba_macros.risk == "high"
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Potentially malicious attachment containing a VBA macro. Oletools categorizes the macro risk as 'high'.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • file.oletools(.).indicators.vba_macros.risk == "high"
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.oletools, profile.by_sender. Reference lists: $file_extensions_macros.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
      file.oletools func_call "file.oletools(.).indicators.vba_macros.risk == \"high\""
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

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"

Attachment with macro calling executable

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

Recursively scans files and archives to detect embedded VBA files with an encoded hex string referencing an exe. This may be an attempt to heavily obfuscate an execution through Microsoft document.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Macros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or .file_extension in~ $file_extensions_common_archives
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.), any(.scan.vba.hex, strings.ilike(., "*exe*")))
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect embedded VBA files with an encoded hex string referencing an exe. This may be an attempt to heavily obfuscate an execution through Microsoft document.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), any(.scan.vba.hex, strings.ilike(., "*exe*")))

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
strings.ilikesubstring*exe*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.), any(.scan.vba.hex, strings.ilike(., \"*exe*\")))"
  type.inbound eq "true"

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"

Attachment with suspicious author (unsolicited)

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

Recursively scans files and archives to detect embedded docx files with a specific author.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("doc", "docm", "docx", "dot", "dotm")
          or .file_extension in~ $file_extensions_common_archives
        )
        and any(file.explode(.), strings.ilike(.scan.docx.author, "root"))
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect embedded docx files with a specific author.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('doc', 'docm', 'docx', 'dot', 'dotm')
      • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), strings.ilike(.scan.docx.author, "root"))
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, profile.by_sender, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberdoc
attachments[].file_extensionmemberdocm
attachments[].file_extensionmemberdocx
attachments[].file_extensionmemberdot
attachments[].file_extensionmemberdotm
strings.ilikesubstringroot

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["doc", "docm", "docx", "dot", "dotm"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.), strings.ilike(.scan.docx.author, \"root\"))"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

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"

Attachment with unscannable encrypted zip

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

Recursively scans files and archives to detect embedded ZIP files that are encrypted and could not be opened/scanned.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEncryption, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (.file_type == "zip" or .file_extension == "zip")
        and any(file.explode(.),
                any(.flavors.yara, . == 'encrypted_zip')
                and .scan.encrypted_zip.cracked_password == null
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect embedded ZIP files that are encrypted and could not be opened/scanned.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'zip'
      • .file_extension is 'zip'
    • any(file.explode(.), any(.flavors.yara, . == 'encrypted_zip') and .scan.encrypted_zip.cracked_password == null )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalszip
attachments[].file_extensionequalszip
file.explode(attachments[])[].flavors.yara[]equalsencrypted_zip

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension eq "zip"
        attachments.file_type eq "zip"
       macro "any(file.explode(.),\n                any(.flavors.yara, . == 'encrypted_zip')\n                and .scan.encrypted_zip.cracked_password == null\n        )"
  type.inbound eq "true"

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"

Attachment with VBA macros from employee impersonation (unsolicited)

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

Attachment contains a VBA macro from a sender your organization has never sent an email to. Sender is using a display name that matches the display name of someone in your organization. VBA macros are a common phishing technique used to deploy malware.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesImpersonation: Employee, Macros, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound

// ensure the display name contains a space to avoid single named process accounts eg. 'billing, payment'
and strings.contains(sender.display_name, " ")
and sender.display_name in~ $org_display_names
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or .file_extension in~ $file_extensions_common_archives
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and file.oletools(.).indicators.vba_macros.exists
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Attachment contains a VBA macro from a sender your organization has never sent an email to. Sender is using a display name that matches the display name of someone in your organization. VBA macros are a common phishing technique used to deploy malware.

  1. inbound message
  2. sender.display_name contains ' '
  3. sender.display_name in $org_display_names
  4. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • file.oletools(.).indicators.vba_macros.exists
  5. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, sender.display_name, type.inbound. Sensors: file.oletools, profile.by_sender, strings.contains. Reference lists: $file_extensions_common_archives, $file_extensions_macros, $org_display_names.

Indicators Matched (3)

FieldMatchValue
strings.containssubstring
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
      file.oletools func_call "file.oletools(.).indicators.vba_macros.exists"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  sender.display_name contains " "
  sender.display_name macro "sender.display_name in org_display_names"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

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

Attachment: .csproj with suspicious commands

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

Attached .csproj file contains suspicious commands.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension == "csproj"
        and any(file.explode(.),
                (
                  (any(.scan.strings.strings, strings.contains(., 'DllImport')))
                  and (
                    any(.scan.strings.strings,
                        strings.icontains(., 'CreateProcess')
                    )
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

Attached .csproj file contains suspicious commands.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension is 'csproj'
    • any(file.explode(.), ( (any(.scan.strings.strings, strings.contains(., 'DllImport'))) and ( any(.scan.strings.strings, strings.icontains(., 'CreateProcess') ) ) ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, strings.contains, strings.icontains.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionequalscsproj
strings.containssubstringDllImport
strings.icontainssubstringCreateProcess

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension eq "csproj"
       macro "any(file.explode(.),\n                (\n                  (any(.scan.strings.strings, strings.contains(., 'DllImport')))\n                  and (\n                    any(.scan.strings.strings,\n                        strings.icontains(., 'CreateProcess')\n                    )\n                  )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: 7z Archive Containing RAR File

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

Detects 7z archive attachments that contain RAR files, which may be used to evade detection by nesting compressed file formats.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_common_archives
          and .file_type == "7z"
        )
        and any(file.expand_archives(.).files, .file_type == "rar")
)

Detection Logic

Scope: inbound message.

Detects 7z archive attachments that contain RAR files, which may be used to evade detection by nesting compressed file formats.

  1. inbound message
  2. any of attachments where all hold:
    • all of:
      • .file_extension in $file_extensions_common_archives
      • .file_type is '7z'
    • any(file.expand_archives(.).files, .file_type == "rar")

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.expand_archives. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequals7z
file.expand_archives(attachments[]).files[].file_typeequalsrar

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
      attachments.file_type eq "7z"
       macro "any(file.expand_archives(.).files, .file_type == \"rar\")"
  type.inbound eq "true"

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"

Attachment: Adobe image lure in body or attachment with suspicious link

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

Detects Adobe phishing messages with an Adobe logo in the body or attachment, with suspicious link language.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImage as content, Impersonation: Brand

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.html
  • body.links
  • headers
  • headers.auth_summary
  • headers.hops
  • recipients
  • recipients.cc
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and (
  // all images
  length(filter(attachments, .file_type not in $file_types_images)) == 0
  // only pdf attachments
  or length(filter(attachments, .file_type != "pdf")) == 0
  // pdf and image attachements where images are all embedded into the message body
  or length(filter(attachments,
                   .file_type == 'pdf'
                   or (
                     .file_type in $file_types_images
                     and strings.icontains(body.html.raw,
                                           strings.concat("cid:", .content_id)
                     )
                   )
            )
  ) == length(attachments)
)
and (
  (
    any(ml.logo_detect(file.message_screenshot()).brands, .name == "Adobe")
    and 0 < length(body.links) < 10
    and any(body.links, .display_text is null)
    and (
      length(filter(body.links,
                    (
                      .display_text is null
                      and .display_url.url == sender.email.domain.root_domain
                    )
                    or .href_url.domain.root_domain in (
                      "aka.ms",
                      "mimecast.com",
                      "mimecastprotect.com",
                      "cisco.com"
                    )
             )
      ) != length(body.links)
    )
  )
  or any(filter(attachments,
                // filter down to attachments with adobe logo
                any(ml.logo_detect(.).brands,
                    .name == "Adobe" and .confidence in ("medium", "high")
                )
         ),
         // the attachment (or message body) contain links
         any(file.explode(.),
             (
               length(.scan.url.urls) > 0
               or length(.scan.pdf.urls) > 0
               or length(body.links) > 0
             )
         )
  )
)
and (
  (
    (length(headers.references) > 0 or headers.in_reply_to is null)
    and not (
      (
        strings.istarts_with(subject.subject, "RE:")
        or strings.istarts_with(subject.subject, "RES:")
        or strings.istarts_with(subject.subject, "R:")
        or strings.istarts_with(subject.subject, "ODG:")
        or strings.istarts_with(subject.subject, "答复:")
        or strings.istarts_with(subject.subject, "AW:")
        or strings.istarts_with(subject.subject, "TR:")
        or strings.istarts_with(subject.subject, "FWD:")
        or regex.imatch(subject.subject, '(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:')
      )
    )
  )
  or length(headers.references) == 0
)

// not a newsletter or advertisement
and not any(headers.hops, any(.fields, .name == "List-Unsubscribe-Post"))
and not any(ml.nlu_classifier(body.current_thread.text).topics,
            .name in ("Advertising and Promotions", "Newsletters and Digests")
            and .confidence == "high"
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  // exclude solicited senders
  not profile.by_sender_email().solicited
  or profile.by_sender_email().prevalence == "new"
  or length(recipients.to) == 0
  // domains for recipients to/cc must be valid
  or (
    all(recipients.to, .email.domain.valid == false)
    and all(recipients.cc, .email.domain.valid == false)
  )
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
)
and not profile.by_sender_email().any_messages_benign

Detection Logic

Scope: inbound message.

Detects Adobe phishing messages with an Adobe logo in the body or attachment, with suspicious link language.

  1. inbound message
  2. any of:
    • length(filter(attachments, .file_type not in $file_types_images)) == 0
    • length(filter(attachments, .file_type != "pdf")) == 0
    • length(filter(attachments, .file_type == 'pdf' or ( .file_type in $file_types_images and strings.icontains(body.html.raw, strings.concat("cid:", .content_id) ) ) ) ) == length(attachments)
  3. any of:
    • all of:
      • any(ml.logo_detect(file.message_screenshot()).brands, .name == "Adobe")
      • all of:
        • (0) < (length(body.links))
        • (length(body.links)) < (10)
      • any of body.links where:
        • .display_text is missing
      • ( length(filter(body.links, ( .display_text is null and .display_url.url == sender.email.domain.root_domain ) or .href_url.domain.root_domain in ( "aka.ms", "mimecast.com", "mimecastprotect.com", "cisco.com" ) ) ) != length(body.links) )
    • any(filter(attachments, // filter down to attachments with adobe logo any(ml.logo_detect(.).brands, .name == "Adobe" and .confidence in ("medium", "high") ) ), // the attachment (or message body) contain links any(file.explode(.), ( length(.scan.url.urls) > 0 or length(.scan.pdf.urls) > 0 or length(body.links) > 0 ) ) )
  4. any of:
    • all of:
      • any of:
        • length(headers.references) > 0
        • headers.in_reply_to is missing
      • none of:
        • subject.subject starts with 'RE:'
        • subject.subject starts with 'RES:'
        • subject.subject starts with 'R:'
        • subject.subject starts with 'ODG:'
        • subject.subject starts with '答复:'
        • subject.subject starts with 'AW:'
        • subject.subject starts with 'TR:'
        • subject.subject starts with 'FWD:'
        • subject.subject matches '(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?)\\s?:'
    • length(headers.references) == 0
  5. not:
    • any of headers.hops where:
      • any of .fields where:
        • .name is 'List-Unsubscribe-Post'
  6. not:
    • any(ml.nlu_classifier(body.current_thread.text).topics, .name in ("Advertising and Promotions", "Newsletters and Digests") and .confidence == "high" )
  7. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  8. any of:
    • not:
      • profile.by_sender_email().solicited
    • profile.by_sender_email().prevalence == "new"
    • length(recipients.to) == 0
    • all of:
      • all of recipients.to where:
        • .email.domain.valid is False
      • all of recipients.cc where:
        • .email.domain.valid is False
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
  9. not:
    • profile.by_sender_email().any_messages_benign

Inspects: attachments[].content_id, attachments[].file_type, body.current_thread.text, body.html.raw, body.links, body.links[].display_text, body.links[].display_url.url, body.links[].href_url.domain.root_domain, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, headers.in_reply_to, headers.references, recipients.cc, recipients.cc[].email.domain.valid, recipients.to, recipients.to[].email.domain.valid, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, file.message_screenshot, ml.logo_detect, ml.nlu_classifier, profile.by_sender_email, regex.imatch, strings.concat, strings.icontains, strings.istarts_with. Reference lists: $file_types_images, $high_trust_sender_root_domains.

Indicators Matched (9)

FieldMatchValue
attachments[].file_typeequalspdf
ml.logo_detect(file.message_screenshot()).brands[].nameequalsAdobe
body.links[].href_url.domain.root_domainmemberaka.ms
body.links[].href_url.domain.root_domainmembermimecast.com
body.links[].href_url.domain.root_domainmembermimecastprotect.com
body.links[].href_url.domain.root_domainmembercisco.com
ml.logo_detect(attachments[]).brands[].nameequalsAdobe
ml.logo_detect(attachments[]).brands[].confidencemembermedium
ml.logo_detect(attachments[]).brands[].confidencememberhigh

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        or
          subject.subject regex_match "(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?)\\s?:"
          subject.subject starts_with "AW:"
          subject.subject starts_with "FWD:"
          subject.subject starts_with "ODG:"
          subject.subject starts_with "R:"
          subject.subject starts_with "RE:"
          subject.subject starts_with "RES:"
          subject.subject starts_with "TR:"
          subject.subject starts_with "答复:"
      or
        headers.in_reply_to is_null
        headers.references length_compare "0"
    headers.references length_compare "0"
  or
    and
      any(body.links)
        body.links.display_text is_null
      body.links length_compare "0"
      body.links length_compare "10"
      length func_call "(\n      length(filter(body.links,\n                    (\n                      .display_text is null\n                      and .display_url.url == sender.email.domain.root_domain\n                    )\n                    or .href_url.domain.root_domain in (\n                      \"aka.ms\",\n                      \"mimecast.com\",\n                      \"mimecastprotect.com\",\n                      \"cisco.com\"\n                    )\n             )\n      ) != length(body.links)\n    )"
       macro "any(ml.logo_detect(file.message_screenshot()).brands, .name == \"Adobe\")"
     macro "any(filter(attachments,\n                // filter down to attachments with adobe logo\n                any(ml.logo_detect(.).brands,\n                    .name == \"Adobe\" and .confidence in (\"medium\", \"high\")\n                )\n         ),\n         // the attachment (or message body) contain links\n         any(file.explode(.),\n             (\n               length(.scan.url.urls) > 0\n               or length(.scan.pdf.urls) > 0\n               or length(body.links) > 0\n             )\n         )\n  )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    any(headers.hops)
      any(headers.hops.fields)
        headers.hops.fields.name eq "List-Unsubscribe-Post"
  or
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    not
      profile.by_sender_email func_call "profile.by_sender_email().solicited"
    and
       macro "all(recipients.cc, .email.domain.valid == false)"
       macro "all(recipients.to, .email.domain.valid == false)"
    profile.by_sender_email func_call "profile.by_sender_email().prevalence == \"new\""
    recipients.to length_compare "0"
  or
    length func_call "length(filter(attachments, .file_type != \"pdf\")) == 0"
    length func_call "length(filter(attachments, .file_type not in $file_types_images)) == 0"
    length func_call "length(filter(attachments,\n                   .file_type == 'pdf'\n                   or (\n                     .file_type in $file_types_images\n                     and strings.icontains(body.html.raw,\n                                           strings.concat(\"cid:\", .content_id)\n                     )\n                   )\n            )\n  ) == length(attachments)"
  not
    profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
  not
     macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n            .name in (\"Advertising and Promotions\", \"Newsletters and Digests\")\n            and .confidence == \"high\"\n)"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
headers.in_reply_tois_null
  • (no value, null check)
field:"headers.in_reply_to" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops

Attachment: Adobe Sign lure PDF with embedded banner images

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

Detects inbound messages containing PDF attachments that contain embedded banner images mimicking Adobe Sign branding, commonly used to deceive recipients into believing the document is legitimate.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Impersonation: Brand

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name == 'adobe_sign_lure_banner_images')
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing PDF attachments that contain embedded banner images mimicking Adobe Sign branding, commonly used to deceive recipients into believing the document is legitimate.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name == 'adobe_sign_lure_banner_images') ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalsadobe_sign_lure_banner_images

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name == 'adobe_sign_lure_banner_images')\n        )\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"

Attachment: Any .sap file (unsolicited)

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

SAP shortcut files can be abused to run unsanctioned code on endpoints. Use if receiving .sap files is not normal behavior in your environment.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments, .file_extension == "sap")
and (
  not profile.by_sender().solicited
  or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

SAP shortcut files can be abused to run unsanctioned code on endpoints. Use if receiving .sap files is not normal behavior in your environment.

  1. inbound message
  2. any of attachments where:
    • .file_extension is 'sap'
  3. any of:
    • not:
      • profile.by_sender().solicited
    • profile.by_sender().any_messages_malicious_or_spam
  4. not:
    • profile.by_sender().any_messages_benign
  5. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].file_extension, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: profile.by_sender. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (1)

FieldMatchValue
attachments[].file_extensionequalssap

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    not
      profile.by_sender func_call "profile.by_sender().solicited"
    profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
  any(attachments)
    attachments.file_extension eq "sap"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: Any HTML file (unsolicited)

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

Potential HTML smuggling attacks in unsolicited messages. Use if passing HTML files is not normal behavior in your environment. This rule may be expanded to inspect HTML attachments for suspicious code.

Threat Classification

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

CategoryValues
Tactics and techniquesHTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in~ ('htm', 'html') or .file_type == "html"
)
and (
  not profile.by_sender().solicited
  or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign

// negate highly trusted sender domains unless they fail DMARC authentication or DMARC is missing
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.

Potential HTML smuggling attacks in unsolicited messages. Use if passing HTML files is not normal behavior in your environment. This rule may be expanded to inspect HTML attachments for suspicious code.

  1. inbound message
  2. any of attachments where any holds:
    • .file_extension in ('htm', 'html')
    • .file_type is 'html'
  3. any of:
    • not:
      • profile.by_sender().solicited
    • profile.by_sender().any_messages_malicious_or_spam
  4. not:
    • profile.by_sender().any_messages_benign
  5. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: profile.by_sender. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionmemberhtm
attachments[].file_extensionmemberhtml
attachments[].file_typeequalshtml

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      attachments.file_extension in ["htm", "html"]
      attachments.file_type eq "html"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  or
    not
      profile.by_sender func_call "profile.by_sender().solicited"
    profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: Any HTML file (untrusted sender)

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

Potential HTML smuggling attacks from new senders. Use if passing HTML files is not normal behavior in your environment. This rule may be expanded to inspect HTML attachments for suspicious code.

Threat Classification

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

CategoryValues
Tactics and techniquesHTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in~ ('htm', 'html') or .file_type == "html"
)
and (
  (
    profile.by_sender().prevalence in ("new", "outlier")
    and not profile.by_sender().solicited
  )
  or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign

// negate highly trusted sender domains unless they fail DMARC authentication or DMARC is missing
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.

Potential HTML smuggling attacks from new senders. Use if passing HTML files is not normal behavior in your environment. This rule may be expanded to inspect HTML attachments for suspicious code.

  1. inbound message
  2. any of attachments where any holds:
    • .file_extension in ('htm', 'html')
    • .file_type is 'html'
  3. any of:
    • all of:
      • profile.by_sender().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender().solicited
    • profile.by_sender().any_messages_malicious_or_spam
  4. not:
    • profile.by_sender().any_messages_benign
  5. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: profile.by_sender. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionmemberhtm
attachments[].file_extensionmemberhtml
attachments[].file_typeequalshtml

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().solicited"
      profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
    profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
  any(attachments)
    or
      attachments.file_extension in ["htm", "html"]
      attachments.file_type eq "html"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: Any HTML file within archive (unsolicited)

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

Recursively scans archives to detect HTML files from unsolicited senders. HTML files can be used for HTML smuggling and embedded in archives to evade detection.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in~ $file_extensions_common_archives
        and any(file.explode(.),
                .depth > 0 and .file_extension in~ ("html", "htm")
        )
)
and (
  not profile.by_sender().solicited
  or (profile.by_sender().any_messages_malicious_or_spam)
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Recursively scans archives to detect HTML files from unsolicited senders. HTML files can be used for HTML smuggling and embedded in archives to evade detection.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), .depth > 0 and .file_extension in~ ("html", "htm") )
  3. any of:
    • not:
      • profile.by_sender().solicited
    • (profile.by_sender().any_messages_malicious_or_spam)
  4. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, profile.by_sender. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
file.explode(attachments[])[].file_extensionmemberhtml
file.explode(attachments[])[].file_extensionmemberhtm

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.),\n                .depth > 0 and .file_extension in~ (\"html\", \"htm\")\n        )"
  or
    not
      profile.by_sender func_call "profile.by_sender().solicited"
    profile.by_sender func_call "(profile.by_sender().any_messages_malicious_or_spam)"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: Archive containing disallowed file type

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

Recursively scans archives to detect disallowed file types. File extensions can be detected within password-protected archives. Attackers often embed malicious files within archives to bypass email gateway controls.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_common_archives
          or .file_type == "rar"
        )
        and any(file.explode(.),
                .file_extension in~ (
                  // File types blocked by Gmail by default
                  // https://support.google.com/mail/answer/6590?hl=en#zippy=%2Cmessages-that-have-attachments
                  "ade",
                  "adp",
                  "apk",
                  "appx",
                  "appxbundle",
                  "bat",
                  "cab",
                  "chm",
                  "cmd",
                  "com",
                  "cpl",
                  "dll",
                  "dmg",
                  "ex",
                  "ex_",
                  "exe",
                  "hta",
                  "ins",
                  "isp",
                  "iso",
                  "jar",
                  "js",
                  "jse",
                  "lib",
                  "lnk",
                  "mde",
                  "msc",
                  "msi",
                  "msix",
                  "msixbundle",
                  "msp",
                  "mst",
                  "nsh",
                  "pif",
                  "ps1",
                  "scr",
                  "sct",
                  "shb",
                  "sys",
                  "vb",
                  "vbe",
                  "vbs",
                  "vxd",
                  "wsc",
                  "wsf",
                  "wsh",

                  // File types blocked by Microsoft 365 by default
                  // https://support.microsoft.com/en-us/office/blocked-attachments-in-outlook-434752e1-02d3-4e90-9124-8b81e49a8519
                  "ade",
                  "adp",
                  "app",
                  "application",
                  "appref-ms",
                  "asp",
                  "aspx",
                  "asx",
                  // "bas", excluded at depth > 1 because they can exist natively in word docs within an archive. see below
                  "bat",
                  "bgi",
                  "cab",
                  // "cer",
                  "chm",
                  "cmd",
                  "cnt",
                  "com",
                  "cpl",
                  // "crt",
                  // "csh",
                  // "der",
                  "diagcab",
                  "exe",
                  "fxp",
                  "gadget",
                  // "grp",
                  "hlp",
                  "hpj",
                  "hta",
                  "htc",
                  // "inf",
                  "ins",
                  "iso",
                  "isp",
                  "its",
                  "jar",
                  "jnlp",
                  "js",
                  "jse",
                  "ksh",
                  "lnk",
                  "mad",
                  "maf",
                  "mag",
                  "mam",
                  "maq",
                  "mar",
                  "mas",
                  "mat",
                  "mau",
                  "mav",
                  "maw",
                  "mcf",
                  "mda",
                  // "mdb",
                  "mde",
                  "mdt",
                  "mdw",
                  "mdz",
                  "msc",
                  "msh",
                  "msh1",
                  "msh2",
                  "mshxml",
                  "msh1xml",
                  "msh2xml",
                  "msi",
                  "msp",
                  "mst",
                  "msu",
                  "ops",
                  "osd",
                  "pcd",
                  "pif",
                  "pl",
                  "plg",
                  "prf",
                  "prg",
                  "printerexport",
                  "ps1",
                  "ps1xml",
                  "ps2",
                  "ps2xml",
                  "psc1",
                  "psc2",
                  "psd1",
                  "psdm1",
                  "pst",
                  // "py",
                  // "pyc",
                  "pyo",
                  "pyw",
                  "pyz",
                  "pyzw",
                  "reg",
                  "scf",
                  "scr",
                  "sct",
                  "shb",
                  "shs",
                  "theme",
                  // "tmp",
                  "url",
                  "vb",
                  "vbe",
                  "vbp",
                  "vbs",
                  "vhd",
                  "vhdx",
                  "vsmacros",
                  "vsw",
                  "webpnp",
                  "website",
                  "ws",
                  "wsc",
                  "wsf",
                  "wsh",
                  "xbap",
                  "xll",
                  "xnk"
                )
                or (
                  // BASIC files can naturally occur in word docs,
                  // so only flag if depth is 1 (archive -> bas, not archive -> doc -> bas)
                  .depth == 1
                  and .file_extension =~ "bas"
                )
        )
)
and (
  profile.by_sender().prevalence in ("new", "outlier")
  or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Recursively scans archives to detect disallowed file types. File extensions can be detected within password-protected archives. Attackers often embed malicious files within archives to bypass email gateway controls.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'rar'
    • any(file.explode(.), .file_extension in~ ( // File types blocked by Gmail by default // https://support.google.com/mail/answer/6590?hl=en#zippy=%2Cmessages-that-have-attachments "ade", "adp", "apk", "appx", "appxbundle", "bat", "cab", "chm", "cmd", "com", "cpl", "dll", "dmg", "ex", "ex_", "exe", "hta", "ins", "isp", "iso", "jar", "js", "jse", "lib", "lnk", "mde", "msc", "msi", "msix", "msixbundle", "msp", "mst", "nsh", "pif", "ps1", "scr", "sct", "shb", "sys", "vb", "vbe", "vbs", "vxd", "wsc", "wsf", "wsh", // File types blocked by Microsoft 365 by default // https://support.microsoft.com/en-us/office/blocked-attachments-in-outlook-434752e1-02d3-4e90-9124-8b81e49a8519 "ade", "adp", "app", "application", "appref-ms", "asp", "aspx", "asx", // "bas", excluded at depth > 1 because they can exist natively in word docs within an archive. see below "bat", "bgi", "cab", // "cer", "chm", "cmd", "cnt", "com", "cpl", // "crt", // "csh", // "der", "diagcab", "exe", "fxp", "gadget", // "grp", "hlp", "hpj", "hta", "htc", // "inf", "ins", "iso", "isp", "its", "jar", "jnlp", "js", "jse", "ksh", "lnk", "mad", "maf", "mag", "mam", "maq", "mar", "mas", "mat", "mau", "mav", "maw", "mcf", "mda", // "mdb", "mde", "mdt", "mdw", "mdz", "msc", "msh", "msh1", "msh2", "mshxml", "msh1xml", "msh2xml", "msi", "msp", "mst", "msu", "ops", "osd", "pcd", "pif", "pl", "plg", "prf", "prg", "printerexport", "ps1", "ps1xml", "ps2", "ps2xml", "psc1", "psc2", "psd1", "psdm1", "pst", // "py", // "pyc", "pyo", "pyw", "pyz", "pyzw", "reg", "scf", "scr", "sct", "shb", "shs", "theme", // "tmp", "url", "vb", "vbe", "vbp", "vbs", "vhd", "vhdx", "vsmacros", "vsw", "webpnp", "website", "ws", "wsc", "wsf", "wsh", "xbap", "xll", "xnk" ) or ( // BASIC files can naturally occur in word docs, // so only flag if depth is 1 (archive -> bas, not archive -> doc -> bas) .depth == 1 and .file_extension =~ "bas" ) )
  3. any of:
    • profile.by_sender().prevalence in ("new", "outlier")
    • profile.by_sender().any_messages_malicious_or_spam
  4. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, profile.by_sender. Reference lists: $file_extensions_common_archives.

Indicators Matched (124)

FieldMatchValue
attachments[].file_typeequalsrar
file.explode(attachments[])[].file_extensionmemberade
file.explode(attachments[])[].file_extensionmemberadp
file.explode(attachments[])[].file_extensionmemberapk
file.explode(attachments[])[].file_extensionmemberappx
file.explode(attachments[])[].file_extensionmemberappxbundle
file.explode(attachments[])[].file_extensionmemberbat
file.explode(attachments[])[].file_extensionmembercab
file.explode(attachments[])[].file_extensionmemberchm
file.explode(attachments[])[].file_extensionmembercmd
file.explode(attachments[])[].file_extensionmembercom
file.explode(attachments[])[].file_extensionmembercpl
112 more
file.explode(attachments[])[].file_extensionmemberdll
file.explode(attachments[])[].file_extensionmemberdmg
file.explode(attachments[])[].file_extensionmemberex
file.explode(attachments[])[].file_extensionmemberex_
file.explode(attachments[])[].file_extensionmemberexe
file.explode(attachments[])[].file_extensionmemberhta
file.explode(attachments[])[].file_extensionmemberins
file.explode(attachments[])[].file_extensionmemberisp
file.explode(attachments[])[].file_extensionmemberiso
file.explode(attachments[])[].file_extensionmemberjar
file.explode(attachments[])[].file_extensionmemberjs
file.explode(attachments[])[].file_extensionmemberjse
file.explode(attachments[])[].file_extensionmemberlib
file.explode(attachments[])[].file_extensionmemberlnk
file.explode(attachments[])[].file_extensionmembermde
file.explode(attachments[])[].file_extensionmembermsc
file.explode(attachments[])[].file_extensionmembermsi
file.explode(attachments[])[].file_extensionmembermsix
file.explode(attachments[])[].file_extensionmembermsixbundle
file.explode(attachments[])[].file_extensionmembermsp
file.explode(attachments[])[].file_extensionmembermst
file.explode(attachments[])[].file_extensionmembernsh
file.explode(attachments[])[].file_extensionmemberpif
file.explode(attachments[])[].file_extensionmemberps1
file.explode(attachments[])[].file_extensionmemberscr
file.explode(attachments[])[].file_extensionmembersct
file.explode(attachments[])[].file_extensionmembershb
file.explode(attachments[])[].file_extensionmembersys
file.explode(attachments[])[].file_extensionmembervb
file.explode(attachments[])[].file_extensionmembervbe
file.explode(attachments[])[].file_extensionmembervbs
file.explode(attachments[])[].file_extensionmembervxd
file.explode(attachments[])[].file_extensionmemberwsc
file.explode(attachments[])[].file_extensionmemberwsf
file.explode(attachments[])[].file_extensionmemberwsh
file.explode(attachments[])[].file_extensionmemberapp
file.explode(attachments[])[].file_extensionmemberapplication
file.explode(attachments[])[].file_extensionmemberappref-ms
file.explode(attachments[])[].file_extensionmemberasp
file.explode(attachments[])[].file_extensionmemberaspx
file.explode(attachments[])[].file_extensionmemberasx
file.explode(attachments[])[].file_extensionmemberbgi
file.explode(attachments[])[].file_extensionmembercnt
file.explode(attachments[])[].file_extensionmemberdiagcab
file.explode(attachments[])[].file_extensionmemberfxp
file.explode(attachments[])[].file_extensionmembergadget
file.explode(attachments[])[].file_extensionmemberhlp
file.explode(attachments[])[].file_extensionmemberhpj
file.explode(attachments[])[].file_extensionmemberhtc
file.explode(attachments[])[].file_extensionmemberits
file.explode(attachments[])[].file_extensionmemberjnlp
file.explode(attachments[])[].file_extensionmemberksh
file.explode(attachments[])[].file_extensionmembermad
file.explode(attachments[])[].file_extensionmembermaf
file.explode(attachments[])[].file_extensionmembermag
file.explode(attachments[])[].file_extensionmembermam
file.explode(attachments[])[].file_extensionmembermaq
file.explode(attachments[])[].file_extensionmembermar
file.explode(attachments[])[].file_extensionmembermas
file.explode(attachments[])[].file_extensionmembermat
file.explode(attachments[])[].file_extensionmembermau
file.explode(attachments[])[].file_extensionmembermav
file.explode(attachments[])[].file_extensionmembermaw
file.explode(attachments[])[].file_extensionmembermcf
file.explode(attachments[])[].file_extensionmembermda
file.explode(attachments[])[].file_extensionmembermdt
file.explode(attachments[])[].file_extensionmembermdw
file.explode(attachments[])[].file_extensionmembermdz
file.explode(attachments[])[].file_extensionmembermsh
file.explode(attachments[])[].file_extensionmembermsh1
file.explode(attachments[])[].file_extensionmembermsh2
file.explode(attachments[])[].file_extensionmembermshxml
file.explode(attachments[])[].file_extensionmembermsh1xml
file.explode(attachments[])[].file_extensionmembermsh2xml
file.explode(attachments[])[].file_extensionmembermsu
file.explode(attachments[])[].file_extensionmemberops
file.explode(attachments[])[].file_extensionmemberosd
file.explode(attachments[])[].file_extensionmemberpcd
file.explode(attachments[])[].file_extensionmemberpl
file.explode(attachments[])[].file_extensionmemberplg
file.explode(attachments[])[].file_extensionmemberprf
file.explode(attachments[])[].file_extensionmemberprg
file.explode(attachments[])[].file_extensionmemberprinterexport
file.explode(attachments[])[].file_extensionmemberps1xml
file.explode(attachments[])[].file_extensionmemberps2
file.explode(attachments[])[].file_extensionmemberps2xml
file.explode(attachments[])[].file_extensionmemberpsc1
file.explode(attachments[])[].file_extensionmemberpsc2
file.explode(attachments[])[].file_extensionmemberpsd1
file.explode(attachments[])[].file_extensionmemberpsdm1
file.explode(attachments[])[].file_extensionmemberpst
file.explode(attachments[])[].file_extensionmemberpyo
file.explode(attachments[])[].file_extensionmemberpyw
file.explode(attachments[])[].file_extensionmemberpyz
file.explode(attachments[])[].file_extensionmemberpyzw
file.explode(attachments[])[].file_extensionmemberreg
file.explode(attachments[])[].file_extensionmemberscf
file.explode(attachments[])[].file_extensionmembershs
file.explode(attachments[])[].file_extensionmembertheme
file.explode(attachments[])[].file_extensionmemberurl
file.explode(attachments[])[].file_extensionmembervbp
file.explode(attachments[])[].file_extensionmembervhd
file.explode(attachments[])[].file_extensionmembervhdx
file.explode(attachments[])[].file_extensionmembervsmacros
file.explode(attachments[])[].file_extensionmembervsw
file.explode(attachments[])[].file_extensionmemberwebpnp
file.explode(attachments[])[].file_extensionmemberwebsite
file.explode(attachments[])[].file_extensionmemberws
file.explode(attachments[])[].file_extensionmemberxbap
file.explode(attachments[])[].file_extensionmemberxll
file.explode(attachments[])[].file_extensionmemberxnk
file.explode(attachments[])[].file_extensionequalsbas

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "rar"
       macro "any(file.explode(.),\n                .file_extension in~ (\n                  // File types blocked by Gmail by default\n                  // https://support.google.com/mail/answer/6590?hl=en#zippy=%2Cmessages-that-have-attachments\n                  \"ade\",\n                  \"adp\",\n                  \"apk\",\n                  \"appx\",\n                  \"appxbundle\",\n                  \"bat\",\n                  \"cab\",\n                  \"chm\",\n                  \"cmd\",\n                  \"com\",\n                  \"cpl\",\n                  \"dll\",\n                  \"dmg\",\n                  \"ex\",\n                  \"ex_\",\n                  \"exe\",\n                  \"hta\",\n                  \"ins\",\n                  \"isp\",\n                  \"iso\",\n                  \"jar\",\n                  \"js\",\n                  \"jse\",\n                  \"lib\",\n                  \"lnk\",\n                  \"mde\",\n                  \"msc\",\n                  \"msi\",\n                  \"msix\",\n                  \"msixbundle\",\n                  \"msp\",\n                  \"mst\",\n                  \"nsh\",\n                  \"pif\",\n                  \"ps1\",\n                  \"scr\",\n                  \"sct\",\n                  \"shb\",\n                  \"sys\",\n                  \"vb\",\n                  \"vbe\",\n                  \"vbs\",\n                  \"vxd\",\n                  \"wsc\",\n                  \"wsf\",\n                  \"wsh\",\n\n                  // File types blocked by Microsoft 365 by default\n                  // https://support.microsoft.com/en-us/office/blocked-attachments-in-outlook-434752e1-02d3-4e90-9124-8b81e49a8519\n                  \"ade\",\n                  \"adp\",\n                  \"app\",\n                  \"application\",\n                  \"appref-ms\",\n                  \"asp\",\n                  \"aspx\",\n                  \"asx\",\n                  // \"bas\", excluded at depth > 1 because they can exist natively in word docs within an archive. see below\n                  \"bat\",\n                  \"bgi\",\n                  \"cab\",\n                  // \"cer\",\n                  \"chm\",\n                  \"cmd\",\n                  \"cnt\",\n                  \"com\",\n                  \"cpl\",\n                  // \"crt\",\n                  // \"csh\",\n                  // \"der\",\n                  \"diagcab\",\n                  \"exe\",\n                  \"fxp\",\n                  \"gadget\",\n                  // \"grp\",\n                  \"hlp\",\n                  \"hpj\",\n                  \"hta\",\n                  \"htc\",\n                  // \"inf\",\n                  \"ins\",\n                  \"iso\",\n                  \"isp\",\n                  \"its\",\n                  \"jar\",\n                  \"jnlp\",\n                  \"js\",\n                  \"jse\",\n                  \"ksh\",\n                  \"lnk\",\n                  \"mad\",\n                  \"maf\",\n                  \"mag\",\n                  \"mam\",\n                  \"maq\",\n                  \"mar\",\n                  \"mas\",\n                  \"mat\",\n                  \"mau\",\n                  \"mav\",\n                  \"maw\",\n                  \"mcf\",\n                  \"mda\",\n                  // \"mdb\",\n                  \"mde\",\n                  \"mdt\",\n                  \"mdw\",\n                  \"mdz\",\n                  \"msc\",\n                  \"msh\",\n                  \"msh1\",\n                  \"msh2\",\n                  \"mshxml\",\n                  \"msh1xml\",\n                  \"msh2xml\",\n                  \"msi\",\n                  \"msp\",\n                  \"mst\",\n                  \"msu\",\n                  \"ops\",\n                  \"osd\",\n                  \"pcd\",\n                  \"pif\",\n                  \"pl\",\n                  \"plg\",\n                  \"prf\",\n                  \"prg\",\n                  \"printerexport\",\n                  \"ps1\",\n                  \"ps1xml\",\n                  \"ps2\",\n                  \"ps2xml\",\n                  \"psc1\",\n                  \"psc2\",\n                  \"psd1\",\n                  \"psdm1\",\n                  \"pst\",\n                  // \"py\",\n                  // \"pyc\",\n                  \"pyo\",\n                  \"pyw\",\n                  \"pyz\",\n                  \"pyzw\",\n                  \"reg\",\n                  \"scf\",\n                  \"scr\",\n                  \"sct\",\n                  \"shb\",\n                  \"shs\",\n                  \"theme\",\n                  // \"tmp\",\n                  \"url\",\n                  \"vb\",\n                  \"vbe\",\n                  \"vbp\",\n                  \"vbs\",\n                  \"vhd\",\n                  \"vhdx\",\n                  \"vsmacros\",\n                  \"vsw\",\n                  \"webpnp\",\n                  \"website\",\n                  \"ws\",\n                  \"wsc\",\n                  \"wsf\",\n                  \"wsh\",\n                  \"xbap\",\n                  \"xll\",\n                  \"xnk\"\n                )\n                or (\n                  // BASIC files can naturally occur in word docs,\n                  // so only flag if depth is 1 (archive -> bas, not archive -> doc -> bas)\n                  .depth == 1\n                  and .file_extension =~ \"bas\"\n                )\n        )"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  or
    profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
  type.inbound eq "true"

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"

Attachment: Archive containing HTML file with file scheme link

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

Attached archive contains an HTML file with a file:// link, likely pointing to an SMB server. This technique can be used to steal NTLM hashes of users who open the HTML file. Known technique of TA577.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Exploit, HTML smuggling, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in $file_extensions_common_archives
        and any(file.explode(.),
                (
                  .file_extension in~ ("html", "htm", "shtml", "dhtml")
                  or .flavors.mime == "text/html"
                  or any(.flavors.yara, . == "html_file")
                )
                and any(.scan.url.urls, .scheme == "file")
        )
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Attached archive contains an HTML file with a file:// link, likely pointing to an SMB server. This technique can be used to steal NTLM hashes of users who open the HTML file. Known technique of TA577.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), ( .file_extension in~ ("html", "htm", "shtml", "dhtml") or .flavors.mime == "text/html" or any(.flavors.yara, . == "html_file") ) and any(.scan.url.urls, .scheme == "file") )
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, profile.by_sender. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
file.explode(attachments[])[].file_extensionmemberhtml
file.explode(attachments[])[].file_extensionmemberhtm
file.explode(attachments[])[].file_extensionmembershtml
file.explode(attachments[])[].file_extensionmemberdhtml
file.explode(attachments[])[].flavors.mimeequalstext/html
file.explode(attachments[])[].flavors.yara[]equalshtml_file
file.explode(attachments[])[].scan.url.urls[].schemeequalsfile

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.),\n                (\n                  .file_extension in~ (\"html\", \"htm\", \"shtml\", \"dhtml\")\n                  or .flavors.mime == \"text/html\"\n                  or any(.flavors.yara, . == \"html_file\")\n                )\n                and any(.scan.url.urls, .scheme == \"file\")\n        )"
  type.inbound eq "true"

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"

Attachment: Archive contains DLL-loading macro

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

An attacker could send a trusted and signed document that references an untrusted DLL file, which will be loaded by the signed document.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesExploit, LNK, Macros, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_common_archives
          or .file_type == "rar"
        )
        and (
          (
            any(file.explode(.),
                .scan.zip.encrypted == false
                // zip contains a dll file
                and any(.scan.zip.all_paths, strings.icontains(., "dll"))
            )
            and any(file.explode(.),
                    // macro references a dll file
                    any(.flavors.yara, strings.like(., "vb_file"))
                    and any(.scan.strings.strings, strings.icontains(., "dll"))
            )
          )
          or any(file.explode(.), // fallback for encrypted zips
                 .scan.zip.encrypted == true
                 and any(.scan.zip.all_paths,
                         any($file_extensions_macros, strings.icontains(.., .))
                 )
                 // zip contains a dll file
                 and any(.scan.zip.all_paths, strings.icontains(., "dll"))
          )
          or (
            any(file.explode(.),
                any(.flavors.yara, strings.like(., "vb_file"))
                and any(.scan.strings.strings, strings.ilike(., "*Lib*.dll*"))
            )
            and any(file.explode(.), strings.ilike(.file_extension, "dll"))
          )
        )
)

Detection Logic

Scope: inbound message.

An attacker could send a trusted and signed document that references an untrusted DLL file, which will be loaded by the signed document.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'rar'
    • any of:
      • all of:
        • any(file.explode(.), .scan.zip.encrypted == false // zip contains a dll file and any(.scan.zip.all_paths, strings.icontains(., "dll")) )
        • any(file.explode(.), // macro references a dll file any(.flavors.yara, strings.like(., "vb_file")) and any(.scan.strings.strings, strings.icontains(., "dll")) )
      • any(file.explode(.), // fallback for encrypted zips .scan.zip.encrypted == true and any(.scan.zip.all_paths, any($file_extensions_macros, strings.icontains(.., .)) ) // zip contains a dll file and any(.scan.zip.all_paths, strings.icontains(., "dll")) )
      • all of:
        • any(file.explode(.), any(.flavors.yara, strings.like(., "vb_file")) and any(.scan.strings.strings, strings.ilike(., "*Lib*.dll*")) )
        • any(file.explode(.), strings.ilike(.file_extension, "dll"))

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.icontains, strings.ilike, strings.like. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalsrar
strings.icontainssubstringdll
strings.likesubstringvb_file
strings.ilikesubstring*Lib*.dll*
strings.ilikesubstringdll

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
           macro "any(file.explode(.), strings.ilike(.file_extension, \"dll\"))"
           macro "any(file.explode(.),\n                any(.flavors.yara, strings.like(., \"vb_file\"))\n                and any(.scan.strings.strings, strings.ilike(., \"*Lib*.dll*\"))\n            )"
        and
           macro "any(file.explode(.),\n                    // macro references a dll file\n                    any(.flavors.yara, strings.like(., \"vb_file\"))\n                    and any(.scan.strings.strings, strings.icontains(., \"dll\"))\n            )"
           macro "any(file.explode(.),\n                .scan.zip.encrypted == false\n                // zip contains a dll file\n                and any(.scan.zip.all_paths, strings.icontains(., \"dll\"))\n            )"
         macro "any(file.explode(.), // fallback for encrypted zips\n                 .scan.zip.encrypted == true\n                 and any(.scan.zip.all_paths,\n                         any($file_extensions_macros, strings.icontains(.., .))\n                 )\n                 // zip contains a dll file\n                 and any(.scan.zip.all_paths, strings.icontains(., \"dll\"))\n          )"
      or
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "rar"
  type.inbound eq "true"

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"

Attachment: Archive with embedded CHM file

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

Recursively scans files and archives to detect embedded CHM (Microsoft Compiled HTML Help) files. According to CERT-UA, on March 7, 2022, phishing attacks targeted state organizations of Ukraine using Zip files with embedded CHM documents, which themselves contained malicious VBScript inside a .htm file. The activity is associated with UNC1151, according to CERT-UA.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in~ $file_extensions_common_archives
        and any(file.explode(.), .file_extension =~ "chm")
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect embedded CHM (Microsoft Compiled HTML Help) files. According to CERT-UA, on March 7, 2022, phishing attacks targeted state organizations of Ukraine using Zip files with embedded CHM documents, which themselves contained malicious VBScript inside a .htm file. The activity is associated with UNC1151, according to CERT-UA.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), .file_extension =~ "chm")

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (1)

FieldMatchValue
file.explode(attachments[])[].file_extensionequalschm

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.), .file_extension =~ \"chm\")"
  type.inbound eq "true"

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"

Attachment: Archive with embedded EXE file

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

Recursively scans files and archives to detect embedded EXE files (with an MZ header). According to The Record, on June 7, 2021, the Ukrainian Secret Service attributed an attack that used this technique to the "special services of the Russian Federation". The spear-phishing operation urged recipients to download a RAR archive included in the email, which, when decompressed, would drop an EXE file with a double extension (filename.pdf.exe) that tried to pass as a PDF file.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_common_archives
          or .file_type == "rar"
        )
        and any(file.explode(.),
                // the YARA scanner alone can be a bit unreliable,
                // it's matched on MZ strings in a text file before
                any(.flavors.yara, . == "mz_file")
                and strings.starts_with(.flavors.mime, "application")
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect embedded EXE files (with an MZ header). According to The Record, on June 7, 2021, the Ukrainian Secret Service attributed an attack that used this technique to the "special services of the Russian Federation". The spear-phishing operation urged recipients to download a RAR archive included in the email, which, when decompressed, would drop an EXE file with a double extension (filename.pdf.exe) that tried to pass as a PDF file.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'rar'
    • any(file.explode(.), // the YARA scanner alone can be a bit unreliable, // it's matched on MZ strings in a text file before any(.flavors.yara, . == "mz_file") and strings.starts_with(.flavors.mime, "application") )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.starts_with. Reference lists: $file_extensions_common_archives.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsrar
file.explode(attachments[])[].flavors.yara[]equalsmz_file
strings.starts_withprefixapplication

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "rar"
       macro "any(file.explode(.),\n                // the YARA scanner alone can be a bit unreliable,\n                // it's matched on MZ strings in a text file before\n                any(.flavors.yara, . == \"mz_file\")\n                and strings.starts_with(.flavors.mime, \"application\")\n        )"
  type.inbound eq "true"

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"

Attachment: Archive with pdf, txt and wsf files

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

Detects a known Qakbot delivery method, zip file with pdf, txt and wsf file at a depth of 1

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in~ $file_extensions_common_archives
        and length(distinct(filter(file.explode(.),
                                   .depth == 1
                                   and .flavors.mime in~ (
                                     "application/pdf",
                                     "text/plain"
                                   )
                            ),
                            .flavors.mime
                   )
        ) == 2
        and any(file.explode(.), .depth == 1 and .file_extension == "wsf")
)

Detection Logic

Scope: inbound message.

Detects a known Qakbot delivery method, zip file with pdf, txt and wsf file at a depth of 1

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_common_archives
    • length(distinct(filter(file.explode(.), .depth == 1 and .flavors.mime in~ ( "application/pdf", "text/plain" ) ), .flavors.mime ) ) == 2
    • any(file.explode(.), .depth == 1 and .file_extension == "wsf")

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (3)

FieldMatchValue
file.explode(attachments[])[].flavors.mimememberapplication/pdf
file.explode(attachments[])[].flavors.mimemembertext/plain
file.explode(attachments[])[].file_extensionequalswsf

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
      length func_call "length(distinct(filter(file.explode(.),\n                                   .depth == 1\n                                   and .flavors.mime in~ (\n                                     \"application/pdf\",\n                                     \"text/plain\"\n                                   )\n                            ),\n                            .flavors.mime\n                   )\n        ) == 2"
       macro "any(file.explode(.), .depth == 1 and .file_extension == \"wsf\")"
  type.inbound eq "true"

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"

Attachment: Base64 encoded bash command in filename

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

This rule detects a fileless attack technique where a malicious payload is encoded directly into a filename. This technique is used by threats like VShell. The rule is designed to find these malicious filenames both in direct attachments and within archived files (like .zip, .rar, etc.).

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEncryption, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(attachments) > 0
and any(attachments,
        (
          .file_type in $file_extensions_common_archives
          or strings.contains(.file_name, "{")
        )
        and any(file.expand_archives(.).files,
                strings.contains(.file_name, "{")
                and (
                  strings.icontains(.file_name, 'echo,')
                  or strings.icontains(.file_name, 'base64')
                  or regex.icontains(.file_name, '\bbash\b')
                  or any(beta.scan_base64(.file_name, ignore_padding=true),
                         length(.) >= 10
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

This rule detects a fileless attack technique where a malicious payload is encoded directly into a filename. This technique is used by threats like VShell. The rule is designed to find these malicious filenames both in direct attachments and within archived files (like .zip, .rar, etc.).

  1. inbound message
  2. length(attachments) > 0
  3. any of attachments where all hold:
    • any of:
      • .file_type in $file_extensions_common_archives
      • .file_name contains '{'
    • any(file.expand_archives(.).files, strings.contains(.file_name, "{") and ( strings.icontains(.file_name, 'echo,') or strings.icontains(.file_name, 'base64') or regex.icontains(.file_name, '\bbash\b') or any(beta.scan_base64(.file_name, ignore_padding=true), length(.) >= 10 ) ) )

Inspects: attachments[].file_name, attachments[].file_type, type.inbound. Sensors: beta.scan_base64, file.expand_archives, regex.icontains, strings.contains, strings.icontains. Reference lists: $file_extensions_common_archives.

Indicators Matched (4)

FieldMatchValue
strings.containssubstring{
strings.icontainssubstringecho,
strings.icontainssubstringbase64
regex.icontainsregex\bbash\b

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_name contains "{"
        attachments.file_type macro "attachments[].file_type in file_extensions_common_archives"
       macro "any(file.expand_archives(.).files,\n                strings.contains(.file_name, \"{\")\n                and (\n                  strings.icontains(.file_name, 'echo,')\n                  or strings.icontains(.file_name, 'base64')\n                  or regex.icontains(.file_name, '\\bbash\\b')\n                  or any(beta.scan_base64(.file_name, ignore_padding=true),\n                         length(.) >= 10\n                  )\n                )\n        )"
  attachments length_compare "0"
  type.inbound eq "true"

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"

Attachment: Calendar file with invisible Unicode characters

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

Detects calendar (.ics) attachments containing suspicious invisible Unicode characters, which may be used to hide malicious content or bypass security filters. The rule triggers on messages with calendar-related keywords in the subject or body.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • subject
  • type

Rule Body

type.inbound
and not subject.is_reply
and any(attachments, .file_extension in~ ('ics'))
and any(attachments,
        any(file.explode(.),
            .file_extension in~ ('ics')
            and regex.icontains(.scan.strings.raw,
                                '[\x{E0000}-\x{E007F}\x{E0100}-\x{E01EF}\x{2062}\x{2064}]{8,}'
            )
        )
)
and (
  regex.icontains(subject.subject, '(calendar|meeting|event|appointment)')
  or regex.icontains(body.current_thread.text,
                     '(calendar|meeting|event|appointment)'
  )
  or any(attachments, .content_type in~ ("text/calendar"))
)

Detection Logic

Scope: inbound message.

Detects calendar (.ics) attachments containing suspicious invisible Unicode characters, which may be used to hide malicious content or bypass security filters. The rule triggers on messages with calendar-related keywords in the subject or body.

  1. inbound message
  2. not:
    • subject.is_reply
  3. any of attachments where:
    • .file_extension in ('ics')
  4. any of attachments where:
    • any(file.explode(.), .file_extension in~ ('ics') and regex.icontains(.scan.strings.raw, '[\x{E0000}-\x{E007F}\x{E0100}-\x{E01EF}\x{2062}\x{2064}]{8,}' ) )
  5. any of:
    • subject.subject matches '(calendar|meeting|event|appointment)'
    • body.current_thread.text matches '(calendar|meeting|event|appointment)'
    • any of attachments where:
      • .content_type in ('text/calendar')

Inspects: attachments[].content_type, attachments[].file_extension, body.current_thread.text, subject.is_reply, subject.subject, type.inbound. Sensors: file.explode, regex.icontains.

Indicators Matched (5)

FieldMatchValue
attachments[].file_extensionmemberics
file.explode(attachments[])[].file_extensionmemberics
regex.icontainsregex[\x{E0000}-\x{E007F}\x{E0100}-\x{E01EF}\x{2062}\x{2064}]{8,}
regex.icontainsregex(calendar|meeting|event|appointment)
attachments[].content_typemembertext/calendar

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      attachments.content_type eq "text/calendar"
    body.current_thread.text regex_match "(calendar|meeting|event|appointment)"
    subject.subject regex_match "(calendar|meeting|event|appointment)"
  any(attachments)
    attachments.file_extension eq "ics"
  not
    subject.is_reply eq "true"
  any(attachments)
     macro "any(file.explode(.),\n            .file_extension in~ ('ics')\n            and regex.icontains(.scan.strings.raw,\n                                '[\\x{E0000}-\\x{E007F}\\x{E0100}-\\x{E01EF}\\x{2062}\\x{2064}]{8,}'\n            )\n        )"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
subject.is_replyeqtrueexcludes:subject.is_reply field:"subject.is_reply" value:"true"

Attachment: Calendar invite from recently registered domain

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

Detects calendar invites (.ics files) from organizers using domains registered within the last 90 days, which may indicate suspicious or malicious calendar invitations.

Threat Classification

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

CategoryValues
Attack typesCallback Phishing
Tactics and techniquesEvasion, ICS Phishing, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(attachments) > 0
and all(attachments, .content_type in ("text/calendar", "application/ics"))
and any(attachments,
        any(file.explode(.),
            any(.scan.ics.calendars,
                any(.components,
                    any(.organizers,
                        network.whois(.mailbox.email.domain).days_old < 90
                    )
                )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects calendar invites (.ics files) from organizers using domains registered within the last 90 days, which may indicate suspicious or malicious calendar invitations.

  1. inbound message
  2. length(attachments) > 0
  3. all of attachments where:
    • .content_type in ('text/calendar', 'application/ics')
  4. any of attachments where:
    • any(file.explode(.), any(.scan.ics.calendars, any(.components, any(.organizers, network.whois(.mailbox.email.domain).days_old < 90 ) ) ) )

Inspects: attachments[].content_type, type.inbound. Sensors: file.explode, network.whois.

Indicators Matched (2)

FieldMatchValue
attachments[].content_typemembertext/calendar
attachments[].content_typememberapplication/ics

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
     macro "any(file.explode(.),\n            any(.scan.ics.calendars,\n                any(.components,\n                    any(.organizers,\n                        network.whois(.mailbox.email.domain).days_old < 90\n                    )\n                )\n            )\n        )"
  attachments length_compare "0"
  type.inbound eq "true"
   macro "all(attachments, .content_type in (\"text/calendar\", \"application/ics\"))"

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"

Attachment: Calendar invite with Google redirect and invoice request

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

Detects calendar file attachments containing Google redirect URLs in the location field combined with invoice-related language in the message body.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, BEC/Fraud
Tactics and techniquesICS Phishing, Open redirect, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ('ics')
          or .content_type in ("application/ics", "text/calendar")
        )
        and regex.icontains(file.parse_text(.).text,
                            'LOCATION[^:]*:.{1,300}google\.com/url'
        )
)
and any(ml.nlu_classifier(body.current_thread.text).topics,
        .name == "Request to View Invoice" and .confidence == "high"
)

Detection Logic

Scope: inbound message.

Detects calendar file attachments containing Google redirect URLs in the location field combined with invoice-related language in the message body.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('ics')
      • .content_type in ('application/ics', 'text/calendar')
    • regex.icontains(file.parse_text(.).text, 'LOCATION[^:]*:.{1,300}google\.com/url' )
  3. any(ml.nlu_classifier(body.current_thread.text).topics, .name == "Request to View Invoice" and .confidence == "high" )

Inspects: attachments[].content_type, attachments[].file_extension, body.current_thread.text, type.inbound. Sensors: file.parse_text, ml.nlu_classifier, regex.icontains.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
regex.icontainsregexLOCATION[^:]*:.{1,300}google\.com/url
ml.nlu_classifier(body.current_thread.text).topics[].nameequalsRequest to View Invoice
ml.nlu_classifier(body.current_thread.text).topics[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
      regex.icontains func_call "regex.icontains(file.parse_text(.).text,\n                            'LOCATION[^:]*:.{1,300}google\\.com/url'\n        )"
  type.inbound eq "true"
   macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n        .name == \"Request to View Invoice\" and .confidence == \"high\"\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"

Attachment: Calendar invite with suspicious link leading to an open redirect

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

Calendar invite contains a link to either a free file host or free subdomain host, and the resulting webpage contains another link to an open redirect.

Threat Classification

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

CategoryValues
Attack typesSpam
Tactics and techniquesFree email provider, Free file host, Free subdomain host, ICS Phishing, Open redirect

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.hops
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
        and any(file.explode(.),
                any(.scan.url.urls,
                    (
                      .domain.domain in $free_file_hosts
                      or (
                        .domain.root_domain in $free_subdomain_hosts
                        and .domain.subdomain is not null
                        and not (
                          strings.ends_with(.url, "jpeg")
                          or strings.ends_with(.url, "png")
                        )
                        and .domain.subdomain != "www"
                      )
                    )
                    and any(ml.link_analysis(.).final_dom.links,
                            any(.href_url.rewrite.encoders,
                                strings.icontains(., "open_redirect")
                            )
                    )
                )
        )
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and (
      any(distinct(headers.hops, .authentication_results.dmarc is not null),
          strings.ilike(.authentication_results.dmarc, "*fail")
      )
    )
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Calendar invite contains a link to either a free file host or free subdomain host, and the resulting webpage contains another link to an open redirect.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'ics'
      • .content_type in ('application/ics', 'text/calendar')
    • any(file.explode(.), any(.scan.url.urls, ( .domain.domain in $free_file_hosts or ( .domain.root_domain in $free_subdomain_hosts and .domain.subdomain is not null and not ( strings.ends_with(.url, "jpeg") or strings.ends_with(.url, "png") ) and .domain.subdomain != "www" ) ) and any(ml.link_analysis(.).final_dom.links, any(.href_url.rewrite.encoders, strings.icontains(., "open_redirect") ) ) ) )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • ( any(distinct(headers.hops, .authentication_results.dmarc is not null), strings.ilike(.authentication_results.dmarc, "*fail") ) )
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  4. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  5. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, headers.hops, headers.hops[].authentication_results.dmarc, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.link_analysis, profile.by_sender, strings.ends_with, strings.icontains, strings.ilike. Reference lists: $free_file_hosts, $free_subdomain_hosts, $high_trust_sender_root_domains.

Indicators Matched (5)

FieldMatchValue
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
strings.icontainssubstringopen_redirect
strings.ilikesubstring*fail

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
       macro "any(file.explode(.),\n                any(.scan.url.urls,\n                    (\n                      .domain.domain in $free_file_hosts\n                      or (\n                        .domain.root_domain in $free_subdomain_hosts\n                        and .domain.subdomain is not null\n                        and not (\n                          strings.ends_with(.url, \"jpeg\")\n                          or strings.ends_with(.url, \"png\")\n                        )\n                        and .domain.subdomain != \"www\"\n                      )\n                    )\n                    and any(ml.link_analysis(.).final_dom.links,\n                            any(.href_url.rewrite.encoders,\n                                strings.icontains(., \"open_redirect\")\n                            )\n                    )\n                )\n        )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    and
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
       macro "(\n      any(distinct(headers.hops, .authentication_results.dmarc is not null),\n          strings.ilike(.authentication_results.dmarc, \"*fail\")\n      )\n    )"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: Callback phishing solicitation via image file

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

A fraudulent invoice/receipt found in an image attachment. Callback Phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.

Threat Classification

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

CategoryValues
Attack typesCallback Phishing
Tactics and techniquesEvasion, Free email provider, Out of band pivot, Social engineering, Image as content

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not (subject.is_reply and headers.in_reply_to is not null)
and not profile.by_sender_email().prevalence == "common"
and (
  sender.email.domain.root_domain in $free_email_providers
  or sender.email.domain.root_domain in ("onmicrosoft.com")
  or (
    (
      length(recipients.to) == 0
      or all(recipients.to, .display_name == "Undisclosed recipients")
    )
    and length(recipients.cc) == 0
    and length(recipients.bcc) == 0
  )
)
and any(attachments,
        // exclude images taken with mobile cameras and screenshots from android
        .file_type in $file_types_images
        and (
          any(file.explode(.),
              not any(.scan.exiftool.fields,
                      .key == "Model"
                      or (
                        .key == "Software"
                        and strings.starts_with(.value, "Android")
                      )
              )
              // exclude images taken with mobile cameras and screenshots from Apple
              and not any(.scan.exiftool.fields,
                          .key == "DeviceManufacturer"
                          and .value == "Apple Computer Inc."
              )
              and not any(.scan.exiftool.fields,
                          .key == "UserComment" and .value == "Screenshot"
              )
              // 4 of the following strings are found        
              and 4 of (
                // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
                strings.icontains(.scan.ocr.raw, "purchase"),
                strings.icontains(.scan.ocr.raw, "payment"),
                strings.icontains(.scan.ocr.raw, "transaction"),
                strings.icontains(.scan.ocr.raw, "subscription"),
                strings.icontains(.scan.ocr.raw, "antivirus"),
                strings.icontains(.scan.ocr.raw, "order"),
                strings.icontains(.scan.ocr.raw, "support"),
                strings.icontains(.scan.ocr.raw, "help line"),
                strings.icontains(.scan.ocr.raw, "receipt"),
                strings.icontains(.scan.ocr.raw, "invoice"),
                strings.icontains(.scan.ocr.raw, "call"),
                strings.icontains(.scan.ocr.raw, "helpdesk"),
                strings.icontains(.scan.ocr.raw, "cancel"),
                strings.icontains(.scan.ocr.raw, "renew"),
                strings.icontains(.scan.ocr.raw, "refund"),
                regex.icontains(.scan.ocr.raw, "(?:reach|contact) us at"),
                strings.icontains(.scan.ocr.raw, "+1"),
                strings.icontains(.scan.ocr.raw, "amount"),
                strings.icontains(.scan.ocr.raw, "charged"),
                strings.icontains(.scan.ocr.raw, "crypto"),
                strings.icontains(.scan.ocr.raw, "wallet address"),
                regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
                regex.icontains(.scan.ocr.raw,
                                '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
                                '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
                ),
              )
              // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
              and regex.icontains(.scan.ocr.raw,
                                  '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
              )
          )
          // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
          or any(ml.logo_detect(.).brands,
                 .name in (
                   "PayPal",
                   "Norton",
                   "GeekSquad",
                   "Ebay",
                   "McAfee",
                   "AT&T"
                 )
          )
        )
)

Detection Logic

Scope: inbound message.

A fraudulent invoice/receipt found in an image attachment. Callback Phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.

  1. inbound message
  2. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  3. not:
    • all of:
      • subject.is_reply
      • headers.in_reply_to is set
  4. not:
    • profile.by_sender_email().prevalence == "common"
  5. any of:
    • sender.email.domain.root_domain in $free_email_providers
    • sender.email.domain.root_domain in ('onmicrosoft.com')
    • all of:
      • any of:
        • length(recipients.to) == 0
        • all of recipients.to where:
          • .display_name is 'Undisclosed recipients'
      • length(recipients.cc) == 0
      • length(recipients.bcc) == 0
  6. any of attachments where all hold:
    • .file_type in $file_types_images
    • any of:
      • any(file.explode(.), not any(.scan.exiftool.fields, .key == "Model" or ( .key == "Software" and strings.starts_with(.value, "Android") ) ) // exclude images taken with mobile cameras and screenshots from Apple and not any(.scan.exiftool.fields, .key == "DeviceManufacturer" and .value == "Apple Computer Inc." ) and not any(.scan.exiftool.fields, .key == "UserComment" and .value == "Screenshot" ) // 4 of the following strings are found and 4 of ( // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml strings.icontains(.scan.ocr.raw, "purchase"), strings.icontains(.scan.ocr.raw, "payment"), strings.icontains(.scan.ocr.raw, "transaction"), strings.icontains(.scan.ocr.raw, "subscription"), strings.icontains(.scan.ocr.raw, "antivirus"), strings.icontains(.scan.ocr.raw, "order"), strings.icontains(.scan.ocr.raw, "support"), strings.icontains(.scan.ocr.raw, "help line"), strings.icontains(.scan.ocr.raw, "receipt"), strings.icontains(.scan.ocr.raw, "invoice"), strings.icontains(.scan.ocr.raw, "call"), strings.icontains(.scan.ocr.raw, "helpdesk"), strings.icontains(.scan.ocr.raw, "cancel"), strings.icontains(.scan.ocr.raw, "renew"), strings.icontains(.scan.ocr.raw, "refund"), regex.icontains(.scan.ocr.raw, "(?:reach|contact) us at"), strings.icontains(.scan.ocr.raw, "+1"), strings.icontains(.scan.ocr.raw, "amount"), strings.icontains(.scan.ocr.raw, "charged"), strings.icontains(.scan.ocr.raw, "crypto"), strings.icontains(.scan.ocr.raw, "wallet address"), regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'), regex.icontains(.scan.ocr.raw, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ), ) // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml and regex.icontains(.scan.ocr.raw, '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)' ) )
      • any(ml.logo_detect(.).brands, .name in ( "PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T" ) )

Inspects: attachments[].file_type, headers.in_reply_to, recipients.bcc, recipients.cc, recipients.to, recipients.to[].display_name, sender.email.domain.root_domain, subject.is_reply, type.inbound. Sensors: file.explode, ml.logo_detect, profile.by_sender, profile.by_sender_email, regex.icontains, strings.icontains, strings.starts_with. Reference lists: $file_types_images, $free_email_providers.

Indicators Matched (33)

FieldMatchValue
sender.email.domain.root_domainmemberonmicrosoft.com
recipients.to[].display_nameequalsUndisclosed recipients
strings.icontainssubstringpurchase
strings.icontainssubstringpayment
strings.icontainssubstringtransaction
strings.icontainssubstringsubscription
strings.icontainssubstringantivirus
strings.icontainssubstringorder
strings.icontainssubstringsupport
strings.icontainssubstringhelp line
strings.icontainssubstringreceipt
strings.icontainssubstringinvoice
21 more
strings.icontainssubstringcall
strings.icontainssubstringhelpdesk
strings.icontainssubstringcancel
strings.icontainssubstringrenew
strings.icontainssubstringrefund
regex.icontainsregex(?:reach|contact) us at
strings.icontainssubstring+1
strings.icontainssubstringamount
strings.icontainssubstringcharged
strings.icontainssubstringcrypto
strings.icontainssubstringwallet address
regex.icontainsregex\$\d{3}\.\d{2}\b
regex.icontainsregex\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}
regex.icontainsregex\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
regex.icontainsregex(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)
ml.logo_detect(attachments[]).brands[].namememberPayPal
ml.logo_detect(attachments[]).brands[].namememberNorton
ml.logo_detect(attachments[]).brands[].namememberGeekSquad
ml.logo_detect(attachments[]).brands[].namememberEbay
ml.logo_detect(attachments[]).brands[].namememberMcAfee
ml.logo_detect(attachments[]).brands[].namememberAT&T

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    and
      or
        recipients.to length_compare "0"
         macro "all(recipients.to, .display_name == \"Undisclosed recipients\")"
      recipients.bcc length_compare "0"
      recipients.cc length_compare "0"
    sender.email.domain.root_domain eq "onmicrosoft.com"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain in free_email_providers"
  any(attachments)
    and
      or
         macro "any(file.explode(.),\n              not any(.scan.exiftool.fields,\n                      .key == \"Model\"\n                      or (\n                        .key == \"Software\"\n                        and strings.starts_with(.value, \"Android\")\n                      )\n              )\n              // exclude images taken with mobile cameras and screenshots from Apple\n              and not any(.scan.exiftool.fields,\n                          .key == \"DeviceManufacturer\"\n                          and .value == \"Apple Computer Inc.\"\n              )\n              and not any(.scan.exiftool.fields,\n                          .key == \"UserComment\" and .value == \"Screenshot\"\n              )\n              // 4 of the following strings are found        \n              and 4 of (\n                // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml\n                strings.icontains(.scan.ocr.raw, \"purchase\"),\n                strings.icontains(.scan.ocr.raw, \"payment\"),\n                strings.icontains(.scan.ocr.raw, \"transaction\"),\n                strings.icontains(.scan.ocr.raw, \"subscription\"),\n                strings.icontains(.scan.ocr.raw, \"antivirus\"),\n                strings.icontains(.scan.ocr.raw, \"order\"),\n                strings.icontains(.scan.ocr.raw, \"support\"),\n                strings.icontains(.scan.ocr.raw, \"help line\"),\n                strings.icontains(.scan.ocr.raw, \"receipt\"),\n                strings.icontains(.scan.ocr.raw, \"invoice\"),\n                strings.icontains(.scan.ocr.raw, \"call\"),\n                strings.icontains(.scan.ocr.raw, \"helpdesk\"),\n                strings.icontains(.scan.ocr.raw, \"cancel\"),\n                strings.icontains(.scan.ocr.raw, \"renew\"),\n                strings.icontains(.scan.ocr.raw, \"refund\"),\n                regex.icontains(.scan.ocr.raw, \"(?:reach|contact) us at\"),\n                strings.icontains(.scan.ocr.raw, \"+1\"),\n                strings.icontains(.scan.ocr.raw, \"amount\"),\n                strings.icontains(.scan.ocr.raw, \"charged\"),\n                strings.icontains(.scan.ocr.raw, \"crypto\"),\n                strings.icontains(.scan.ocr.raw, \"wallet address\"),\n                regex.icontains(.scan.ocr.raw, '\\$\\d{3}\\.\\d{2}\\b'),\n                regex.icontains(.scan.ocr.raw,\n                                '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n                                '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n                ),\n              )\n              // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml\n              and regex.icontains(.scan.ocr.raw,\n                                  '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'\n              )\n          )"
         macro "any(ml.logo_detect(.).brands,\n                 .name in (\n                   \"PayPal\",\n                   \"Norton\",\n                   \"GeekSquad\",\n                   \"Ebay\",\n                   \"McAfee\",\n                   \"AT&T\"\n                 )\n          )"
      attachments.file_type macro "attachments[].file_type in file_types_images"
  not
    and
      headers.in_reply_to is_not_null
      subject.is_reply eq "true"
  not
    profile.by_sender_email func_call "profile.by_sender_email().prevalence == \"common\""
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
sender.email.domain.root_domainin
  • onmicrosoft.com corpus 3 (mql 3)
field:"sender.email.domain.root_domain" kind:in value:"onmicrosoft.com"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.in_reply_tois_not_null(no value, null check)excludes:headers.in_reply_to
subject.is_replyeqtrueexcludes:subject.is_reply field:"subject.is_reply" value:"true"

Attachment: Callback phishing solicitation via pdf file

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

A fraudulent invoice/receipt found in a pdf attachment. Callback Phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.

Threat Classification

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

CategoryValues
Attack typesCallback Phishing
Tactics and techniquesEvasion, Free email provider, Out of band pivot, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.html
  • body.plain
  • headers
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

// single attachment
and length(attachments) == 1

// sender is freemail
and (
  sender.email.domain.root_domain in $free_email_providers
  // the sender is a common service, which has likely been sent through a DL
  or (
    sender.email.domain.root_domain in $tranco_50k
    and all(recipients.to, .email.domain.domain not in $org_domains)
  )
)

// negate ML matches to "Professional and Career Development" - tuning resume FPs
and not any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics,
            .name == "Professional and Career Development"
            and .confidence == "high"
)
and not any(attachments,
            .file_type == 'pdf'
            and any(file.explode(.),
                    any(ml.nlu_classifier(.scan.ocr.raw).topics,
                        .name == "Professional and Career Development"
                        and .confidence == "high"
                    )
            )
)

// the attachment is a pdf with less than 3 pages, and at least 60 ocr chars
and any(attachments,
        (
          .file_extension == "pdf"
          // get the length of the attached pdf
          and any(file.explode(.),
                  .depth == 0
                  and .scan.exiftool.page_count < 3
                  and (
                    not (
                      strings.istarts_with(.scan.exiftool.producer,
                                           "Aspose.Words for Java"
                      )
                      and (
                        .scan.exiftool.creator == "Anusha T"
                        or any(.scan.exiftool.fields,
                               .key == "Author" and .value == "Anusha T"
                        )
                      )
                    )
                    or .scan.exiftool.producer is null
                    or .scan.exiftool.creator is null
                  )
          )
          // check that any _single_ result in the file.explode matches these conditions
          // a second file.explode is required because the OCR is generated at a different depth within
          // the file.explode results
          and (
            any(file.explode(.),
                length(.scan.ocr.raw) > 60
                // 4 of the following strings are found
                and 4 of (
                  // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
                  strings.icontains(.scan.ocr.raw, "purchase"),
                  strings.icontains(.scan.ocr.raw, "payment"),
                  strings.icontains(.scan.ocr.raw, "transaction"),
                  strings.icontains(.scan.ocr.raw, "subscription"),
                  strings.icontains(.scan.ocr.raw, "antivirus"),
                  strings.icontains(.scan.ocr.raw, "order"),
                  strings.icontains(.scan.ocr.raw, "support"),
                  strings.icontains(.scan.ocr.raw, "help line"),
                  strings.icontains(.scan.ocr.raw, "receipt"),
                  strings.icontains(.scan.ocr.raw, "invoice"),
                  strings.icontains(.scan.ocr.raw, "call"),
                  strings.icontains(.scan.ocr.raw, "helpdesk"),
                  strings.icontains(.scan.ocr.raw, "cancel"),
                  strings.icontains(.scan.ocr.raw, "renew"),
                  strings.icontains(.scan.ocr.raw, "refund"),
                  regex.icontains(.scan.ocr.raw, "(?:reach|contact) us at"),
                  strings.icontains(.scan.ocr.raw, "+1"),
                  strings.icontains(.scan.ocr.raw, "amount"),
                  strings.icontains(.scan.ocr.raw, "charged"),
                  strings.icontains(.scan.ocr.raw, "crypto"),
                  strings.icontains(.scan.ocr.raw, "wallet address"),
                  regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
                  regex.icontains(.scan.ocr.raw,
                                  '(\+[ilo0-9]|1.(\()?[ilo0-9]{3}(\))?\D[ilo0-9]{3}\D[ilo0-9]{4})',
                                  '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
                  ),
                )
                and (
                  // this section is synced with attachment_callback_phish_with_img.yml and body_callback_phishing_no_attachment.yml
                  regex.icontains(.scan.ocr.raw,
                                  '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
                  )
                  // suspicious attachment name from the attachment object not file.explode() output
                  or regex.icontains(..file_name, 'INV(?:_|\s)?\d+(.pdf)$')
                )
                // Negate bank statements
                and not (
                  2 of (
                    strings.icontains(.scan.ocr.raw, "opening balance"),
                    strings.icontains(.scan.ocr.raw, "closing balance"),
                    strings.icontains(.scan.ocr.raw, "direct debit"),
                    strings.icontains(.scan.ocr.raw, "interest"),
                    strings.icontains(.scan.ocr.raw, "account balance"),
                  )
                )
            )
            // this section is synced with attachment_callback_phish_with_img.yml and body_callback_phishing_no_attachment.yml
            or any(ml.logo_detect(.).brands,
                   .name in (
                     "PayPal",
                     "Norton",
                     "GeekSquad",
                     "Ebay",
                     "McAfee",
                     "AT&T"
                   )
            )
          )
        )
)
and (
  (
    (length(headers.references) > 0 or headers.in_reply_to is null)
    and not (
      (
        strings.istarts_with(subject.subject, "RE:")
        or strings.istarts_with(subject.subject, "RES:")
        or strings.istarts_with(subject.subject, "R:")
        or strings.istarts_with(subject.subject, "ODG:")
        or strings.istarts_with(subject.subject, "答复:")
        or strings.istarts_with(subject.subject, "AW:")
        or strings.istarts_with(subject.subject, "TR:")
        or strings.istarts_with(subject.subject, "FWD:")
        or regex.imatch(subject.subject,
                        '(\[[^\]]+\]\s?){0,3}(re|fwd?|automat.*)\s?:.*'
        )
      )
    )
  )
  or (length(headers.references) == 0 or length(body.current_thread.text) < 10)
)

Detection Logic

Scope: inbound message.

A fraudulent invoice/receipt found in a pdf attachment. Callback Phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.

  1. inbound message
  2. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  3. length(attachments) == 1
  4. any of:
    • sender.email.domain.root_domain in $free_email_providers
    • all of:
      • sender.email.domain.root_domain in $tranco_50k
      • all of recipients.to where:
        • .email.domain.domain not in $org_domains
  5. not:
    • any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics, .name == "Professional and Career Development" and .confidence == "high" )
  6. not:
    • any of attachments where all hold:
      • .file_type is 'pdf'
      • any(file.explode(.), any(ml.nlu_classifier(.scan.ocr.raw).topics, .name == "Professional and Career Development" and .confidence == "high" ) )
  7. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any(file.explode(.), .depth == 0 and .scan.exiftool.page_count < 3 and ( not ( strings.istarts_with(.scan.exiftool.producer, "Aspose.Words for Java" ) and ( .scan.exiftool.creator == "Anusha T" or any(.scan.exiftool.fields, .key == "Author" and .value == "Anusha T" ) ) ) or .scan.exiftool.producer is null or .scan.exiftool.creator is null ) )
    • any of:
      • any(file.explode(.), length(.scan.ocr.raw) > 60 // 4 of the following strings are found and 4 of ( // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml strings.icontains(.scan.ocr.raw, "purchase"), strings.icontains(.scan.ocr.raw, "payment"), strings.icontains(.scan.ocr.raw, "transaction"), strings.icontains(.scan.ocr.raw, "subscription"), strings.icontains(.scan.ocr.raw, "antivirus"), strings.icontains(.scan.ocr.raw, "order"), strings.icontains(.scan.ocr.raw, "support"), strings.icontains(.scan.ocr.raw, "help line"), strings.icontains(.scan.ocr.raw, "receipt"), strings.icontains(.scan.ocr.raw, "invoice"), strings.icontains(.scan.ocr.raw, "call"), strings.icontains(.scan.ocr.raw, "helpdesk"), strings.icontains(.scan.ocr.raw, "cancel"), strings.icontains(.scan.ocr.raw, "renew"), strings.icontains(.scan.ocr.raw, "refund"), regex.icontains(.scan.ocr.raw, "(?:reach|contact) us at"), strings.icontains(.scan.ocr.raw, "+1"), strings.icontains(.scan.ocr.raw, "amount"), strings.icontains(.scan.ocr.raw, "charged"), strings.icontains(.scan.ocr.raw, "crypto"), strings.icontains(.scan.ocr.raw, "wallet address"), regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'), regex.icontains(.scan.ocr.raw, '(\+[ilo0-9]|1.(\()?[ilo0-9]{3}(\))?\D[ilo0-9]{3}\D[ilo0-9]{4})', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ), ) and ( // this section is synced with attachment_callback_phish_with_img.yml and body_callback_phishing_no_attachment.yml regex.icontains(.scan.ocr.raw, '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)' ) // suspicious attachment name from the attachment object not file.explode() output or regex.icontains(..file_name, 'INV(?:_|\s)?\d+(.pdf)$') ) // Negate bank statements and not ( 2 of ( strings.icontains(.scan.ocr.raw, "opening balance"), strings.icontains(.scan.ocr.raw, "closing balance"), strings.icontains(.scan.ocr.raw, "direct debit"), strings.icontains(.scan.ocr.raw, "interest"), strings.icontains(.scan.ocr.raw, "account balance"), ) ) )
      • any(ml.logo_detect(.).brands, .name in ( "PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T" ) )
  8. any of:
    • all of:
      • any of:
        • length(headers.references) > 0
        • headers.in_reply_to is missing
      • none of:
        • subject.subject starts with 'RE:'
        • subject.subject starts with 'RES:'
        • subject.subject starts with 'R:'
        • subject.subject starts with 'ODG:'
        • subject.subject starts with '答复:'
        • subject.subject starts with 'AW:'
        • subject.subject starts with 'TR:'
        • subject.subject starts with 'FWD:'
        • subject.subject matches '(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?|automat.*)\\s?:.*'
    • any of:
      • length(headers.references) == 0
      • length(body.current_thread.text) < 10

Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, body.current_thread.text, body.html.display_text, body.plain.raw, headers.in_reply_to, headers.references, recipients.to, recipients.to[].email.domain.domain, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, ml.logo_detect, ml.nlu_classifier, profile.by_sender, regex.icontains, regex.imatch, strings.icontains, strings.istarts_with. Reference lists: $free_email_providers, $org_domains, $tranco_50k.

Indicators Matched (33)

FieldMatchValue
attachments[].file_extensionequalspdf
strings.icontainssubstringpurchase
strings.icontainssubstringpayment
strings.icontainssubstringtransaction
strings.icontainssubstringsubscription
strings.icontainssubstringantivirus
strings.icontainssubstringorder
strings.icontainssubstringsupport
strings.icontainssubstringhelp line
strings.icontainssubstringreceipt
strings.icontainssubstringinvoice
strings.icontainssubstringcall
21 more
strings.icontainssubstringhelpdesk
strings.icontainssubstringcancel
strings.icontainssubstringrenew
strings.icontainssubstringrefund
regex.icontainsregex(?:reach|contact) us at
strings.icontainssubstring+1
strings.icontainssubstringamount
strings.icontainssubstringcharged
strings.icontainssubstringcrypto
strings.icontainssubstringwallet address
regex.icontainsregex\$\d{3}\.\d{2}\b
regex.icontainsregex(\+[ilo0-9]|1.(\()?[ilo0-9]{3}(\))?\D[ilo0-9]{3}\D[ilo0-9]{4})
regex.icontainsregex\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
regex.icontainsregex(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)
regex.icontainsregexINV(?:_|\s)?\d+(.pdf)$
ml.logo_detect(attachments[]).brands[].namememberPayPal
ml.logo_detect(attachments[]).brands[].namememberNorton
ml.logo_detect(attachments[]).brands[].namememberGeekSquad
ml.logo_detect(attachments[]).brands[].namememberEbay
ml.logo_detect(attachments[]).brands[].namememberMcAfee
ml.logo_detect(attachments[]).brands[].namememberAT&T

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        or
          subject.subject regex_match "(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?|automat.*)\\s?:.*"
          subject.subject starts_with "AW:"
          subject.subject starts_with "FWD:"
          subject.subject starts_with "ODG:"
          subject.subject starts_with "R:"
          subject.subject starts_with "RE:"
          subject.subject starts_with "RES:"
          subject.subject starts_with "TR:"
          subject.subject starts_with "答复:"
      or
        headers.in_reply_to is_null
        headers.references length_compare "0"
    body.current_thread.text length_compare "10"
    headers.references length_compare "0"
  not
    any(attachments)
      and
        attachments.file_type eq "pdf"
         macro "any(file.explode(.),\n                    any(ml.nlu_classifier(.scan.ocr.raw).topics,\n                        .name == \"Professional and Career Development\"\n                        and .confidence == \"high\"\n                    )\n            )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  any(attachments)
    and
      or
         macro "any(file.explode(.),\n                length(.scan.ocr.raw) > 60\n                // 4 of the following strings are found\n                and 4 of (\n                  // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml\n                  strings.icontains(.scan.ocr.raw, \"purchase\"),\n                  strings.icontains(.scan.ocr.raw, \"payment\"),\n                  strings.icontains(.scan.ocr.raw, \"transaction\"),\n                  strings.icontains(.scan.ocr.raw, \"subscription\"),\n                  strings.icontains(.scan.ocr.raw, \"antivirus\"),\n                  strings.icontains(.scan.ocr.raw, \"order\"),\n                  strings.icontains(.scan.ocr.raw, \"support\"),\n                  strings.icontains(.scan.ocr.raw, \"help line\"),\n                  strings.icontains(.scan.ocr.raw, \"receipt\"),\n                  strings.icontains(.scan.ocr.raw, \"invoice\"),\n                  strings.icontains(.scan.ocr.raw, \"call\"),\n                  strings.icontains(.scan.ocr.raw, \"helpdesk\"),\n                  strings.icontains(.scan.ocr.raw, \"cancel\"),\n                  strings.icontains(.scan.ocr.raw, \"renew\"),\n                  strings.icontains(.scan.ocr.raw, \"refund\"),\n                  regex.icontains(.scan.ocr.raw, \"(?:reach|contact) us at\"),\n                  strings.icontains(.scan.ocr.raw, \"+1\"),\n                  strings.icontains(.scan.ocr.raw, \"amount\"),\n                  strings.icontains(.scan.ocr.raw, \"charged\"),\n                  strings.icontains(.scan.ocr.raw, \"crypto\"),\n                  strings.icontains(.scan.ocr.raw, \"wallet address\"),\n                  regex.icontains(.scan.ocr.raw, '\\$\\d{3}\\.\\d{2}\\b'),\n                  regex.icontains(.scan.ocr.raw,\n                                  '(\\+[ilo0-9]|1.(\\()?[ilo0-9]{3}(\\))?\\D[ilo0-9]{3}\\D[ilo0-9]{4})',\n                                  '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n                  ),\n                )\n                and (\n                  // this section is synced with attachment_callback_phish_with_img.yml and body_callback_phishing_no_attachment.yml\n                  regex.icontains(.scan.ocr.raw,\n                                  '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'\n                  )\n                  // suspicious attachment name from the attachment object not file.explode() output\n                  or regex.icontains(..file_name, 'INV(?:_|\\s)?\\d+(.pdf)$')\n                )\n                // Negate bank statements\n                and not (\n                  2 of (\n                    strings.icontains(.scan.ocr.raw, \"opening balance\"),\n                    strings.icontains(.scan.ocr.raw, \"closing balance\"),\n                    strings.icontains(.scan.ocr.raw, \"direct debit\"),\n                    strings.icontains(.scan.ocr.raw, \"interest\"),\n                    strings.icontains(.scan.ocr.raw, \"account balance\"),\n                  )\n                )\n            )"
         macro "any(ml.logo_detect(.).brands,\n                   .name in (\n                     \"PayPal\",\n                     \"Norton\",\n                     \"GeekSquad\",\n                     \"Ebay\",\n                     \"McAfee\",\n                     \"AT&T\"\n                   )\n            )"
      attachments.file_extension eq "pdf"
       macro "any(file.explode(.),\n                  .depth == 0\n                  and .scan.exiftool.page_count < 3\n                  and (\n                    not (\n                      strings.istarts_with(.scan.exiftool.producer,\n                                           \"Aspose.Words for Java\"\n                      )\n                      and (\n                        .scan.exiftool.creator == \"Anusha T\"\n                        or any(.scan.exiftool.fields,\n                               .key == \"Author\" and .value == \"Anusha T\"\n                        )\n                      )\n                    )\n                    or .scan.exiftool.producer is null\n                    or .scan.exiftool.creator is null\n                  )\n          )"
  or
    and
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in tranco_50k"
       macro "all(recipients.to, .email.domain.domain not in $org_domains)"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain in free_email_providers"
  not
     macro "any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics,\n            .name == \"Professional and Career Development\"\n            and .confidence == \"high\"\n)"
  attachments length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
headers.in_reply_tois_null
  • (no value, null check)
field:"headers.in_reply_to" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments

Attachment: Callback phishing solicitation via text-based file

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

Callback Phishing via a text-based file attachment and a short body and subject from an unknown sender.

Threat Classification

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

CategoryValues
Attack typesCallback Phishing
Tactics and techniquesEvasion, Out of band pivot, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.links
  • headers
  • headers.auth_summary
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and length(subject.subject) <= 10
// there are no links, all the links are to aka.ms, or an extraction from a warning banner that match the senders domain
and (
  length(body.links) == 0
  or length(filter(body.links,
                   (
                     .display_text is null
                     and .display_url.url == sender.email.domain.root_domain
                   )
                   or .href_url.domain.domain == "aka.ms"
                   or network.whois(.display_url.domain).days_old < 30
            )
  ) == length(body.links)
)
and (body.current_thread.text is null or length(body.current_thread.text) < 50)
and 0 < length(attachments) < 4
and any(attachments,
        (
          .content_type == "text/plain"
          or .file_type in ("doc", "docx", "xls", "xlsx")
        )
        and any(file.explode(.),
                (.depth == 0 or .flavors.mime == "text/plain")
                // 4 of the following strings are found        
                and 4 of (
                  // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
                  strings.icontains(.scan.strings.raw, "purchase"),
                  strings.icontains(.scan.strings.raw, "payment"),
                  strings.icontains(.scan.strings.raw, "transaction"),
                  strings.icontains(.scan.strings.raw, "subscription"),
                  strings.icontains(.scan.strings.raw, "antivirus"),
                  strings.icontains(.scan.strings.raw, "order"),
                  strings.icontains(.scan.strings.raw, "support"),
                  strings.icontains(.scan.strings.raw, "help line"),
                  strings.icontains(.scan.strings.raw, "receipt"),
                  strings.icontains(.scan.strings.raw, "invoice"),
                  strings.icontains(.scan.strings.raw, "call"),
                  strings.icontains(.scan.strings.raw, "helpdesk"),
                  strings.icontains(.scan.strings.raw, "cancel"),
                  strings.icontains(.scan.strings.raw, "renew"),
                  strings.icontains(.scan.strings.raw, "refund"),
                  regex.icontains(.scan.strings.raw, "(?:reach|contact) us at"),
                  strings.icontains(.scan.strings.raw, "+1"),
                  strings.icontains(.scan.strings.raw, "amount"),
                  strings.icontains(.scan.strings.raw, "charged"),
                  strings.icontains(.scan.strings.raw, "crypto"),
                  strings.icontains(.scan.strings.raw, "wallet address"),
                  regex.icontains(.scan.strings.raw, '\$\d{3}\.\d{2}\b'),
                  regex.icontains(.scan.strings.raw,
                                  '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
                                  '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
                  ),
                )
                // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
                and regex.icontains(.scan.strings.raw,
                                    '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks)'
                )
        )
)
and profile.by_sender().prevalence != "common"
and not profile.by_sender().solicited
and not profile.by_sender().any_messages_benign

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

Callback Phishing via a text-based file attachment and a short body and subject from an unknown sender.

  1. inbound message
  2. length(subject.subject) <= 10
  3. any of:
    • length(body.links) == 0
    • length(filter(body.links, ( .display_text is null and .display_url.url == sender.email.domain.root_domain ) or .href_url.domain.domain == "aka.ms" or network.whois(.display_url.domain).days_old < 30 ) ) == length(body.links)
  4. any of:
    • body.current_thread.text is missing
    • length(body.current_thread.text) < 50
  5. all of:
    • (0) < (length(attachments))
    • (length(attachments)) < (4)
  6. any of attachments where all hold:
    • any of:
      • .content_type is 'text/plain'
      • .file_type in ('doc', 'docx', 'xls', 'xlsx')
    • any(file.explode(.), (.depth == 0 or .flavors.mime == "text/plain") // 4 of the following strings are found and 4 of ( // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml strings.icontains(.scan.strings.raw, "purchase"), strings.icontains(.scan.strings.raw, "payment"), strings.icontains(.scan.strings.raw, "transaction"), strings.icontains(.scan.strings.raw, "subscription"), strings.icontains(.scan.strings.raw, "antivirus"), strings.icontains(.scan.strings.raw, "order"), strings.icontains(.scan.strings.raw, "support"), strings.icontains(.scan.strings.raw, "help line"), strings.icontains(.scan.strings.raw, "receipt"), strings.icontains(.scan.strings.raw, "invoice"), strings.icontains(.scan.strings.raw, "call"), strings.icontains(.scan.strings.raw, "helpdesk"), strings.icontains(.scan.strings.raw, "cancel"), strings.icontains(.scan.strings.raw, "renew"), strings.icontains(.scan.strings.raw, "refund"), regex.icontains(.scan.strings.raw, "(?:reach|contact) us at"), strings.icontains(.scan.strings.raw, "+1"), strings.icontains(.scan.strings.raw, "amount"), strings.icontains(.scan.strings.raw, "charged"), strings.icontains(.scan.strings.raw, "crypto"), strings.icontains(.scan.strings.raw, "wallet address"), regex.icontains(.scan.strings.raw, '\$\d{3}\.\d{2}\b'), regex.icontains(.scan.strings.raw, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ), ) // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml and regex.icontains(.scan.strings.raw, '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks)' ) )
  7. profile.by_sender().prevalence != "common"
  8. not:
    • profile.by_sender().solicited
  9. not:
    • profile.by_sender().any_messages_benign
  10. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].content_type, attachments[].file_type, body.current_thread.text, body.links, body.links[].display_text, body.links[].display_url.domain, body.links[].display_url.url, body.links[].href_url.domain.domain, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, network.whois, profile.by_sender, regex.icontains, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (32)

FieldMatchValue
body.links[].href_url.domain.domainequalsaka.ms
attachments[].content_typeequalstext/plain
attachments[].file_typememberdoc
attachments[].file_typememberdocx
attachments[].file_typememberxls
attachments[].file_typememberxlsx
file.explode(attachments[])[].flavors.mimeequalstext/plain
strings.icontainssubstringpurchase
strings.icontainssubstringpayment
strings.icontainssubstringtransaction
strings.icontainssubstringsubscription
strings.icontainssubstringantivirus
20 more
strings.icontainssubstringorder
strings.icontainssubstringsupport
strings.icontainssubstringhelp line
strings.icontainssubstringreceipt
strings.icontainssubstringinvoice
strings.icontainssubstringcall
strings.icontainssubstringhelpdesk
strings.icontainssubstringcancel
strings.icontainssubstringrenew
strings.icontainssubstringrefund
regex.icontainsregex(?:reach|contact) us at
strings.icontainssubstring+1
strings.icontainssubstringamount
strings.icontainssubstringcharged
strings.icontainssubstringcrypto
strings.icontainssubstringwallet address
regex.icontainsregex\$\d{3}\.\d{2}\b
regex.icontainsregex\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}
regex.icontainsregex\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
regex.icontainsregex(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "text/plain"
        attachments.file_type in ["doc", "docx", "xls", "xlsx"]
       macro "any(file.explode(.),\n                (.depth == 0 or .flavors.mime == \"text/plain\")\n                // 4 of the following strings are found        \n                and 4 of (\n                  // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml\n                  strings.icontains(.scan.strings.raw, \"purchase\"),\n                  strings.icontains(.scan.strings.raw, \"payment\"),\n                  strings.icontains(.scan.strings.raw, \"transaction\"),\n                  strings.icontains(.scan.strings.raw, \"subscription\"),\n                  strings.icontains(.scan.strings.raw, \"antivirus\"),\n                  strings.icontains(.scan.strings.raw, \"order\"),\n                  strings.icontains(.scan.strings.raw, \"support\"),\n                  strings.icontains(.scan.strings.raw, \"help line\"),\n                  strings.icontains(.scan.strings.raw, \"receipt\"),\n                  strings.icontains(.scan.strings.raw, \"invoice\"),\n                  strings.icontains(.scan.strings.raw, \"call\"),\n                  strings.icontains(.scan.strings.raw, \"helpdesk\"),\n                  strings.icontains(.scan.strings.raw, \"cancel\"),\n                  strings.icontains(.scan.strings.raw, \"renew\"),\n                  strings.icontains(.scan.strings.raw, \"refund\"),\n                  regex.icontains(.scan.strings.raw, \"(?:reach|contact) us at\"),\n                  strings.icontains(.scan.strings.raw, \"+1\"),\n                  strings.icontains(.scan.strings.raw, \"amount\"),\n                  strings.icontains(.scan.strings.raw, \"charged\"),\n                  strings.icontains(.scan.strings.raw, \"crypto\"),\n                  strings.icontains(.scan.strings.raw, \"wallet address\"),\n                  regex.icontains(.scan.strings.raw, '\\$\\d{3}\\.\\d{2}\\b'),\n                  regex.icontains(.scan.strings.raw,\n                                  '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n                                  '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n                  ),\n                )\n                // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml\n                and regex.icontains(.scan.strings.raw,\n                                    '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks)'\n                )\n        )"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  or
    body.current_thread.text is_null
    body.current_thread.text length_compare "50"
  or
    body.links length_compare "0"
    length func_call "length(filter(body.links,\n                   (\n                     .display_text is null\n                     and .display_url.url == sender.email.domain.root_domain\n                   )\n                   or .href_url.domain.domain == \"aka.ms\"\n                   or network.whois(.display_url.domain).days_old < 30\n            )\n  ) == length(body.links)"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  not
    profile.by_sender func_call "profile.by_sender().solicited"
  attachments length_compare "0"
  attachments length_compare "4"
  profile.by_sender func_call "profile.by_sender().prevalence != \"common\""
  subject.subject length_compare "10"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textis_null
  • (no value, null check)
field:"body.current_thread.text" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: Canva PDF with susupicious author metadata

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

Detects inbound messages containing PDF attachments that were created using Canva but have author metadata containing '@proton.me', indicating potential service abuse where legitimate design tools are being misused in conjunction with privacy-focused email services.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesFree email provider, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        strings.icontains(beta.parse_exif(.).author, '@proton.me')
        and beta.parse_exif(.).producer == 'Canva'
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing PDF attachments that were created using Canva but have author metadata containing '@proton.me', indicating potential service abuse where legitimate design tools are being misused in conjunction with privacy-focused email services.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), strings.icontains(beta.parse_exif(.).author, '@proton.me') and beta.parse_exif(.).producer == 'Canva' )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif, strings.icontains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
strings.icontainssubstring@proton.me

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        strings.icontains(beta.parse_exif(.).author, '@proton.me')\n        and beta.parse_exif(.).producer == 'Canva'\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"

Attachment: cmd file extension

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

Detects messages containing CMD (Command Prompt) batch files, either as direct attachments or within compressed archives. CMD files can execute arbitrary system commands and are commonly used to deliver malware or perform unauthorized system modifications.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesScripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(attachments) > 0
and any(attachments,
        .file_extension =~ "cmd"
        or (
          .file_extension in~ $file_extensions_common_archives
          and any(file.explode(.), .file_extension =~ "cmd")
        )
)

Detection Logic

Scope: inbound message.

Detects messages containing CMD (Command Prompt) batch files, either as direct attachments or within compressed archives. CMD files can execute arbitrary system commands and are commonly used to deliver malware or perform unauthorized system modifications.

  1. inbound message
  2. length(attachments) > 0
  3. any of attachments where any holds:
    • .file_extension is 'cmd'
    • all of:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), .file_extension =~ "cmd")

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalscmd
file.explode(attachments[])[].file_extensionequalscmd

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.), .file_extension =~ \"cmd\")"
      attachments.file_extension eq "cmd"
  attachments length_compare "0"
  type.inbound eq "true"

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"

Attachment: Compensation review lure with QR code

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

Detects PDF attachments containing compensation or payroll-themed content with QR codes from unsolicited or suspicious senders.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, QR code, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • recipients
  • recipients.to
  • sender.email
  • type

Rule Body

type.inbound
and (
  any(attachments, .content_type == "application/pdf" or .file_type == "pdf")
  and (
    // short or null message body
    (
      length(body.current_thread.text) < 500 or body.current_thread.text is null
    )
    // ignore disclaimers in body length calculation
    or (
      any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,
                     .name == "disclaimer"
              ),
              .text
          ),
          (length(body.current_thread.text) - length(.)) < 500
      )
    )
  )
)
and (
  // attached PDF contains a compensation review themed lure with a QR code and suspicious indicators
  any(attachments,
      // add conditions for pdf attachment
      (
        regex.icontains(.file_name,
                        'salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting'
        )
        // recipient email SLD in filename
        or any(recipients.to,
               strings.icontains(..file_name, .email.domain.sld)
               and .email.domain.valid
        )
        or regex.icontains(beta.parse_exif(.).title,
                           'salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting'
        )
      )
      // add conditions for text and any QR code within the pdf attachment
      and (
        // conditions for QR code via text
        any(file.explode(.),
            any([.scan.strings.raw, .scan.ocr.raw],
                regex.icontains(., 'scan|camera|review and sign')
                and regex.icontains(., '\bQR\b|Q\.R\.|barcode')
            )
        )
        or any(file.explode(.),
               .scan.qr.type == "url" and .scan.qr.url.domain.valid
        )
      )
      // conditions for text
      and any(file.explode(.),
              // review/change terms in file content
              any([.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title],
                  (
                    regex.icontains(.,
                                    '\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\b'
                    )
                  )
              )
              or (
                // recipient local_part in attachment body
                any(recipients.to,
                    strings.contains(..scan.ocr.raw, .email.local_part)
                )
                and (
                  // NLU cred_theft disposition
                  any(ml.nlu_classifier(.scan.ocr.raw).intents,
                      .name == "cred_theft" and .confidence != "low"
                  )
                  // suspicious topics
                  and any(ml.nlu_classifier(.scan.ocr.raw).topics,
                          .name in (
                            "Benefit Enrollment",
                            "Financial Communications"
                          )
                          and .confidence != "low"
                  )
                )
              )
      )
  )
)
and (
  not profile.by_sender_email().solicited
  or not profile.by_sender_email().any_messages_benign
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
  // account for spoofed sender domains
  or (
    sender.email.domain.domain in $org_domains
    and not coalesce(headers.auth_summary.dmarc.pass, false)
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing compensation or payroll-themed content with QR codes from unsolicited or suspicious senders.

  1. inbound message
  2. all of:
    • any of attachments where any holds:
      • .content_type is 'application/pdf'
      • .file_type is 'pdf'
    • any of:
      • any of:
        • length(body.current_thread.text) < 500
        • body.current_thread.text is missing
      • ( any(map(filter(ml.nlu_classifier(body.current_thread.text).entities, .name == "disclaimer" ), .text ), (length(body.current_thread.text) - length(.)) < 500 ) )
  3. any of attachments where all hold:
    • any of:
      • .file_name matches 'salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting'
      • any of recipients.to where all hold:
        • strings.icontains(..file_name, .email.domain.sld)
        • .email.domain.valid
      • regex.icontains(beta.parse_exif(.).title, 'salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting' )
    • any of:
      • any(file.explode(.), any([.scan.strings.raw, .scan.ocr.raw], regex.icontains(., 'scan|camera|review and sign') and regex.icontains(., '\bQR\b|Q\.R\.|barcode') ) )
      • any(file.explode(.), .scan.qr.type == "url" and .scan.qr.url.domain.valid )
    • any(file.explode(.), // review/change terms in file content any([.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title], ( regex.icontains(., '\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\b' ) ) ) or ( // recipient local_part in attachment body any(recipients.to, strings.contains(..scan.ocr.raw, .email.local_part) ) and ( // NLU cred_theft disposition any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence != "low" ) // suspicious topics and any(ml.nlu_classifier(.scan.ocr.raw).topics, .name in ( "Benefit Enrollment", "Financial Communications" ) and .confidence != "low" ) ) ) )
  4. any of:
    • not:
      • profile.by_sender_email().solicited
    • not:
      • profile.by_sender_email().any_messages_benign
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
    • all of:
      • sender.email.domain.domain in $org_domains
      • not:
        • coalesce(headers.auth_summary.dmarc.pass, false)
  5. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_type, attachments[].file_name, attachments[].file_type, body.current_thread.text, headers.auth_summary.dmarc.pass, recipients.to, recipients.to[].email.domain.sld, recipients.to[].email.domain.valid, recipients.to[].email.local_part, sender.email.domain.domain, sender.email.domain.root_domain, type.inbound. Sensors: beta.parse_exif, file.explode, ml.nlu_classifier, profile.by_sender_email, regex.icontains, strings.contains, strings.icontains. Reference lists: $high_trust_sender_root_domains, $org_domains.

Indicators Matched (11)

FieldMatchValue
attachments[].content_typeequalsapplication/pdf
attachments[].file_typeequalspdf
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsdisclaimer
regex.icontainsregexsalary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting
regex.icontainsregexscan|camera|review and sign
regex.icontainsregex\bQR\b|Q\.R\.|barcode
file.explode(attachments[])[].scan.qr.typeequalsurl
regex.icontainsregex\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\b
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].namememberBenefit Enrollment
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].namememberFinancial Communications

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        any(recipients.to)
          and
            recipients.to.email.domain.valid eq "true"
            strings.icontains func_call "strings.icontains(..file_name, .email.domain.sld)"
        attachments.file_name regex_match "salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting"
        regex.icontains func_call "regex.icontains(beta.parse_exif(.).title,\n                           'salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting'\n        )"
      or
         macro "any(file.explode(.),\n               .scan.qr.type == \"url\" and .scan.qr.url.domain.valid\n        )"
         macro "any(file.explode(.),\n            any([.scan.strings.raw, .scan.ocr.raw],\n                regex.icontains(., 'scan|camera|review and sign')\n                and regex.icontains(., '\\bQR\\b|Q\\.R\\.|barcode')\n            )\n        )"
       macro "any(file.explode(.),\n              // review/change terms in file content\n              any([.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title],\n                  (\n                    regex.icontains(.,\n                                    '\\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\\b'\n                    )\n                  )\n              )\n              or (\n                // recipient local_part in attachment body\n                any(recipients.to,\n                    strings.contains(..scan.ocr.raw, .email.local_part)\n                )\n                and (\n                  // NLU cred_theft disposition\n                  any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                      .name == \"cred_theft\" and .confidence != \"low\"\n                  )\n                  // suspicious topics\n                  and any(ml.nlu_classifier(.scan.ocr.raw).topics,\n                          .name in (\n                            \"Benefit Enrollment\",\n                            \"Financial Communications\"\n                          )\n                          and .confidence != \"low\"\n                  )\n                )\n              )\n      )"
  or
    and
      not
        and
          headers.auth_summary.dmarc.pass eq "true"
          headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.domain macro "sender.email.domain.domain in org_domains"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    not
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
    not
      profile.by_sender_email func_call "profile.by_sender_email().solicited"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  any(attachments)
    or
      attachments.content_type eq "application/pdf"
      attachments.file_type eq "pdf"
  or
    body.current_thread.text is_null
    body.current_thread.text length_compare "500"
     macro "(\n      any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,\n                     .name == \"disclaimer\"\n              ),\n              .text\n          ),\n          (length(body.current_thread.text) - length(.)) < 500\n      )\n    )"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textis_null
  • (no value, null check)
field:"body.current_thread.text" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: Compensation-themed DOCX with QR code credential theft

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

Detects inbound messages containing DOCX attachments with compensation or benefit-related themes that include QR codes and suspicious indicators. The rule identifies files with reward/benefit language in filenames, compensation-related content in document metadata, and QR codes that may redirect to credential theft pages. It uses natural language processing to detect credential theft intent and suspicious topics like benefit enrollment or financial communications.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code, Social engineering, Impersonation: Brand

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • recipients
  • recipients.to
  • sender.email
  • type

Rule Body

type.inbound
and (
  length(filter(attachments, .file_type == "docx")) >= 1
  and (
    // short or null message body
    (
      length(body.current_thread.text) < 500 or body.current_thread.text is null
    )
    // ignore disclaimers in body length calculation
    or (
      any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,
                     .name == "disclaimer"
              ),
              .text
          ),
          (length(body.current_thread.text) - length(.)) < 500
      )
    )
  )
)
and (
  // attached DOCX contains a compensation review themed lure with a QR code and suspicious indicators
  any(filter(attachments, .file_type == "docx"),
      // add conditions for DOCX attachment
      (
        regex.icontains(.file_name,
                        '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)'
        )
        // recipient email SLD in filename
        or any(recipients.to,
               strings.icontains(..file_name, .email.domain.sld)
               and .email.domain.valid
        )
        or regex.icontains(beta.parse_exif(.).title,
                           '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)'
        )
      )
      // add conditions for text and any QR code within the DOCX attachment
      and (
        // conditions for QR code via text
        any(file.explode(.),
            any([.scan.strings.raw, .scan.ocr.raw],
                regex.icontains(., 'scan|camera|review and sign')
                and regex.icontains(., '\bQR\b|Q\.R\.|barcode')
            )
            or (
              .scan.qr.type == "url"
              and .scan.qr.url.url is not null
              and any(recipients.to,
                      .email.domain.valid
                      and (
                        strings.icontains(..scan.qr.url.url, .email.email)
                        or any(strings.scan_base64(..scan.qr.url.url,
                                                   format="url"
                               ),
                               strings.icontains(., ..email.email)
                        )
                      )
              )
            )
        )
        or any(file.explode(.),
               .scan.qr.type == "url" and .scan.qr.url.domain.valid
        )
      )
      // conditions for text
      and any(file.explode(.),
              // review/change terms in file content
              any([.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title],
                  (
                    regex.icontains(.,
                                    '\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\b'
                    )
                  )
              )
              or (
                // recipient local_part in attachment body
                any(recipients.to,
                    strings.contains(..scan.ocr.raw, .email.local_part)
                )
                and (
                  // NLU cred_theft disposition
                  any(ml.nlu_classifier(.scan.ocr.raw).intents,
                      .name == "cred_theft" and .confidence != "low"
                  )
                  // suspicious topics
                  and any(ml.nlu_classifier(.scan.ocr.raw).topics,
                          .name in (
                            "Benefit Enrollment",
                            "Financial Communications"
                          )
                          and .confidence != "low"
                  )
                )
              )
      )
  )
)

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

Detects inbound messages containing DOCX attachments with compensation or benefit-related themes that include QR codes and suspicious indicators. The rule identifies files with reward/benefit language in filenames, compensation-related content in document metadata, and QR codes that may redirect to credential theft pages. It uses natural language processing to detect credential theft intent and suspicious topics like benefit enrollment or financial communications.

  1. inbound message
  2. all of:
    • length(filter(attachments, .file_type == "docx")) >= 1
    • any of:
      • any of:
        • length(body.current_thread.text) < 500
        • body.current_thread.text is missing
      • ( any(map(filter(ml.nlu_classifier(body.current_thread.text).entities, .name == "disclaimer" ), .text ), (length(body.current_thread.text) - length(.)) < 500 ) )
  3. ( // attached DOCX contains a compensation review themed lure with a QR code and suspicious indicators any(filter(attachments, .file_type == "docx"), // add conditions for DOCX attachment ( regex.icontains(.file_name, '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)' ) // recipient email SLD in filename or any(recipients.to, strings.icontains(..file_name, .email.domain.sld) and .email.domain.valid ) or regex.icontains(beta.parse_exif(.).title, '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)' ) ) // add conditions for text and any QR code within the DOCX attachment and ( // conditions for QR code via text any(file.explode(.), any([.scan.strings.raw, .scan.ocr.raw], regex.icontains(., 'scan|camera|review and sign') and regex.icontains(., '\bQR\b|Q\.R\.|barcode') ) or ( .scan.qr.type == "url" and .scan.qr.url.url is not null and any(recipients.to, .email.domain.valid and ( strings.icontains(..scan.qr.url.url, .email.email) or any(strings.scan_base64(..scan.qr.url.url, format="url" ), strings.icontains(., ..email.email) ) ) ) ) ) or any(file.explode(.), .scan.qr.type == "url" and .scan.qr.url.domain.valid ) ) // conditions for text and any(file.explode(.), // review/change terms in file content any([.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title], ( regex.icontains(., '\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\b' ) ) ) or ( // recipient local_part in attachment body any(recipients.to, strings.contains(..scan.ocr.raw, .email.local_part) ) and ( // NLU cred_theft disposition any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence != "low" ) // suspicious topics and any(ml.nlu_classifier(.scan.ocr.raw).topics, .name in ( "Benefit Enrollment", "Financial Communications" ) and .confidence != "low" ) ) ) ) ) )
  4. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_type, body.current_thread.text, headers.auth_summary.dmarc.pass, recipients.to, recipients.to[].email.domain.sld, recipients.to[].email.domain.valid, recipients.to[].email.email, recipients.to[].email.local_part, sender.email.domain.root_domain, type.inbound. Sensors: beta.parse_exif, file.explode, ml.nlu_classifier, regex.icontains, strings.contains, strings.icontains, strings.scan_base64. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (10)

FieldMatchValue
attachments[].file_typeequalsdocx
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsdisclaimer
regex.icontainsregex(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)
regex.icontainsregexscan|camera|review and sign
regex.icontainsregex\bQR\b|Q\.R\.|barcode
file.explode(filter(attachments)[])[].scan.qr.typeequalsurl
regex.icontainsregex\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\b
ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).topics[].namememberBenefit Enrollment
ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).topics[].namememberFinancial Communications

Stages and Predicates

Stage 1: mql_rule

and
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  or
    body.current_thread.text is_null
    body.current_thread.text length_compare "500"
     macro "(\n      any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,\n                     .name == \"disclaimer\"\n              ),\n              .text\n          ),\n          (length(body.current_thread.text) - length(.)) < 500\n      )\n    )"
  length func_call "length(filter(attachments, .file_type == \"docx\")) >= 1"
  type.inbound eq "true"
   macro "(\n  // attached DOCX contains a compensation review themed lure with a QR code and suspicious indicators\n  any(filter(attachments, .file_type == \"docx\"),\n      // add conditions for DOCX attachment\n      (\n        regex.icontains(.file_name,\n                        '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)'\n        )\n        // recipient email SLD in filename\n        or any(recipients.to,\n               strings.icontains(..file_name, .email.domain.sld)\n               and .email.domain.valid\n        )\n        or regex.icontains(beta.parse_exif(.).title,\n                           '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)'\n        )\n      )\n      // add conditions for text and any QR code within the DOCX attachment\n      and (\n        // conditions for QR code via text\n        any(file.explode(.),\n            any([.scan.strings.raw, .scan.ocr.raw],\n                regex.icontains(., 'scan|camera|review and sign')\n                and regex.icontains(., '\\bQR\\b|Q\\.R\\.|barcode')\n            )\n            or (\n              .scan.qr.type == \"url\"\n              and .scan.qr.url.url is not null\n              and any(recipients.to,\n                      .email.domain.valid\n                      and (\n                        strings.icontains(..scan.qr.url.url, .email.email)\n                        or any(strings.scan_base64(..scan.qr.url.url,\n                                                   format=\"url\"\n                               ),\n                               strings.icontains(., ..email.email)\n                        )\n                      )\n              )\n            )\n        )\n        or any(file.explode(.),\n               .scan.qr.type == \"url\" and .scan.qr.url.domain.valid\n        )\n      )\n      // conditions for text\n      and any(file.explode(.),\n              // review/change terms in file content\n              any([.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title],\n                  (\n                    regex.icontains(.,\n                                    '\\b(?:Remuneration Overview|Updated Compensation (?:Summary|Schedule|Details)|Access Your Statements?|Staff Performance Appraisal|Compensation Adjustment|performance appraisal|Appraisal Overview|appraisal and compensation|salary (?:increment|deduction))\\b'\n                    )\n                  )\n              )\n              or (\n                // recipient local_part in attachment body\n                any(recipients.to,\n                    strings.contains(..scan.ocr.raw, .email.local_part)\n                )\n                and (\n                  // NLU cred_theft disposition\n                  any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                      .name == \"cred_theft\" and .confidence != \"low\"\n                  )\n                  // suspicious topics\n                  and any(ml.nlu_classifier(.scan.ocr.raw).topics,\n                          .name in (\n                            \"Benefit Enrollment\",\n                            \"Financial Communications\"\n                          )\n                          and .confidence != \"low\"\n                  )\n                )\n              )\n      )\n  )\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textis_null
  • (no value, null check)
field:"body.current_thread.text" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: Credit card application with WhatsApp contact

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

Detects messages containing promotional credit card offers with attached forms requesting extensive personal information (PII) and directing victims to contact via WhatsApp, indicating potential fraud.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesSocial engineering, Out of band pivot

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • body.current_thread
  • subject
  • type

Rule Body

type.inbound
// promotional/advertising content targeting financial services
and (
  (
    regex.icontains(body.current_thread.text,
                    "credit card.*offer|promotional.*credit|free.*credit card|lifetime.*free|special offer"
    )
    or regex.icontains(subject.subject,
                       "credit card.*offer|promotional.*credit|free.*credit card|lifetime.*free"
    )
  )
  and any(ml.nlu_classifier(body.current_thread.text).topics,
          .name in ("Advertising and Promotions")
  )
)
// PII harvesting template in attachments (3+ of these patterns)
and any(attachments,
        any(file.explode(.),
            3 of (
              regex.icontains(.scan.strings.raw, "Credit Card Application"),
              regex.icontains(.scan.strings.raw, "Date of Birth"),
              regex.icontains(.scan.strings.raw, "[eE]mail"),
              regex.icontains(.scan.strings.raw, "[aA]ddress"),
              regex.icontains(.scan.strings.raw, "Contact No"),
              regex.icontains(.scan.strings.raw, "Pan No"),
              regex.icontains(.scan.strings.raw, "ADHAAR"),
              regex.icontains(.scan.strings.raw, "Annual.*salary"),
              regex.icontains(.scan.strings.raw, "Mother Name"),
              regex.icontains(.scan.strings.raw, "Father Name"),
              regex.icontains(.scan.strings.raw, "SINGLE.*MARRIED")
            )
        )
)
// WhatsApp contact method (suspicious for legitimate financial institutions)
and (
  regex.icontains(body.current_thread.text, "whatsapp")
  or any(attachments,
         any(file.explode(.), regex.icontains(.scan.qr.url.url, "wa\\.me"))
  )
  or any(file.explode(file.message_screenshot()),
         regex.icontains(.scan.qr.url.url, "wa\\.me")
  )
)

Detection Logic

Scope: inbound message.

Detects messages containing promotional credit card offers with attached forms requesting extensive personal information (PII) and directing victims to contact via WhatsApp, indicating potential fraud.

  1. inbound message
  2. all of:
    • any of:
      • body.current_thread.text matches 'credit card.*offer|promotional.*credit|free.*credit card|lifetime.*free|special offer'
      • subject.subject matches 'credit card.*offer|promotional.*credit|free.*credit card|lifetime.*free'
    • any(ml.nlu_classifier(body.current_thread.text).topics, .name in ("Advertising and Promotions") )
  3. any of attachments where:
    • any(file.explode(.), 3 of ( regex.icontains(.scan.strings.raw, "Credit Card Application"), regex.icontains(.scan.strings.raw, "Date of Birth"), regex.icontains(.scan.strings.raw, "[eE]mail"), regex.icontains(.scan.strings.raw, "[aA]ddress"), regex.icontains(.scan.strings.raw, "Contact No"), regex.icontains(.scan.strings.raw, "Pan No"), regex.icontains(.scan.strings.raw, "ADHAAR"), regex.icontains(.scan.strings.raw, "Annual.*salary"), regex.icontains(.scan.strings.raw, "Mother Name"), regex.icontains(.scan.strings.raw, "Father Name"), regex.icontains(.scan.strings.raw, "SINGLE.*MARRIED") ) )
  4. any of:
    • body.current_thread.text matches 'whatsapp'
    • any of attachments where:
      • any(file.explode(.), regex.icontains(.scan.qr.url.url, "wa\\.me"))
    • any(file.explode(file.message_screenshot()), regex.icontains(.scan.qr.url.url, "wa\\.me") )

Inspects: body.current_thread.text, subject.subject, type.inbound. Sensors: file.explode, file.message_screenshot, ml.nlu_classifier, regex.icontains.

Indicators Matched (16)

FieldMatchValue
regex.icontainsregexcredit card.*offer|promotional.*credit|free.*credit card|lifetime.*free|special offer
regex.icontainsregexcredit card.*offer|promotional.*credit|free.*credit card|lifetime.*free
ml.nlu_classifier(body.current_thread.text).topics[].namememberAdvertising and Promotions
regex.icontainsregexCredit Card Application
regex.icontainsregexDate of Birth
regex.icontainsregex[eE]mail
regex.icontainsregex[aA]ddress
regex.icontainsregexContact No
regex.icontainsregexPan No
regex.icontainsregexADHAAR
regex.icontainsregexAnnual.*salary
regex.icontainsregexMother Name
4 more
regex.icontainsregexFather Name
regex.icontainsregexSINGLE.*MARRIED
regex.icontainsregexwhatsapp
regex.icontainsregexwa\\.me

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
       macro "any(file.explode(.), regex.icontains(.scan.qr.url.url, \"wa\\\\.me\"))"
    body.current_thread.text regex_match "whatsapp"
     macro "any(file.explode(file.message_screenshot()),\n         regex.icontains(.scan.qr.url.url, \"wa\\\\.me\")\n  )"
  or
    body.current_thread.text regex_match "credit card.*offer|promotional.*credit|free.*credit card|lifetime.*free|special offer"
    subject.subject regex_match "credit card.*offer|promotional.*credit|free.*credit card|lifetime.*free"
  any(attachments)
     macro "any(file.explode(.),\n            3 of (\n              regex.icontains(.scan.strings.raw, \"Credit Card Application\"),\n              regex.icontains(.scan.strings.raw, \"Date of Birth\"),\n              regex.icontains(.scan.strings.raw, \"[eE]mail\"),\n              regex.icontains(.scan.strings.raw, \"[aA]ddress\"),\n              regex.icontains(.scan.strings.raw, \"Contact No\"),\n              regex.icontains(.scan.strings.raw, \"Pan No\"),\n              regex.icontains(.scan.strings.raw, \"ADHAAR\"),\n              regex.icontains(.scan.strings.raw, \"Annual.*salary\"),\n              regex.icontains(.scan.strings.raw, \"Mother Name\"),\n              regex.icontains(.scan.strings.raw, \"Father Name\"),\n              regex.icontains(.scan.strings.raw, \"SINGLE.*MARRIED\")\n            )\n        )"
  type.inbound eq "true"
   macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n          .name in (\"Advertising and Promotions\")\n  )"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textregex_match
    • credit card.*offer
    • promotional.*credit
    • free.*credit card
    • lifetime.*free
    • special offer
  • whatsapp
field:"body.current_thread.text" kind:regex_match
subject.subjectregex_match
    • credit card.*offer
    • promotional.*credit
    • free.*credit card
    • lifetime.*free
field:"subject.subject" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: CVE-2023-21716 - Microsoft Office Remote Code Execution Vulnerability

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

Attachment contains an RTF file with a font table defining an excessive number of fonts, used to exploit CVE-2023-21716.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesExploit

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("rtf", "doc", "docx")
          or .file_extension in~ $file_extensions_common_archives
          or .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.),
                any(.scan.strings.strings, strings.ilike(., '*\fonttbl*'))
                and length(filter(.scan.strings.strings,
                                  strings.ilike(., '{\f*;}')
                           )
                ) > 10000
        )
)

Detection Logic

Scope: inbound message.

Attachment contains an RTF file with a font table defining an excessive number of fonts, used to exploit CVE-2023-21716.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('rtf', 'doc', 'docx')
      • .file_extension in $file_extensions_common_archives
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., '*\fonttbl*')) and length(filter(.scan.strings.strings, strings.ilike(., '{\f*;}') ) ) > 10000 )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberrtf
attachments[].file_extensionmemberdoc
attachments[].file_extensionmemberdocx
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
strings.ilikesubstring*\fonttbl*
strings.ilikesubstring{\f*;}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension in ["doc", "docx", "rtf"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                any(.scan.strings.strings, strings.ilike(., '*\\fonttbl*'))\n                and length(filter(.scan.strings.strings,\n                                  strings.ilike(., '{\\f*;}')\n                           )\n                ) > 10000\n        )"
  type.inbound eq "true"

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"

Attachment: Decoy PDF author (Julie P.)

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

This detection rule matches on messages containing one or more Decoy PDF attachments with metadata discovered to have been assoicated with malicious email campaigns featuring CrowdStrike, DocuSign, Human Resource and password expiration lures.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(attachments) > 0
and any(attachments,
        .size <= 250000
        and .file_extension == "pdf"
        and any(file.explode(.),
                (
                  .scan.exiftool.producer == "DocFly"
                  or any(.scan.exiftool.fields,
                         .key == "XMPToolkit"
                         and strings.icontains(.value, 'DynaPDF')
                  )
                )
                and (
                  any(.scan.exiftool.fields,
                      .key == "CreatorTool"
                      and .value == "Acrobat PDFMaker 24 for Word"
                  )
                  or any(.scan.exiftool.fields,
                         .key == "ContentTypeId"
                         and .value == "2.2388136001807807e+43"
                  )
                  or any(.scan.exiftool.fields,
                         .key == "Creator"
                         and .value in ('Julie Peters', 'Julie Pieters')
                  )
                  or any(.scan.exiftool.fields,
                         .key == "Author"
                         and .value in ('Julie Peters', 'Julie Pieters')
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

This detection rule matches on messages containing one or more Decoy PDF attachments with metadata discovered to have been assoicated with malicious email campaigns featuring CrowdStrike, DocuSign, Human Resource and password expiration lures.

  1. inbound message
  2. length(attachments) > 0
  3. any of attachments where all hold:
    • .size ≤ 250000
    • .file_extension is 'pdf'
    • any(file.explode(.), ( .scan.exiftool.producer == "DocFly" or any(.scan.exiftool.fields, .key == "XMPToolkit" and strings.icontains(.value, 'DynaPDF') ) ) and ( any(.scan.exiftool.fields, .key == "CreatorTool" and .value == "Acrobat PDFMaker 24 for Word" ) or any(.scan.exiftool.fields, .key == "ContentTypeId" and .value == "2.2388136001807807e+43" ) or any(.scan.exiftool.fields, .key == "Creator" and .value in ('Julie Peters', 'Julie Pieters') ) or any(.scan.exiftool.fields, .key == "Author" and .value in ('Julie Peters', 'Julie Pieters') ) ) )

Inspects: attachments[].file_extension, attachments[].size, type.inbound. Sensors: file.explode, strings.icontains.

Indicators Matched (12)

FieldMatchValue
attachments[].file_extensionequalspdf
file.explode(attachments[])[].scan.exiftool.producerequalsDocFly
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsXMPToolkit
strings.icontainssubstringDynaPDF
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsCreatorTool
file.explode(attachments[])[].scan.exiftool.fields[].valueequalsAcrobat PDFMaker 24 for Word
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsContentTypeId
file.explode(attachments[])[].scan.exiftool.fields[].valueequals2.2388136001807807e+43
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsCreator
file.explode(attachments[])[].scan.exiftool.fields[].valuememberJulie Peters
file.explode(attachments[])[].scan.exiftool.fields[].valuememberJulie Pieters
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsAuthor

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension eq "pdf"
      attachments.size le "250000"
       macro "any(file.explode(.),\n                (\n                  .scan.exiftool.producer == \"DocFly\"\n                  or any(.scan.exiftool.fields,\n                         .key == \"XMPToolkit\"\n                         and strings.icontains(.value, 'DynaPDF')\n                  )\n                )\n                and (\n                  any(.scan.exiftool.fields,\n                      .key == \"CreatorTool\"\n                      and .value == \"Acrobat PDFMaker 24 for Word\"\n                  )\n                  or any(.scan.exiftool.fields,\n                         .key == \"ContentTypeId\"\n                         and .value == \"2.2388136001807807e+43\"\n                  )\n                  or any(.scan.exiftool.fields,\n                         .key == \"Creator\"\n                         and .value in ('Julie Peters', 'Julie Pieters')\n                  )\n                  or any(.scan.exiftool.fields,\n                         .key == \"Author\"\n                         and .value in ('Julie Peters', 'Julie Pieters')\n                  )\n                )\n        )"
  attachments length_compare "0"
  type.inbound eq "true"

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"

Attachment: DocuSign impersonation via PDF linking to new domain

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

This rule detects PDF files containing a DocuSign logo linking to a newly created domain (Less than or equal to 3 days)

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • headers.hops
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type == "pdf"
        and any(ml.logo_detect(.).brands, .name == "DocuSign")
        and any(file.explode(.),
                any(.scan.pdf.urls, network.whois(.domain).days_old <= 3)
        )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

// excludes senders that contain "via" in the display name a resilient way
and not (
  any(headers.hops,
      any(.fields,
          .name == "X-Api-Host" and strings.ends_with(.value, "docusign.net")
      )
  )
)

Detection Logic

Scope: inbound message.

This rule detects PDF files containing a DocuSign logo linking to a newly created domain (Less than or equal to 3 days)

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • any(ml.logo_detect(.).brands, .name == "DocuSign")
    • any(file.explode(.), any(.scan.pdf.urls, network.whois(.domain).days_old <= 3) )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  4. not:
    • any of headers.hops where:
      • any of .fields where all hold:
        • .name is 'X-Api-Host'
        • .value ends with 'docusign.net'

Inspects: attachments[].file_type, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, headers.hops[].fields[].value, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.logo_detect, network.whois, strings.ends_with. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
ml.logo_detect(attachments[]).brands[].nameequalsDocuSign

Stages and Predicates

Stage 1: mql_rule

and
  not
    any(headers.hops)
      any(headers.hops.fields)
        and
          headers.hops.fields[].name eq "X-Api-Host"
          headers.hops.fields[].value ends_with "docusign.net"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  any(attachments)
    and
      attachments.file_type eq "pdf"
       macro "any(file.explode(.),\n                any(.scan.pdf.urls, network.whois(.domain).days_old <= 3)\n        )"
       macro "any(ml.logo_detect(.).brands, .name == \"DocuSign\")"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops

Attachment: DocX embedded binary

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

This rule is designed to detect sophisticated phishing attacks that deliver binary payloads through MS office open XML files. It identifies malicious documents containing embedded scripts or objects, either encoded in base64 or using specific JavaScript functions like createObjectURL or msSaveOrOpenBlob, which are indicative of attempts to download and execute a binary payload.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or .file_extension in~ $file_extensions_common_archives
          or .content_type == "application/zip"
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.),
                .file_extension in~ (
                  "doc",
                  "docm",
                  "docx",
                  "dot",
                  "dotm",
                  "xls",
                  "xlsx",
                  "xlsm",
                  "xlm",
                  "xlsb",
                  "xlt",
                  "xltm",
                  "ppt",
                  "pptx",
                  "pptm",
                  "ppsm"
                )
                and (
                  any(.flavors.yara, . == "base64_pe")
                  // The malicious file to be downloaded and run with the data URI may not always be portable executable
                  or any(.scan.strings.strings,
                         strings.ilike(., "*.createObjectURL(*)*")
                  )
                  or any(.scan.strings.strings,
                         strings.ilike(., "*.msSaveOrOpenBlob(*)*")
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

This rule is designed to detect sophisticated phishing attacks that deliver binary payloads through MS office open XML files. It identifies malicious documents containing embedded scripts or objects, either encoded in base64 or using specific JavaScript functions like createObjectURL or msSaveOrOpenBlob, which are indicative of attempts to download and execute a binary payload.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • .content_type is 'application/zip'
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), .file_extension in~ ( "doc", "docm", "docx", "dot", "dotm", "xls", "xlsx", "xlsm", "xlm", "xlsb", "xlt", "xltm", "ppt", "pptx", "pptm", "ppsm" ) and ( any(.flavors.yara, . == "base64_pe") // The malicious file to be downloaded and run with the data URI may not always be portable executable or any(.scan.strings.strings, strings.ilike(., "*.createObjectURL(*)*") ) or any(.scan.strings.strings, strings.ilike(., "*.msSaveOrOpenBlob(*)*") ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (22)

FieldMatchValue
attachments[].content_typeequalsapplication/zip
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
file.explode(attachments[])[].file_extensionmemberdoc
file.explode(attachments[])[].file_extensionmemberdocm
file.explode(attachments[])[].file_extensionmemberdocx
file.explode(attachments[])[].file_extensionmemberdot
file.explode(attachments[])[].file_extensionmemberdotm
file.explode(attachments[])[].file_extensionmemberxls
file.explode(attachments[])[].file_extensionmemberxlsx
file.explode(attachments[])[].file_extensionmemberxlsm
file.explode(attachments[])[].file_extensionmemberxlm
10 more
file.explode(attachments[])[].file_extensionmemberxlsb
file.explode(attachments[])[].file_extensionmemberxlt
file.explode(attachments[])[].file_extensionmemberxltm
file.explode(attachments[])[].file_extensionmemberppt
file.explode(attachments[])[].file_extensionmemberpptx
file.explode(attachments[])[].file_extensionmemberpptm
file.explode(attachments[])[].file_extensionmemberppsm
file.explode(attachments[])[].flavors.yara[]equalsbase64_pe
strings.ilikesubstring*.createObjectURL(*)*
strings.ilikesubstring*.msSaveOrOpenBlob(*)*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.content_type eq "application/zip"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                .file_extension in~ (\n                  \"doc\",\n                  \"docm\",\n                  \"docx\",\n                  \"dot\",\n                  \"dotm\",\n                  \"xls\",\n                  \"xlsx\",\n                  \"xlsm\",\n                  \"xlm\",\n                  \"xlsb\",\n                  \"xlt\",\n                  \"xltm\",\n                  \"ppt\",\n                  \"pptx\",\n                  \"pptm\",\n                  \"ppsm\"\n                )\n                and (\n                  any(.flavors.yara, . == \"base64_pe\")\n                  // The malicious file to be downloaded and run with the data URI may not always be portable executable\n                  or any(.scan.strings.strings,\n                         strings.ilike(., \"*.createObjectURL(*)*\")\n                  )\n                  or any(.scan.strings.strings,\n                         strings.ilike(., \"*.msSaveOrOpenBlob(*)*\")\n                  )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: DOCX with hyperlink targeting recipient address

#

Attachment: DOCX with malicious document template artifacts

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

Detects inbound messages containing DOCX attachments with artifacts associated with malicious document templates.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Exploit

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "docx"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name in ("malicious_docx_document_template_artifacts")
            )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing DOCX attachments with artifacts associated with malicious document templates.

  1. inbound message
  2. any(filter(attachments, .file_type == "docx"), any(file.explode(.), any(.scan.yara.matches, .name in ("malicious_docx_document_template_artifacts") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalsdocx
file.explode(filter(attachments)[])[].scan.yara.matches[].namemembermalicious_docx_document_template_artifacts

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"docx\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name in (\"malicious_docx_document_template_artifacts\")\n            )\n        )\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"

Attachment: Double base64-encoded zip file in HTML smuggling attachment

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

Qakbot double Base64 encodes zip files within their HTML smuggling email attachments. This leads to predictable file header strings appearing in the HTML string content.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in ("html", "htm")
        and any(file.explode(.),
                any(.scan.strings.strings,
                    strings.ilike(.,
                                  // Double Base64 encoded zips
                                  "*VUVzREJCUUFBUUFJQ*",
                                  "*VFc0RCQlFBQVFBSU*",
                                  "*VRXNEQkJRQUFRQUlB*",
                                  // Reversed base64 strings double encoded zips
                                  "*QJFUUBFUUCJERzVUV*",
                                  "*USBFVQBFlQCR0cFV*",
                                  "*BlUQRFUQRJkQENXRV*"
                    )
                )
        )
)

Detection Logic

Scope: inbound message.

Qakbot double Base64 encodes zip files within their HTML smuggling email attachments. This leads to predictable file header strings appearing in the HTML string content.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in ('html', 'htm')
    • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., // Double Base64 encoded zips "*VUVzREJCUUFBUUFJQ*", "*VFc0RCQlFBQVFBSU*", "*VRXNEQkJRQUFRQUlB*", // Reversed base64 strings double encoded zips "*QJFUUBFUUCJERzVUV*", "*USBFVQBFlQCR0cFV*", "*BlUQRFUQRJkQENXRV*" ) ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, strings.ilike.

Indicators Matched (8)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
strings.ilikesubstring*VUVzREJCUUFBUUFJQ*
strings.ilikesubstring*VFc0RCQlFBQVFBSU*
strings.ilikesubstring*VRXNEQkJRQUFRQUlB*
strings.ilikesubstring*QJFUUBFUUCJERzVUV*
strings.ilikesubstring*USBFVQBFlQCR0cFV*
strings.ilikesubstring*BlUQRFUQRJkQENXRV*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension in ["htm", "html"]
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    strings.ilike(.,\n                                  // Double Base64 encoded zips\n                                  \"*VUVzREJCUUFBUUFJQ*\",\n                                  \"*VFc0RCQlFBQVFBSU*\",\n                                  \"*VRXNEQkJRQUFRQUlB*\",\n                                  // Reversed base64 strings double encoded zips\n                                  \"*QJFUUBFUUCJERzVUV*\",\n                                  \"*USBFVQBFlQCR0cFV*\",\n                                  \"*BlUQRFUQRJkQENXRV*\"\n                    )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: Dropbox image lure with no Dropbox domains in links

#

Attachment: Duplicated header pages in fraudulent multi-page PDF Request for Quotation

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

Detects inbound PDF attachments between 2-3 pages where the first three lines of the header text appear nearly identical (within a Levenshtein distance of 5) on multiple pages, combined with terminology commonly found in fraudulent Request for Quotation (RFQ) documents such as procurement language, payment conditions, and preference point systems. This pattern is consistent with fabricated or manipulated procurement documents used in BEC or fraud schemes.

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
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type == "pdf"
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and 1 < beta.parse_exif(.).page_count <= 3
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and beta.ocr(.).page_results[0].text != ""
        // extract the first 3 lines from the first page
        and any(regex.iextract(beta.ocr(.).page_results[0].text,
                               '^(?P<page_1_3_lines>(?:[^\r\n]+[\r\n]+){3})'
                ),
                // make sure we have something
                .named_groups["page_1_3_lines"] != ""
                // either page 2 or page 3 contain VERY close text
                // we have to do very close because sometimes the address format changes in trivial ways
                // like a comma is removed or something
                and (
                  any(regex.iextract(beta.ocr(..).page_results[1].text,
                                     '^(?P<page_2_3_lines>(?:[^\r\n]+[\r\n]+){3})'
                      ),
                      strings.levenshtein(.named_groups["page_2_3_lines"],
                                          ..named_groups["page_1_3_lines"]
                      ) <= 5
                  )
                  or any(regex.iextract(beta.ocr(..).page_results[2].text,
                                        '^(?P<page_3_3_lines>(?:[^\r\n]+[\r\n]+){3})'
                         ),
                         strings.levenshtein(.named_groups["page_3_3_lines"],
                                             ..named_groups["page_1_3_lines"]
                         ) <= 5
                  )
                )
        )
        and (
          3 of (
            strings.icontains(beta.ocr(.).text,
                              "Contact Person",
                              "Date of issue",
                              "Date Issued",
                              "Closing Time and Date",
                              "Closing Date",
                              "QUOTATIONS ARE HEREBY INVITED FOR THE SUPPLY OF",
                              "COMPULSORY BIDDERS MUST QUOTE",
                              "Method of RFQ Submission"
            ),
            strings.icontains(beta.ocr(.).text,
                              "Must be inclusive",
                              "Tax on Price Quotation",
                              "100% payment made in the form",
                              "Conditions for Release of Payment",
                              "Period of Validity of Quotes",
                              "Partial Bids",
                              "PRICING QUOTATION",
                              "Payment Terms and Conditions",
                              "freight, insurance until acceptance"
            ),
            strings.icontains(beta.ocr(.).text,
                              "80/20 preference point system",
                              "80:20",
                              "Selection of suppliers will be based on",
                              "plant upgrade and maintenance",
                              "plant maintenance",
                              "without an Official Purchase Order",
                              "If unable to quote"
            ),
            strings.icontains(beta.ocr(.).text,
                              "remain binding upon me/us",
                              "Authorized Signature",
                              "Name and Capacity",
                              "must be completed and accompanied by",
                              "This is not a Purchase Order"
            )
          )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound PDF attachments between 2-3 pages where the first three lines of the header text appear nearly identical (within a Levenshtein distance of 5) on multiple pages, combined with terminology commonly found in fraudulent Request for Quotation (RFQ) documents such as procurement language, payment conditions, and preference point systems. This pattern is consistent with fabricated or manipulated procurement documents used in BEC or fraud schemes.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • all of:
      • (1) < (beta.parse_exif(.).page_count)
      • (beta.parse_exif(.).page_count) <= (3)
    • beta.ocr(.).page_results[0].text != ""
    • any(regex.iextract(beta.ocr(.).page_results[0].text, '^(?P<page_1_3_lines>(?:[^\r\n]+[\r\n]+){3})' ), // make sure we have something .named_groups["page_1_3_lines"] != "" // either page 2 or page 3 contain VERY close text // we have to do very close because sometimes the address format changes in trivial ways // like a comma is removed or something and ( any(regex.iextract(beta.ocr(..).page_results[1].text, '^(?P<page_2_3_lines>(?:[^\r\n]+[\r\n]+){3})' ), strings.levenshtein(.named_groups["page_2_3_lines"], ..named_groups["page_1_3_lines"] ) <= 5 ) or any(regex.iextract(beta.ocr(..).page_results[2].text, '^(?P<page_3_3_lines>(?:[^\r\n]+[\r\n]+){3})' ), strings.levenshtein(.named_groups["page_3_3_lines"], ..named_groups["page_1_3_lines"] ) <= 5 ) ) )
    • at least 3 of:
      • strings.icontains(beta.ocr(.).text, "Contact Person", "Date of issue", "Date Issued", "Closing Time and Date", "Closing Date", "QUOTATIONS ARE HEREBY INVITED FOR THE SUPPLY OF", "COMPULSORY BIDDERS MUST QUOTE", "Method of RFQ Submission" )
      • strings.icontains(beta.ocr(.).text, "Must be inclusive", "Tax on Price Quotation", "100% payment made in the form", "Conditions for Release of Payment", "Period of Validity of Quotes", "Partial Bids", "PRICING QUOTATION", "Payment Terms and Conditions", "freight, insurance until acceptance" )
      • strings.icontains(beta.ocr(.).text, "80/20 preference point system", "80:20", "Selection of suppliers will be based on", "plant upgrade and maintenance", "plant maintenance", "without an Official Purchase Order", "If unable to quote" )
      • strings.icontains(beta.ocr(.).text, "remain binding upon me/us", "Authorized Signature", "Name and Capacity", "must be completed and accompanied by", "This is not a Purchase Order" )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.ocr, beta.parse_exif, regex.iextract, strings.icontains, strings.levenshtein.

Indicators Matched (33)

FieldMatchValue
attachments[].file_typeequalspdf
regex.iextractregex^(?P<page_1_3_lines>(?:[^\r\n]+[\r\n]+){3})
regex.iextractregex^(?P<page_2_3_lines>(?:[^\r\n]+[\r\n]+){3})
regex.iextractregex^(?P<page_3_3_lines>(?:[^\r\n]+[\r\n]+){3})
strings.icontainssubstringContact Person
strings.icontainssubstringDate of issue
strings.icontainssubstringDate Issued
strings.icontainssubstringClosing Time and Date
strings.icontainssubstringClosing Date
strings.icontainssubstringQUOTATIONS ARE HEREBY INVITED FOR THE SUPPLY OF
strings.icontainssubstringCOMPULSORY BIDDERS MUST QUOTE
strings.icontainssubstringMethod of RFQ Submission
21 more
strings.icontainssubstringMust be inclusive
strings.icontainssubstringTax on Price Quotation
strings.icontainssubstring100% payment made in the form
strings.icontainssubstringConditions for Release of Payment
strings.icontainssubstringPeriod of Validity of Quotes
strings.icontainssubstringPartial Bids
strings.icontainssubstringPRICING QUOTATION
strings.icontainssubstringPayment Terms and Conditions
strings.icontainssubstringfreight, insurance until acceptance
strings.icontainssubstring80/20 preference point system
strings.icontainssubstring80:20
strings.icontainssubstringSelection of suppliers will be based on
strings.icontainssubstringplant upgrade and maintenance
strings.icontainssubstringplant maintenance
strings.icontainssubstringwithout an Official Purchase Order
strings.icontainssubstringIf unable to quote
strings.icontainssubstringremain binding upon me/us
strings.icontainssubstringAuthorized Signature
strings.icontainssubstringName and Capacity
strings.icontainssubstringmust be completed and accompanied by
strings.icontainssubstringThis is not a Purchase Order

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"80/20 preference point system\",\n                              \"80:20\",\n                              \"Selection of suppliers will be based on\",\n                              \"plant upgrade and maintenance\",\n                              \"plant maintenance\",\n                              \"without an Official Purchase Order\",\n                              \"If unable to quote\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"Contact Person\",\n                              \"Date of issue\",\n                              \"Date Issued\",\n                              \"Closing Time and Date\",\n                              \"Closing Date\",\n                              \"QUOTATIONS ARE HEREBY INVITED FOR THE SUPPLY OF\",\n                              \"COMPULSORY BIDDERS MUST QUOTE\",\n                              \"Method of RFQ Submission\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"Must be inclusive\",\n                              \"Tax on Price Quotation\",\n                              \"100% payment made in the form\",\n                              \"Conditions for Release of Payment\",\n                              \"Period of Validity of Quotes\",\n                              \"Partial Bids\",\n                              \"PRICING QUOTATION\",\n                              \"Payment Terms and Conditions\",\n                              \"freight, insurance until acceptance\"\n            )"
        and
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"80/20 preference point system\",\n                              \"80:20\",\n                              \"Selection of suppliers will be based on\",\n                              \"plant upgrade and maintenance\",\n                              \"plant maintenance\",\n                              \"without an Official Purchase Order\",\n                              \"If unable to quote\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"Contact Person\",\n                              \"Date of issue\",\n                              \"Date Issued\",\n                              \"Closing Time and Date\",\n                              \"Closing Date\",\n                              \"QUOTATIONS ARE HEREBY INVITED FOR THE SUPPLY OF\",\n                              \"COMPULSORY BIDDERS MUST QUOTE\",\n                              \"Method of RFQ Submission\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"remain binding upon me/us\",\n                              \"Authorized Signature\",\n                              \"Name and Capacity\",\n                              \"must be completed and accompanied by\",\n                              \"This is not a Purchase Order\"\n            )"
        and
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"80/20 preference point system\",\n                              \"80:20\",\n                              \"Selection of suppliers will be based on\",\n                              \"plant upgrade and maintenance\",\n                              \"plant maintenance\",\n                              \"without an Official Purchase Order\",\n                              \"If unable to quote\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"Must be inclusive\",\n                              \"Tax on Price Quotation\",\n                              \"100% payment made in the form\",\n                              \"Conditions for Release of Payment\",\n                              \"Period of Validity of Quotes\",\n                              \"Partial Bids\",\n                              \"PRICING QUOTATION\",\n                              \"Payment Terms and Conditions\",\n                              \"freight, insurance until acceptance\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"remain binding upon me/us\",\n                              \"Authorized Signature\",\n                              \"Name and Capacity\",\n                              \"must be completed and accompanied by\",\n                              \"This is not a Purchase Order\"\n            )"
        and
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"Contact Person\",\n                              \"Date of issue\",\n                              \"Date Issued\",\n                              \"Closing Time and Date\",\n                              \"Closing Date\",\n                              \"QUOTATIONS ARE HEREBY INVITED FOR THE SUPPLY OF\",\n                              \"COMPULSORY BIDDERS MUST QUOTE\",\n                              \"Method of RFQ Submission\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"Must be inclusive\",\n                              \"Tax on Price Quotation\",\n                              \"100% payment made in the form\",\n                              \"Conditions for Release of Payment\",\n                              \"Period of Validity of Quotes\",\n                              \"Partial Bids\",\n                              \"PRICING QUOTATION\",\n                              \"Payment Terms and Conditions\",\n                              \"freight, insurance until acceptance\"\n            )"
          strings.icontains func_call "strings.icontains(beta.ocr(.).text,\n                              \"remain binding upon me/us\",\n                              \"Authorized Signature\",\n                              \"Name and Capacity\",\n                              \"must be completed and accompanied by\",\n                              \"This is not a Purchase Order\"\n            )"
      attachments.file_type eq "pdf"
      beta.ocr func_call "beta.ocr(.).page_results[0].text != \"\""
      beta.parse_exif func_call "(1) < (beta.parse_exif(.).page_count)"
      beta.parse_exif func_call "(beta.parse_exif(.).page_count) <= (3)"
       macro "any(regex.iextract(beta.ocr(.).page_results[0].text,\n                               '^(?P<page_1_3_lines>(?:[^\\r\\n]+[\\r\\n]+){3})'\n                ),\n                // make sure we have something\n                .named_groups[\"page_1_3_lines\"] != \"\"\n                // either page 2 or page 3 contain VERY close text\n                // we have to do very close because sometimes the address format changes in trivial ways\n                // like a comma is removed or something\n                and (\n                  any(regex.iextract(beta.ocr(..).page_results[1].text,\n                                     '^(?P<page_2_3_lines>(?:[^\\r\\n]+[\\r\\n]+){3})'\n                      ),\n                      strings.levenshtein(.named_groups[\"page_2_3_lines\"],\n                                          ..named_groups[\"page_1_3_lines\"]\n                      ) <= 5\n                  )\n                  or any(regex.iextract(beta.ocr(..).page_results[2].text,\n                                        '^(?P<page_3_3_lines>(?:[^\\r\\n]+[\\r\\n]+){3})'\n                         ),\n                         strings.levenshtein(.named_groups[\"page_3_3_lines\"],\n                                             ..named_groups[\"page_1_3_lines\"]\n                         ) <= 5\n                  )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: EICAR string present

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

This rule detects the EICAR test string, used to evaluate Anti-Virus scanning and file inspection capabilities. For performance reasons, this rule is limited to attachments with "eicar" in the file name.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments, strings.icontains(.file_name, "eicar"))
and any(attachments,
        any(file.explode(.),
            any(.scan.strings.strings,
                strings.icontains(.,
                                  'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'
                )
            )
        )
)

Detection Logic

Scope: inbound message.

This rule detects the EICAR test string, used to evaluate Anti-Virus scanning and file inspection capabilities. For performance reasons, this rule is limited to attachments with "eicar" in the file name.

  1. inbound message
  2. any of attachments where:
    • .file_name contains 'eicar'
  3. any of attachments where:
    • any(file.explode(.), any(.scan.strings.strings, strings.icontains(., 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' ) ) )

Inspects: attachments[].file_name, type.inbound. Sensors: file.explode, strings.icontains.

Indicators Matched (2)

FieldMatchValue
strings.icontainssubstringeicar
strings.icontainssubstringX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    attachments.file_name contains "eicar"
  any(attachments)
     macro "any(file.explode(.),\n            any(.scan.strings.strings,\n                strings.icontains(.,\n                                  'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'\n                )\n            )\n        )"
  type.inbound eq "true"

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"

Attachment: Embedded Javascript in SVG file

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

Javascript inside SVG files can be used to smuggle malicious payloads or execute scripts.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesScripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          (
            .file_extension in~ ("svg", "svgz")
            or .content_type in~ ("image/svg+xml")
            or .file_type == "svg"
          )
          and (
            strings.ilike(file.parse_text(.,
                                          encodings=[
                                            "ascii",
                                            "utf8",
                                            "utf16-le"
                                          ]
                          ).text,
                          "*onload*",
                          "*window.location.href*",
                          "*onerror*",
                          "*CDATA*",
                          "*<script*",
                          "*</script*",
                          "*atob*",
                          "*location.assign*",
                          "*decodeURIComponent*"
            )
            or regex.icontains(file.parse_text(.,
                                               encodings=[
                                                 "ascii",
                                                 "utf8",
                                                 "utf16-le"
                                               ]
                               ).text,
                               '<iframe[^\>]+src\s*=\s*\"data:[^\;]+;base64,'
            )
            or any(beta.scan_base64(file.parse_text(.).text,
                                    encodings=["ascii", "utf8", "utf16-le"]
                   ),
                   strings.ilike(.,
                                 "*onload*",
                                 "*window.location.href*",
                                 "*onerror*",
                                 "*CDATA*",
                                 "*<script*",
                                 "*</script*",
                                 "*atob*",
                                 "*location.assign*",
                                 "*decodeURIComponent*"
                   )
            )
          )
        )
        or (
          (
            .file_extension in $file_extensions_common_archives
            or .file_type == "gz"
            or .content_type == "application/x-gzip"
          )
          and any(file.explode(.),
                  (
                    .file_extension in~ ("svg", "svgz")
                    or .flavors.mime == "image/svg+xml"
                  )
                  and any(.scan.strings.strings,
                          strings.ilike(.,
                                        "*onload*",
                                        "*window.location.href*",
                                        "*onerror*",
                                        "*CDATA*",
                                        "*<script*",
                                        "*</script*",
                                        "*atob*",
                                        "*location.assign*",
                                        "*decodeURIComponent*"
                          )
                  )
          )
        )
)

Detection Logic

Scope: inbound message.

Javascript inside SVG files can be used to smuggle malicious payloads or execute scripts.

  1. inbound message
  2. any of attachments where any holds:
    • all of:
      • any of:
        • .file_extension in ('svg', 'svgz')
        • .content_type in ('image/svg+xml')
        • .file_type is 'svg'
      • any of:
        • strings.ilike(file.parse_text(., encodings=[ "ascii", "utf8", "utf16-le" ] ).text, "*onload*", "*window.location.href*", "*onerror*", "*CDATA*", "*<script*", "*</script*", "*atob*", "*location.assign*", "*decodeURIComponent*" )
        • regex.icontains(file.parse_text(., encodings=[ "ascii", "utf8", "utf16-le" ] ).text, '<iframe[^\>]+src\s*=\s*\"data:[^\;]+;base64,' )
        • any(beta.scan_base64(file.parse_text(.).text, encodings=["ascii", "utf8", "utf16-le"] ), strings.ilike(., "*onload*", "*window.location.href*", "*onerror*", "*CDATA*", "*<script*", "*</script*", "*atob*", "*location.assign*", "*decodeURIComponent*" ) )
    • all of:
      • any of:
        • .file_extension in $file_extensions_common_archives
        • .file_type is 'gz'
        • .content_type is 'application/x-gzip'
      • any(file.explode(.), ( .file_extension in~ ("svg", "svgz") or .flavors.mime == "image/svg+xml" ) and any(.scan.strings.strings, strings.ilike(., "*onload*", "*window.location.href*", "*onerror*", "*CDATA*", "*<script*", "*</script*", "*atob*", "*location.assign*", "*decodeURIComponent*" ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: beta.scan_base64, file.explode, file.parse_text, regex.icontains, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (19)

FieldMatchValue
attachments[].file_extensionmembersvg
attachments[].file_extensionmembersvgz
attachments[].content_typememberimage/svg+xml
attachments[].file_typeequalssvg
strings.ilikesubstring*onload*
strings.ilikesubstring*window.location.href*
strings.ilikesubstring*onerror*
strings.ilikesubstring*CDATA*
strings.ilikesubstring*<script*
strings.ilikesubstring*</script*
strings.ilikesubstring*atob*
strings.ilikesubstring*location.assign*
7 more
strings.ilikesubstring*decodeURIComponent*
regex.icontainsregex<iframe[^\>]+src\s*=\s*\"data:[^\;]+;base64,
attachments[].file_typeequalsgz
attachments[].content_typeequalsapplication/x-gzip
file.explode(attachments[])[].file_extensionmembersvg
file.explode(attachments[])[].file_extensionmembersvgz
file.explode(attachments[])[].flavors.mimeequalsimage/svg+xml

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        or
          attachments.content_type eq "application/x-gzip"
          attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
          attachments.file_type eq "gz"
         macro "any(file.explode(.),\n                  (\n                    .file_extension in~ (\"svg\", \"svgz\")\n                    or .flavors.mime == \"image/svg+xml\"\n                  )\n                  and any(.scan.strings.strings,\n                          strings.ilike(.,\n                                        \"*onload*\",\n                                        \"*window.location.href*\",\n                                        \"*onerror*\",\n                                        \"*CDATA*\",\n                                        \"*<script*\",\n                                        \"*</script*\",\n                                        \"*atob*\",\n                                        \"*location.assign*\",\n                                        \"*decodeURIComponent*\"\n                          )\n                  )\n          )"
      and
        or
          attachments.content_type eq "image/svg+xml"
          attachments.file_extension in ["svg", "svgz"]
          attachments.file_type eq "svg"
        or
          regex.icontains func_call "regex.icontains(file.parse_text(.,\n                                               encodings=[\n                                                 \"ascii\",\n                                                 \"utf8\",\n                                                 \"utf16-le\"\n                                               ]\n                               ).text,\n                               '<iframe[^\\>]+src\\s*=\\s*\\\"data:[^\\;]+;base64,'\n            )"
          strings.ilike func_call "strings.ilike(file.parse_text(.,\n                                          encodings=[\n                                            \"ascii\",\n                                            \"utf8\",\n                                            \"utf16-le\"\n                                          ]\n                          ).text,\n                          \"*onload*\",\n                          \"*window.location.href*\",\n                          \"*onerror*\",\n                          \"*CDATA*\",\n                          \"*<script*\",\n                          \"*</script*\",\n                          \"*atob*\",\n                          \"*location.assign*\",\n                          \"*decodeURIComponent*\"\n            )"
           macro "any(beta.scan_base64(file.parse_text(.).text,\n                                    encodings=[\"ascii\", \"utf8\", \"utf16-le\"]\n                   ),\n                   strings.ilike(.,\n                                 \"*onload*\",\n                                 \"*window.location.href*\",\n                                 \"*onerror*\",\n                                 \"*CDATA*\",\n                                 \"*<script*\",\n                                 \"*</script*\",\n                                 \"*atob*\",\n                                 \"*location.assign*\",\n                                 \"*decodeURIComponent*\"\n                   )\n            )"
  type.inbound eq "true"

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"

Attachment: Embedded VBScript in MHT file

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

MHT files can be used to run VBScript, which can run malicious code.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension =~ "mht"
          or .file_extension in~ $file_extensions_common_archives
        )

        // ensure there's an mht file (if it's in an archive)
        and any(file.explode(.), .file_extension =~ "mht")
        and any(file.explode(.),
                any(.scan.html.scripts, .language == "VBScript")
        )
)

Detection Logic

Scope: inbound message.

MHT files can be used to run VBScript, which can run malicious code.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'mht'
      • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), .file_extension =~ "mht")
    • any(file.explode(.), any(.scan.html.scripts, .language == "VBScript") )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionequalsmht
file.explode(attachments[])[].file_extensionequalsmht
file.explode(attachments[])[].scan.html.scripts[].languageequalsVBScript

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension eq "mht"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.), .file_extension =~ \"mht\")"
       macro "any(file.explode(.),\n                any(.scan.html.scripts, .language == \"VBScript\")\n        )"
  type.inbound eq "true"

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"

Attachment: EML containing a base64 encoded script

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

Attached EML contains a base64 encoded script in the message body.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, HTML smuggling, Scripting, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • sender.email
  • type

Rule Body

type.inbound
and length(body.current_thread.text) < 1000
and any(attachments,
        (.content_type == "message/rfc822" or .file_extension == "eml")
        and strings.ilike(file.parse_eml(.).body.html.raw,
                          "*script*data:text/html;base64*"
        )
)
// exclude bounce backs & read receipts
and not strings.like(sender.email.local_part,
                     "*postmaster*",
                     "*mailer-daemon*",
                     "*administrator*"
)
and not any(attachments, .content_type == "message/delivery-status")

Detection Logic

Scope: inbound message.

Attached EML contains a base64 encoded script in the message body.

  1. inbound message
  2. length(body.current_thread.text) < 1000
  3. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension is 'eml'
    • strings.ilike(file.parse_eml(.).body.html.raw, "*script*data:text/html;base64*" )
  4. not:
    • sender.email.local_part matches any of 3 patterns
      • *postmaster*
      • *mailer-daemon*
      • *administrator*
  5. not:
    • any of attachments where:
      • .content_type is 'message/delivery-status'

Inspects: attachments[].content_type, attachments[].file_extension, body.current_thread.text, sender.email.local_part, type.inbound. Sensors: file.parse_eml, strings.ilike, strings.like.

Indicators Matched (3)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionequalseml
strings.ilikesubstring*script*data:text/html;base64*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
      strings.ilike func_call "strings.ilike(file.parse_eml(.).body.html.raw,\n                          \"*script*data:text/html;base64*\"\n        )"
  not
    any(attachments)
      attachments.content_type eq "message/delivery-status"
  not
    or
      sender.email.local_part match "administrator"
      sender.email.local_part match "mailer-daemon"
      sender.email.local_part match "postmaster"
  body.current_thread.text length_compare "1000"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments
sender.email.local_partmatchadministratorexcludes:sender.email.local_part field:"sender.email.local_part" value:"administrator"
sender.email.local_partmatchmailer-daemonexcludes:sender.email.local_part field:"sender.email.local_part" value:"mailer-daemon"
sender.email.local_partmatchpostmasterexcludes:sender.email.local_part field:"sender.email.local_part" value:"postmaster"

Attachment: EML file contains HTML attachment with login portal indicators

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

Attached EML file contains an HTML attachment with suspicious login indicators. Known credential theft technique.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.html
  • headers
  • headers.hops
  • sender.email
  • subject
  • type

Rule Body

type.inbound

// exclude bounce backs & read receipts
and not strings.like(sender.email.local_part,
                     "*postmaster*",
                     "*mailer-daemon*",
                     "*administrator*"
)
and not regex.imatch(subject.subject, "(undeliverable|read:).*")
and not any(attachments, .content_type == "message/delivery-status")

// if the "References" is in the body of the message, it's probably a bounce
and not any(headers.references, strings.contains(body.html.display_text, .))
and (
  (length(headers.references) == 0 and headers.in_reply_to is null)
  or (
    not strings.istarts_with(subject.subject, "re:")
    and headers.in_reply_to is null
    and not any(headers.hops, strings.ilike(.signature.headers, "*:reply-to"))
  )
)
and any(attachments,
        (.content_type == "message/rfc822" or .file_extension in ('eml'))
        and any(file.explode(.),
                // suspicious strings found in javascript
                length(filter(.scan.javascript.strings,
                              strings.ilike(.,
                                            "*username*",
                                            "*login-form*",
                                            "*email-form*",
                                            "*Incorrect password. Please try again.*",
                                            "*Password Incomplete, please try again*"
                              )
                       )
                ) >= 3
                or (

                  // suspicious strings found outside of javascript, but binexplode'd file still of HTML type
                  .flavors.mime in~ ("text/html", "text/plain")
                  and 3 of (
                    any(.scan.strings.strings, strings.ilike(., "*username*")),
                    any(.scan.strings.strings, strings.ilike(., "*login-form*")),
                    any(.scan.strings.strings, strings.ilike(., "*email-form*")),
                    any(.scan.strings.strings,
                        strings.ilike(.,
                                      "*Incorrect password. Please try again.*"
                        )
                    ),
                    any(.scan.strings.strings,
                        strings.ilike(.,
                                      "*Password Incomplete, please try again*"
                        )
                    )
                  )
                )
                or 

                // Known phishing obfuscation
                2 of (
                  // Enter password
                  any(.scan.strings.strings,
                      strings.ilike(.,
                                    "*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*"
                      )
                  ),
                  // Forgotten my password
                  any(.scan.strings.strings,
                      strings.ilike(.,
                                    "*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*"
                      )
                  ),
                  // Sign in
                  any(.scan.strings.strings,
                      strings.ilike(.,
                                    "*&#83;&#105;&#103;&#110;&#32;&#105;&#110*"
                      )
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

Attached EML file contains an HTML attachment with suspicious login indicators. Known credential theft technique.

  1. inbound message
  2. not:
    • sender.email.local_part matches any of 3 patterns
      • *postmaster*
      • *mailer-daemon*
      • *administrator*
  3. not:
    • subject.subject matches '(undeliverable|read:).*'
  4. not:
    • any of attachments where:
      • .content_type is 'message/delivery-status'
  5. not:
    • any of headers.references where:
      • strings.contains(body.html.display_text, .)
  6. any of:
    • all of:
      • length(headers.references) == 0
      • headers.in_reply_to is missing
    • all of:
      • not:
        • subject.subject starts with 're:'
      • headers.in_reply_to is missing
      • not:
        • any of headers.hops where:
          • .signature.headers matches '*:reply-to'
  7. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension in ('eml')
    • any(file.explode(.), // suspicious strings found in javascript length(filter(.scan.javascript.strings, strings.ilike(., "*username*", "*login-form*", "*email-form*", "*Incorrect password. Please try again.*", "*Password Incomplete, please try again*" ) ) ) >= 3 or ( // suspicious strings found outside of javascript, but binexplode'd file still of HTML type .flavors.mime in~ ("text/html", "text/plain") and 3 of ( any(.scan.strings.strings, strings.ilike(., "*username*")), any(.scan.strings.strings, strings.ilike(., "*login-form*")), any(.scan.strings.strings, strings.ilike(., "*email-form*")), any(.scan.strings.strings, strings.ilike(., "*Incorrect password. Please try again.*" ) ), any(.scan.strings.strings, strings.ilike(., "*Password Incomplete, please try again*" ) ) ) ) or // Known phishing obfuscation 2 of ( // Enter password any(.scan.strings.strings, strings.ilike(., "*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*" ) ), // Forgotten my password any(.scan.strings.strings, strings.ilike(., "*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*" ) ), // Sign in any(.scan.strings.strings, strings.ilike(., "*&#83;&#105;&#103;&#110;&#32;&#105;&#110*" ) ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, body.html.display_text, headers.hops, headers.hops[].signature.headers, headers.in_reply_to, headers.references, sender.email.local_part, subject.subject, type.inbound. Sensors: file.explode, regex.imatch, strings.contains, strings.ilike, strings.istarts_with, strings.like.

Indicators Matched (12)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionmembereml
strings.ilikesubstring*username*
strings.ilikesubstring*login-form*
strings.ilikesubstring*email-form*
strings.ilikesubstring*Incorrect password. Please try again.*
strings.ilikesubstring*Password Incomplete, please try again*
file.explode(attachments[])[].flavors.mimemembertext/html
file.explode(attachments[])[].flavors.mimemembertext/plain
strings.ilikesubstring*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*
strings.ilikesubstring*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*
strings.ilikesubstring*&#83;&#105;&#103;&#110;&#32;&#105;&#110*

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        any(headers.hops)
          headers.hops.signature.headers ends_with ":reply-to"
      not
        subject.subject starts_with "re:"
      headers.in_reply_to is_null
    and
      headers.in_reply_to is_null
      headers.references length_compare "0"
  any(attachments)
    and
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
       macro "any(file.explode(.),\n                // suspicious strings found in javascript\n                length(filter(.scan.javascript.strings,\n                              strings.ilike(.,\n                                            \"*username*\",\n                                            \"*login-form*\",\n                                            \"*email-form*\",\n                                            \"*Incorrect password. Please try again.*\",\n                                            \"*Password Incomplete, please try again*\"\n                              )\n                       )\n                ) >= 3\n                or (\n\n                  // suspicious strings found outside of javascript, but binexplode'd file still of HTML type\n                  .flavors.mime in~ (\"text/html\", \"text/plain\")\n                  and 3 of (\n                    any(.scan.strings.strings, strings.ilike(., \"*username*\")),\n                    any(.scan.strings.strings, strings.ilike(., \"*login-form*\")),\n                    any(.scan.strings.strings, strings.ilike(., \"*email-form*\")),\n                    any(.scan.strings.strings,\n                        strings.ilike(.,\n                                      \"*Incorrect password. Please try again.*\"\n                        )\n                    ),\n                    any(.scan.strings.strings,\n                        strings.ilike(.,\n                                      \"*Password Incomplete, please try again*\"\n                        )\n                    )\n                  )\n                )\n                or \n\n                // Known phishing obfuscation\n                2 of (\n                  // Enter password\n                  any(.scan.strings.strings,\n                      strings.ilike(.,\n                                    \"*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*\"\n                      )\n                  ),\n                  // Forgotten my password\n                  any(.scan.strings.strings,\n                      strings.ilike(.,\n                                    \"*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*\"\n                      )\n                  ),\n                  // Sign in\n                  any(.scan.strings.strings,\n                      strings.ilike(.,\n                                    \"*&#83;&#105;&#103;&#110;&#32;&#105;&#110*\"\n                      )\n                  )\n                )\n        )"
  not
    any(attachments)
      attachments.content_type eq "message/delivery-status"
  not
    or
      sender.email.local_part match "administrator"
      sender.email.local_part match "mailer-daemon"
      sender.email.local_part match "postmaster"
  not
    any(headers.references)
      strings.contains func_call "strings.contains(body.html.display_text, .)"
  not
    subject.subject regex_match "(undeliverable|read:).*"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
headers.in_reply_tois_null
  • (no value, null check)
field:"headers.in_reply_to" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments
sender.email.local_partmatchadministratorexcludes:sender.email.local_part field:"sender.email.local_part" value:"administrator"
sender.email.local_partmatchmailer-daemonexcludes:sender.email.local_part field:"sender.email.local_part" value:"mailer-daemon"
sender.email.local_partmatchpostmasterexcludes:sender.email.local_part field:"sender.email.local_part" value:"postmaster"
headers.referencesarray_any(no value, null check)excludes:headers.references
subject.subjectregex_match(undeliverable|read:).*excludes:subject.subject field:"subject.subject" value:"(undeliverable|read:).*"

Attachment: EML file with HTML attachment (unsolicited)

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

Detects HTML files in EML attachments from unsolicited senders. Reduces attack surface against HTML smuggling.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.html
  • headers
  • headers.auth_summary
  • sender.email
  • subject
  • type

Rule Body

type.inbound

// has EML attachment
and any(attachments,
        (.file_extension == "eml" or .content_type == "message/rfc822")
        and any(file.parse_eml(.).attachments,
                // HTML file inside EML attachment
                // we've seen files named ".htm.", which results in an empty
                // .file_extension, so instead we look at .file_name
                // they should be rare enough in EML attachments to not cause
                // extraneous FPs
                strings.ilike(.file_name, "*htm*")
                or .file_type == "html"
                or any(file.explode(.), .flavors.mime == "text/html")
        )
)

// exclude bounce backs & read receipts
and not strings.like(sender.email.local_part,
                     "*postmaster*",
                     "*mailer-daemon*",
                     "*administrator*"
)
and not regex.icontains(subject.subject, "^(undeliverable|read:)")
and not any(attachments, .content_type == "message/delivery-status")
// if the "References" is in the body of the message, it's probably a bounce
and not any(headers.references, strings.contains(body.html.display_text, .))
// unsolicited or fails authentation
and (
  (
    profile.by_sender_email().prevalence in ("new", "outlier")
    and not profile.by_sender_email().solicited
  )
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
  or (
    sender.email.domain.domain in $org_domains
    and not coalesce(headers.auth_summary.dmarc.pass, false)
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not coalesce(headers.auth_summary.dmarc.pass, false)
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects HTML files in EML attachments from unsolicited senders. Reduces attack surface against HTML smuggling.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'eml'
      • .content_type is 'message/rfc822'
    • any(file.parse_eml(.).attachments, // HTML file inside EML attachment // we've seen files named ".htm.", which results in an empty // .file_extension, so instead we look at .file_name // they should be rare enough in EML attachments to not cause // extraneous FPs strings.ilike(.file_name, "*htm*") or .file_type == "html" or any(file.explode(.), .flavors.mime == "text/html") )
  3. not:
    • sender.email.local_part matches any of 3 patterns
      • *postmaster*
      • *mailer-daemon*
      • *administrator*
  4. not:
    • subject.subject matches '^(undeliverable|read:)'
  5. not:
    • any of attachments where:
      • .content_type is 'message/delivery-status'
  6. not:
    • any of headers.references where:
      • strings.contains(body.html.display_text, .)
  7. any of:
    • all of:
      • profile.by_sender_email().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender_email().solicited
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
    • all of:
      • sender.email.domain.domain in $org_domains
      • not:
        • coalesce(headers.auth_summary.dmarc.pass, false)
  8. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • coalesce(headers.auth_summary.dmarc.pass, false)
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_type, attachments[].file_extension, body.html.display_text, headers.auth_summary.dmarc.pass, headers.references, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.local_part, subject.subject, type.inbound. Sensors: file.explode, file.parse_eml, profile.by_sender_email, regex.icontains, strings.contains, strings.ilike, strings.like. Reference lists: $high_trust_sender_root_domains, $org_domains.

Indicators Matched (5)

FieldMatchValue
attachments[].file_extensionequalseml
attachments[].content_typeequalsmessage/rfc822
strings.ilikesubstring*htm*
file.parse_eml(attachments[]).attachments[].file_typeequalshtml
file.explode(file.parse_eml(attachments[]).attachments[])[].flavors.mimeequalstext/html

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        and
          headers.auth_summary.dmarc.pass eq "true"
          headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.domain macro "sender.email.domain.domain in org_domains"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().solicited"
      profile.by_sender_email func_call "profile.by_sender_email().prevalence in (\"new\", \"outlier\")"
  or
    and
      not
        and
          headers.auth_summary.dmarc.pass eq "true"
          headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  any(attachments)
    and
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
       macro "any(file.parse_eml(.).attachments,\n                // HTML file inside EML attachment\n                // we've seen files named \".htm.\", which results in an empty\n                // .file_extension, so instead we look at .file_name\n                // they should be rare enough in EML attachments to not cause\n                // extraneous FPs\n                strings.ilike(.file_name, \"*htm*\")\n                or .file_type == \"html\"\n                or any(file.explode(.), .flavors.mime == \"text/html\")\n        )"
  not
    any(attachments)
      attachments.content_type eq "message/delivery-status"
  not
    or
      sender.email.local_part match "administrator"
      sender.email.local_part match "mailer-daemon"
      sender.email.local_part match "postmaster"
  not
    any(headers.references)
      strings.contains func_call "strings.contains(body.html.display_text, .)"
  not
    subject.subject regex_match "^(undeliverable|read:)"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments
sender.email.local_partmatchadministratorexcludes:sender.email.local_part field:"sender.email.local_part" value:"administrator"
sender.email.local_partmatchmailer-daemonexcludes:sender.email.local_part field:"sender.email.local_part" value:"mailer-daemon"
sender.email.local_partmatchpostmasterexcludes:sender.email.local_part field:"sender.email.local_part" value:"postmaster"
headers.referencesarray_any(no value, null check)excludes:headers.references
subject.subjectregex_match^(undeliverable|read:)excludes:subject.subject field:"subject.subject" value:"^(undeliverable|read:)"

Attachment: EML file with IPFS links

#

Attachment: EML with embedded Javascript in SVG file

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

Detects incoming messages containing EML attachments with embedded SVG files that contain malicious JavaScript code, including base64-encoded content and potentially harmful event handlers. The rule specifically watches for onload events, location redirects, error handlers, and iframe elements with base64 data URIs.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesScripting, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (.content_type == "message/rfc822" or .file_extension =~ "eml")
        and (
          any(file.parse_eml(.).attachments,
              .file_extension in~ ("svg", "svgz")
              or .file_type == "svg"
              and (
                (
                  strings.ilike(file.parse_text(.,
                                                encodings=[
                                                  "ascii",
                                                  "utf8",
                                                  "utf16-le"
                                                ]
                                ).text,
                                "*onload*",
                                "*window.location.href*",
                                "*onerror*",
                                "*CDATA*",
                                "*<script*",
                                "*</script*",
                                "*atob*",
                                '*location.assign*',
                                '*decodeURIComponent*'
                  )
                  or regex.icontains(file.parse_text(.,
                                                     encodings=[
                                                       "ascii",
                                                       "utf8",
                                                       "utf16-le"
                                                     ]
                                     ).text,
                                     '<iframe[^\>]+src\s*=\s*\"data:[^\;]+;base64,'
                  )
                  or any(beta.scan_base64(file.parse_text(.).text,
                                          encodings=[
                                            "ascii",
                                            "utf8",
                                            "utf16-le"
                                          ]
                         ),
                         strings.ilike(.,
                                       "*onload*",
                                       "*window.location.href*",
                                       "*onerror*",
                                       "*CDATA*",
                                       "*<script*",
                                       "*</script*",
                                       "*atob*",
                                       '*location.assign*',
                                       '*decodeURIComponent*'
                         )
                  )
                )
                or (
                  (
                    .file_extension in $file_extensions_common_archives
                    or .file_type == "gz"
                    or .content_type == "application/x-gzip"
                  )
                  and any(file.explode(.),
                          (
                            .file_extension in~ ("svg", "svgz")
                            or .flavors.mime == "image/svg+xml"
                          )
                          and any(.scan.strings.strings,
                                  strings.ilike(.,
                                                "*onload*",
                                                "*window.location.href*",
                                                "*onerror*",
                                                "*CDATA*",
                                                "*<script*",
                                                "*</script*",
                                                "*atob*",
                                                "*location.assign*",
                                                "*decodeURIComponent*"
                                  )
                          )
                  )
                )
              )
          )
        )
)

Detection Logic

Scope: inbound message.

Detects incoming messages containing EML attachments with embedded SVG files that contain malicious JavaScript code, including base64-encoded content and potentially harmful event handlers. The rule specifically watches for onload events, location redirects, error handlers, and iframe elements with base64 data URIs.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension is 'eml'
    • ( any(file.parse_eml(.).attachments, .file_extension in~ ("svg", "svgz") or .file_type == "svg" and ( ( strings.ilike(file.parse_text(., encodings=[ "ascii", "utf8", "utf16-le" ] ).text, "*onload*", "*window.location.href*", "*onerror*", "*CDATA*", "*<script*", "*</script*", "*atob*", '*location.assign*', '*decodeURIComponent*' ) or regex.icontains(file.parse_text(., encodings=[ "ascii", "utf8", "utf16-le" ] ).text, '<iframe[^\>]+src\s*=\s*\"data:[^\;]+;base64,' ) or any(beta.scan_base64(file.parse_text(.).text, encodings=[ "ascii", "utf8", "utf16-le" ] ), strings.ilike(., "*onload*", "*window.location.href*", "*onerror*", "*CDATA*", "*<script*", "*</script*", "*atob*", '*location.assign*', '*decodeURIComponent*' ) ) ) or ( ( .file_extension in $file_extensions_common_archives or .file_type == "gz" or .content_type == "application/x-gzip" ) and any(file.explode(.), ( .file_extension in~ ("svg", "svgz") or .flavors.mime == "image/svg+xml" ) and any(.scan.strings.strings, strings.ilike(., "*onload*", "*window.location.href*", "*onerror*", "*CDATA*", "*<script*", "*</script*", "*atob*", "*location.assign*", "*decodeURIComponent*" ) ) ) ) ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: beta.scan_base64, file.explode, file.parse_eml, file.parse_text, regex.icontains, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (20)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionequalseml
file.parse_eml(attachments[]).attachments[].file_extensionmembersvg
file.parse_eml(attachments[]).attachments[].file_extensionmembersvgz
file.parse_eml(attachments[]).attachments[].file_typeequalssvg
strings.ilikesubstring*onload*
strings.ilikesubstring*window.location.href*
strings.ilikesubstring*onerror*
strings.ilikesubstring*CDATA*
strings.ilikesubstring*<script*
strings.ilikesubstring*</script*
strings.ilikesubstring*atob*
8 more
strings.ilikesubstring*location.assign*
strings.ilikesubstring*decodeURIComponent*
regex.icontainsregex<iframe[^\>]+src\s*=\s*\"data:[^\;]+;base64,
file.parse_eml(attachments[]).attachments[].file_typeequalsgz
file.parse_eml(attachments[]).attachments[].content_typeequalsapplication/x-gzip
file.explode(file.parse_eml(attachments[]).attachments[])[].file_extensionmembersvg
file.explode(file.parse_eml(attachments[]).attachments[])[].file_extensionmembersvgz
file.explode(file.parse_eml(attachments[]).attachments[])[].flavors.mimeequalsimage/svg+xml

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
       macro "(\n          any(file.parse_eml(.).attachments,\n              .file_extension in~ (\"svg\", \"svgz\")\n              or .file_type == \"svg\"\n              and (\n                (\n                  strings.ilike(file.parse_text(.,\n                                                encodings=[\n                                                  \"ascii\",\n                                                  \"utf8\",\n                                                  \"utf16-le\"\n                                                ]\n                                ).text,\n                                \"*onload*\",\n                                \"*window.location.href*\",\n                                \"*onerror*\",\n                                \"*CDATA*\",\n                                \"*<script*\",\n                                \"*</script*\",\n                                \"*atob*\",\n                                '*location.assign*',\n                                '*decodeURIComponent*'\n                  )\n                  or regex.icontains(file.parse_text(.,\n                                                     encodings=[\n                                                       \"ascii\",\n                                                       \"utf8\",\n                                                       \"utf16-le\"\n                                                     ]\n                                     ).text,\n                                     '<iframe[^\\>]+src\\s*=\\s*\\\"data:[^\\;]+;base64,'\n                  )\n                  or any(beta.scan_base64(file.parse_text(.).text,\n                                          encodings=[\n                                            \"ascii\",\n                                            \"utf8\",\n                                            \"utf16-le\"\n                                          ]\n                         ),\n                         strings.ilike(.,\n                                       \"*onload*\",\n                                       \"*window.location.href*\",\n                                       \"*onerror*\",\n                                       \"*CDATA*\",\n                                       \"*<script*\",\n                                       \"*</script*\",\n                                       \"*atob*\",\n                                       '*location.assign*',\n                                       '*decodeURIComponent*'\n                         )\n                  )\n                )\n                or (\n                  (\n                    .file_extension in $file_extensions_common_archives\n                    or .file_type == \"gz\"\n                    or .content_type == \"application/x-gzip\"\n                  )\n                  and any(file.explode(.),\n                          (\n                            .file_extension in~ (\"svg\", \"svgz\")\n                            or .flavors.mime == \"image/svg+xml\"\n                          )\n                          and any(.scan.strings.strings,\n                                  strings.ilike(.,\n                                                \"*onload*\",\n                                                \"*window.location.href*\",\n                                                \"*onerror*\",\n                                                \"*CDATA*\",\n                                                \"*<script*\",\n                                                \"*</script*\",\n                                                \"*atob*\",\n                                                \"*location.assign*\",\n                                                \"*decodeURIComponent*\"\n                                  )\n                          )\n                  )\n                )\n              )\n          )\n        )"
  type.inbound eq "true"

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"

Attachment: EML with Encrypted ZIP

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

Detects when an EML file is attached that contains an encrypted ZIP file. The encryption can be used to bypass security scanning and deliver malicious content.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEncryption, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
// attached EML
and any(filter(attachments,
               .content_type == "message/rfc822" or .file_extension in ('eml')
        ),
        // Attached EML contains a ZIP file
        any(filter(file.parse_eml(.).attachments,
                   .file_type == "zip" or .file_extension == "zip"
            ),
            // ZIP file is encrypted
            any(file.explode(.),
                any(.flavors.yara, . == 'encrypted_zip') or .scan.zip.encrypted
            )
        )
)

Detection Logic

Scope: inbound message.

Detects when an EML file is attached that contains an encrypted ZIP file. The encryption can be used to bypass security scanning and deliver malicious content.

  1. inbound message
  2. any(filter(attachments, .content_type == "message/rfc822" or .file_extension in ('eml') ), // Attached EML contains a ZIP file any(filter(file.parse_eml(.).attachments, .file_type == "zip" or .file_extension == "zip" ), // ZIP file is encrypted any(file.explode(.), any(.flavors.yara, . == 'encrypted_zip') or .scan.zip.encrypted ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: file.explode, file.parse_eml.

Indicators Matched (5)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionmembereml
file.parse_eml(filter(attachments)[]).attachments[].file_typeequalszip
file.parse_eml(filter(attachments)[]).attachments[].file_extensionequalszip
file.explode(filter(...)[])[].flavors.yara[]equalsencrypted_zip

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .content_type == \"message/rfc822\" or .file_extension in ('eml')\n        ),\n        // Attached EML contains a ZIP file\n        any(filter(file.parse_eml(.).attachments,\n                   .file_type == \"zip\" or .file_extension == \"zip\"\n            ),\n            // ZIP file is encrypted\n            any(file.explode(.),\n                any(.flavors.yara, . == 'encrypted_zip') or .scan.zip.encrypted\n            )\n        )\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"

Attachment: EML with link to credential phishing page

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

Attached EML links to a credential phishing site or exhibits unusual behavior such as multiple suspicious redirects.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Free file host, Free subdomain host, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.html
  • headers
  • headers.reply_to
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and length(attachments) == 1
and any(attachments,
        (.content_type == "message/rfc822" or .file_extension =~ "eml")

        // identifies suspicious URLs in the attached EML
        and any(file.parse_eml(.).body.links,
                (
                  ml.link_analysis(., mode="aggressive").credphish.disposition == "phishing"
                  and ml.link_analysis(., mode="aggressive").credphish.confidence in (
                    "medium",
                    "high"
                  )
                )

                // or any links in the final dom lead to a suspicious tld
                or any(ml.link_analysis(.).final_dom.links,
                       .href_url.domain.tld in $suspicious_tlds
                       or ml.link_analysis(.href_url).effective_url.domain.tld in $suspicious_tlds
                )

                // link redirects to a suspicious TLD
                or any(ml.link_analysis(., mode="aggressive").redirect_history,
                       .domain.tld in $suspicious_tlds
                )
                or (
                  // suspicious redirects
                  // 3 or more different domains with 2 or more different TLDs
                  // careful because click trackers will always make this at least 2
                  // different domains and not unlikely 2 or more TLDs
                  length(distinct(map(ml.link_analysis(., mode="aggressive").redirect_history,
                                      .domain.tld
                                  )
                         )
                  ) >= 2
                  and length(distinct(map(ml.link_analysis(., mode="aggressive").redirect_history,
                                          .domain.domain
                                      )
                             )
                  ) >= 3
                )
        )

        // identifies other suspicious indicators
        and (
          // engaging language in the original body
          any(ml.nlu_classifier(body.current_thread.text).entities,
              .name == "request"
          )

          // // engaging language in the attached EML
          or any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).entities,
                 .name == "request"
          )
          // recipient SLD impersonated in the subject or display name
          or any(recipients.to,
                 // ensure that we're checking the org SLD
                 .email.domain.sld in $org_slds
                 and (
                   strings.icontains(subject.subject, .email.domain.sld)
                   or strings.icontains(sender.display_name, .email.domain.sld)
                 )
          )
          // mismatched sender (From) and Reply-to + freemail
          or (
            length(headers.reply_to) > 0
            and all(headers.reply_to,
                    .email.domain.root_domain != sender.email.domain.root_domain
                    and .email.domain.root_domain in $free_email_providers
            )
          )
          or any($suspicious_subjects, strings.icontains(subject.subject, .))
          or regex.icontains(subject.subject,
                             "termination.*notice",
                             "38417",
                             ":completed",
                             "[il1]{2}mit.*ma[il1]{2} ?bo?x",
                             "[il][il][il]egai[ -]",
                             "[li][li][li]ega[li] attempt",
                             "[ng]-?[io]n .*block",
                             "[ng]-?[io]n .*cancel",
                             "[ng]-?[io]n .*deactiv",
                             "[ng]-?[io]n .*disabl",
                             "action.*required",
                             "abandon.*package",
                             "about.your.account",
                             "acc(ou)?n?t (is )?on ho[li]d",
                             "acc(ou)?n?t.*terminat",
                             "acc(oun)?t.*[il1]{2}mitation",
                             "access.*limitation",
                             "account (will be )?block",
                             "account.*de-?activat",
                             "account.*locked",
                             "account.*re-verification",
                             "account.*security",
                             "account.*suspension",
                             "account.has.been",
                             "account.has.expired",
                             "account.will.be.blocked",
                             "account v[il]o[li]at",
                             "activity.*acc(oun)?t",
                             "almost.full",
                             "app[li]e.[il]d",
                             "authenticate.*account",
                             "been.*suspend",
                             "clos.*of.*account.*processed",
                             "confirm.your.account",
                             "courier.*able",
                             "crediential.*notif",
                             "deactivation.*in.*progress",
                             "delivery.*attempt.*failed",
                             "document.received",
                             "documented.*shared.*with.*you",
                             "dropbox.*document",
                             "e-?ma[il1]+ .{010}suspen",
                             "e-?ma[il1]{1} user",
                             "e-?ma[il1]{2} acc",
                             "e-?ma[il1]{2}.*up.?grade",
                             "e.?ma[il1]{2}.*server",
                             "e.?ma[il1]{2}.*suspend",
                             "email.update",
                             "faxed you",
                             "fraud(ulent)?.*charge",
                             "from.helpdesk",
                             "fu[il1]{2}.*ma[il1]+[ -]?box",
                             "has.been.*suspended",
                             "has.been.limited",
                             "have.locked",
                             "he[li]p ?desk upgrade",
                             "heipdesk",
                             "i[il]iega[il]",
                             "ii[il]ega[il]",
                             "incoming e?mail",
                             "incoming.*fax",
                             "lock.*security",
                             "ma[il1]{1}[ -]?box.*quo",
                             "ma[il1]{2}[ -]?box.*fu[il1]",
                             "ma[il1]{2}box.*[il1]{2}mit",
                             "ma[il1]{2}box stor",
                             "mail on.?hold",
                             "mail.*box.*migration",
                             "mail.*de-?activat",
                             "mail.update.required",
                             "mails.*pending",
                             "messages.*pending",
                             "missed.*shipping.*notification",
                             "missed.shipment.notification",
                             "must.update.your.account",
                             "new [sl][io]g?[nig][ -]?in from",
                             "new voice ?-?mail",
                             "notifications.*pending",
                             "office.*3.*6.*5.*suspend",
                             "office365",
                             "on google docs with you",
                             "online doc",
                             "password.*compromised",
                             "periodic maintenance",
                             "potential(ly)? unauthorized",
                             "refund not approved",
                             "report",
                             "revised.*policy",
                             "scam",
                             "scanned.?invoice",
                             "secured?.update",
                             "security breach",
                             "securlty",
                             "signed.*delivery",
                             "status of your .{314}? ?delivery",
                             "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty",
                             "suspicious.*sign.*[io]n",
                             "suspicious.activit",
                             "temporar(il)?y deactivate",
                             "temporar[il1]{2}y disab[li]ed",
                             "temporarily.*lock",
                             "un-?usua[li].activity",
                             "unable.*deliver",
                             "unauthorized.*activit",
                             "unauthorized.device",
                             "undelivered message",
                             "unread.*doc",
                             "unusual.activity",
                             "upgrade.*account",
                             "upgrade.notice",
                             "urgent message",
                             "urgent.verification",
                             "v[il1]o[li1]at[il1]on security",
                             "va[il1]{1}date.*ma[il1]{2}[ -]?box",
                             "verification ?-?require",
                             "verification( )?-?need",
                             "verify.your?.account",
                             "web ?-?ma[il1]{2}",
                             "web[ -]?ma[il1]{2}",
                             "will.be.suspended",
                             "your (customer )?account .as",
                             "your.office.365",
                             "your.online.access",
          )
        )
)
// exclude bounce backs & read receipts
and not strings.ilike(sender.email.local_part,
                      "*postmaster*",
                      "*mailer-daemon*",
                      "*administrator*"
)
// exclude optonline deprecated mailbox returns
and (
  not strings.starts_with(sender.display_name, "Auto-reply")
  and sender.email.domain.root_domain == "optonline.net"
)
and not regex.icontains(subject.subject, "^(undeliverable|read:)")
and not any(attachments, .content_type == "message/delivery-status")
// if the "References" is in the body of the message, it's probably a bounce
and not any(headers.references, strings.contains(body.html.display_text, .))
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Attached EML links to a credential phishing site or exhibits unusual behavior such as multiple suspicious redirects.

  1. inbound message
  2. length(attachments) == 1
  3. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension is 'eml'
    • any(file.parse_eml(.).body.links, ( ml.link_analysis(., mode="aggressive").credphish.disposition == "phishing" and ml.link_analysis(., mode="aggressive").credphish.confidence in ( "medium", "high" ) ) // or any links in the final dom lead to a suspicious tld or any(ml.link_analysis(.).final_dom.links, .href_url.domain.tld in $suspicious_tlds or ml.link_analysis(.href_url).effective_url.domain.tld in $suspicious_tlds ) // link redirects to a suspicious TLD or any(ml.link_analysis(., mode="aggressive").redirect_history, .domain.tld in $suspicious_tlds ) or ( // suspicious redirects // 3 or more different domains with 2 or more different TLDs // careful because click trackers will always make this at least 2 // different domains and not unlikely 2 or more TLDs length(distinct(map(ml.link_analysis(., mode="aggressive").redirect_history, .domain.tld ) ) ) >= 2 and length(distinct(map(ml.link_analysis(., mode="aggressive").redirect_history, .domain.domain ) ) ) >= 3 ) )
    • any of:
      • any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request" )
      • any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).entities, .name == "request" )
      • any of recipients.to where all hold:
        • .email.domain.sld in $org_slds
        • any of:
          • strings.icontains(subject.subject, .email.domain.sld)
          • strings.icontains(sender.display_name, .email.domain.sld)
      • all of:
        • length(headers.reply_to) > 0
        • all of headers.reply_to where all hold:
          • .email.domain.root_domain is not sender.email.domain.root_domain
          • .email.domain.root_domain in $free_email_providers
      • any($suspicious_subjects, strings.icontains(subject.subject, .))
      • subject.subject matches any of 123 patterns
        • termination.*notice
        • 38417
        • :completed
        • [il1]{2}mit.*ma[il1]{2} ?bo?x
        • [il][il][il]egai[ -]
        • [li][li][li]ega[li] attempt
        • [ng]-?[io]n .*block
        • [ng]-?[io]n .*cancel
        • [ng]-?[io]n .*deactiv
        • [ng]-?[io]n .*disabl
        • action.*required
        • abandon.*package
        • about.your.account
        • acc(ou)?n?t (is )?on ho[li]d
        • acc(ou)?n?t.*terminat
        • acc(oun)?t.*[il1]{2}mitation
        • access.*limitation
        • account (will be )?block
        • account.*de-?activat
        • account.*locked
        • account.*re-verification
        • account.*security
        • account.*suspension
        • account.has.been
        • account.has.expired
        • account.will.be.blocked
        • account v[il]o[li]at
        • activity.*acc(oun)?t
        • almost.full
        • app[li]e.[il]d
        • authenticate.*account
        • been.*suspend
        • clos.*of.*account.*processed
        • confirm.your.account
        • courier.*able
        • crediential.*notif
        • deactivation.*in.*progress
        • delivery.*attempt.*failed
        • document.received
        • documented.*shared.*with.*you
        • dropbox.*document
        • e-?ma[il1]+ .{010}suspen
        • e-?ma[il1]{1} user
        • e-?ma[il1]{2} acc
        • e-?ma[il1]{2}.*up.?grade
        • e.?ma[il1]{2}.*server
        • e.?ma[il1]{2}.*suspend
        • email.update
        • faxed you
        • fraud(ulent)?.*charge
        • from.helpdesk
        • fu[il1]{2}.*ma[il1]+[ -]?box
        • has.been.*suspended
        • has.been.limited
        • have.locked
        • he[li]p ?desk upgrade
        • heipdesk
        • i[il]iega[il]
        • ii[il]ega[il]
        • incoming e?mail
        • incoming.*fax
        • lock.*security
        • ma[il1]{1}[ -]?box.*quo
        • ma[il1]{2}[ -]?box.*fu[il1]
        • ma[il1]{2}box.*[il1]{2}mit
        • ma[il1]{2}box stor
        • mail on.?hold
        • mail.*box.*migration
        • mail.*de-?activat
        • mail.update.required
        • mails.*pending
        • messages.*pending
        • missed.*shipping.*notification
        • missed.shipment.notification
        • must.update.your.account
        • new [sl][io]g?[nig][ -]?in from
        • new voice ?-?mail
        • notifications.*pending
        • office.*3.*6.*5.*suspend
        • office365
        • on google docs with you
        • online doc
        • password.*compromised
        • periodic maintenance
        • potential(ly)? unauthorized
        • refund not approved
        • report
        • revised.*policy
        • scam
        • scanned.?invoice
        • secured?.update
        • security breach
        • securlty
        • signed.*delivery
        • status of your .{314}? ?delivery
        • susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty
        • suspicious.*sign.*[io]n
        • suspicious.activit
        • temporar(il)?y deactivate
        • temporar[il1]{2}y disab[li]ed
        • temporarily.*lock
        • un-?usua[li].activity
        • unable.*deliver
        • unauthorized.*activit
        • unauthorized.device
        • undelivered message
        • unread.*doc
        • unusual.activity
        • upgrade.*account
        • upgrade.notice
        • urgent message
        • urgent.verification
        • v[il1]o[li1]at[il1]on security
        • va[il1]{1}date.*ma[il1]{2}[ -]?box
        • verification ?-?require
        • verification( )?-?need
        • verify.your?.account
        • web ?-?ma[il1]{2}
        • web[ -]?ma[il1]{2}
        • will.be.suspended
        • your (customer )?account .as
        • your.office.365
        • your.online.access
  4. not:
    • sender.email.local_part matches any of 3 patterns
      • *postmaster*
      • *mailer-daemon*
      • *administrator*
  5. all of:
    • not:
      • sender.display_name starts with 'Auto-reply'
    • sender.email.domain.root_domain is 'optonline.net'
  6. not:
    • subject.subject matches '^(undeliverable|read:)'
  7. not:
    • any of attachments where:
      • .content_type is 'message/delivery-status'
  8. not:
    • any of headers.references where:
      • strings.contains(body.html.display_text, .)
  9. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  10. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, body.current_thread.text, body.html.display_text, headers.references, headers.reply_to, headers.reply_to[].email.domain.root_domain, recipients.to, recipients.to[].email.domain.sld, sender.display_name, sender.email.domain.root_domain, sender.email.local_part, subject.subject, type.inbound. Sensors: file.parse_eml, ml.link_analysis, ml.nlu_classifier, profile.by_sender, regex.icontains, strings.contains, strings.icontains, strings.ilike, strings.starts_with. Reference lists: $free_email_providers, $org_slds, $suspicious_subjects, $suspicious_tlds.

Indicators Matched (128)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionequalseml
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsrequest
ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).entities[].nameequalsrequest
regex.icontainsregextermination.*notice
regex.icontainsregex38417
regex.icontainsregex:completed
regex.icontainsregex[il1]{2}mit.*ma[il1]{2} ?bo?x
regex.icontainsregex[il][il][il]egai[ -]
regex.icontainsregex[li][li][li]ega[li] attempt
regex.icontainsregex[ng]-?[io]n .*block
regex.icontainsregex[ng]-?[io]n .*cancel
116 more
regex.icontainsregex[ng]-?[io]n .*deactiv
regex.icontainsregex[ng]-?[io]n .*disabl
regex.icontainsregexaction.*required
regex.icontainsregexabandon.*package
regex.icontainsregexabout.your.account
regex.icontainsregexacc(ou)?n?t (is )?on ho[li]d
regex.icontainsregexacc(ou)?n?t.*terminat
regex.icontainsregexacc(oun)?t.*[il1]{2}mitation
regex.icontainsregexaccess.*limitation
regex.icontainsregexaccount (will be )?block
regex.icontainsregexaccount.*de-?activat
regex.icontainsregexaccount.*locked
regex.icontainsregexaccount.*re-verification
regex.icontainsregexaccount.*security
regex.icontainsregexaccount.*suspension
regex.icontainsregexaccount.has.been
regex.icontainsregexaccount.has.expired
regex.icontainsregexaccount.will.be.blocked
regex.icontainsregexaccount v[il]o[li]at
regex.icontainsregexactivity.*acc(oun)?t
regex.icontainsregexalmost.full
regex.icontainsregexapp[li]e.[il]d
regex.icontainsregexauthenticate.*account
regex.icontainsregexbeen.*suspend
regex.icontainsregexclos.*of.*account.*processed
regex.icontainsregexconfirm.your.account
regex.icontainsregexcourier.*able
regex.icontainsregexcrediential.*notif
regex.icontainsregexdeactivation.*in.*progress
regex.icontainsregexdelivery.*attempt.*failed
regex.icontainsregexdocument.received
regex.icontainsregexdocumented.*shared.*with.*you
regex.icontainsregexdropbox.*document
regex.icontainsregexe-?ma[il1]+ .{010}suspen
regex.icontainsregexe-?ma[il1]{1} user
regex.icontainsregexe-?ma[il1]{2} acc
regex.icontainsregexe-?ma[il1]{2}.*up.?grade
regex.icontainsregexe.?ma[il1]{2}.*server
regex.icontainsregexe.?ma[il1]{2}.*suspend
regex.icontainsregexemail.update
regex.icontainsregexfaxed you
regex.icontainsregexfraud(ulent)?.*charge
regex.icontainsregexfrom.helpdesk
regex.icontainsregexfu[il1]{2}.*ma[il1]+[ -]?box
regex.icontainsregexhas.been.*suspended
regex.icontainsregexhas.been.limited
regex.icontainsregexhave.locked
regex.icontainsregexhe[li]p ?desk upgrade
regex.icontainsregexheipdesk
regex.icontainsregexi[il]iega[il]
regex.icontainsregexii[il]ega[il]
regex.icontainsregexincoming e?mail
regex.icontainsregexincoming.*fax
regex.icontainsregexlock.*security
regex.icontainsregexma[il1]{1}[ -]?box.*quo
regex.icontainsregexma[il1]{2}[ -]?box.*fu[il1]
regex.icontainsregexma[il1]{2}box.*[il1]{2}mit
regex.icontainsregexma[il1]{2}box stor
regex.icontainsregexmail on.?hold
regex.icontainsregexmail.*box.*migration
regex.icontainsregexmail.*de-?activat
regex.icontainsregexmail.update.required
regex.icontainsregexmails.*pending
regex.icontainsregexmessages.*pending
regex.icontainsregexmissed.*shipping.*notification
regex.icontainsregexmissed.shipment.notification
regex.icontainsregexmust.update.your.account
regex.icontainsregexnew [sl][io]g?[nig][ -]?in from
regex.icontainsregexnew voice ?-?mail
regex.icontainsregexnotifications.*pending
regex.icontainsregexoffice.*3.*6.*5.*suspend
regex.icontainsregexoffice365
regex.icontainsregexon google docs with you
regex.icontainsregexonline doc
regex.icontainsregexpassword.*compromised
regex.icontainsregexperiodic maintenance
regex.icontainsregexpotential(ly)? unauthorized
regex.icontainsregexrefund not approved
regex.icontainsregexreport
regex.icontainsregexrevised.*policy
regex.icontainsregexscam
regex.icontainsregexscanned.?invoice
regex.icontainsregexsecured?.update
regex.icontainsregexsecurity breach
regex.icontainsregexsecurlty
regex.icontainsregexsigned.*delivery
regex.icontainsregexstatus of your .{314}? ?delivery
regex.icontainsregexsusp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty
regex.icontainsregexsuspicious.*sign.*[io]n
regex.icontainsregexsuspicious.activit
regex.icontainsregextemporar(il)?y deactivate
regex.icontainsregextemporar[il1]{2}y disab[li]ed
regex.icontainsregextemporarily.*lock
regex.icontainsregexun-?usua[li].activity
regex.icontainsregexunable.*deliver
regex.icontainsregexunauthorized.*activit
regex.icontainsregexunauthorized.device
regex.icontainsregexundelivered message
regex.icontainsregexunread.*doc
regex.icontainsregexunusual.activity
regex.icontainsregexupgrade.*account
regex.icontainsregexupgrade.notice
regex.icontainsregexurgent message
regex.icontainsregexurgent.verification
regex.icontainsregexv[il1]o[li1]at[il1]on security
regex.icontainsregexva[il1]{1}date.*ma[il1]{2}[ -]?box
regex.icontainsregexverification ?-?require
regex.icontainsregexverification( )?-?need
regex.icontainsregexverify.your?.account
regex.icontainsregexweb ?-?ma[il1]{2}
regex.icontainsregexweb[ -]?ma[il1]{2}
regex.icontainsregexwill.be.suspended
regex.icontainsregexyour (customer )?account .as
regex.icontainsregexyour.office.365
regex.icontainsregexyour.online.access
sender.email.domain.root_domainequalsoptonline.net

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        any(recipients.to)
          and
            or
              strings.icontains func_call "strings.icontains(sender.display_name, .email.domain.sld)"
              strings.icontains func_call "strings.icontains(subject.subject, .email.domain.sld)"
            recipients.to.email.domain.sld macro "recipients.to[].email.domain.sld in org_slds"
        and
          headers.reply_to length_compare "0"
           macro "all(headers.reply_to,\n                    .email.domain.root_domain != sender.email.domain.root_domain\n                    and .email.domain.root_domain in $free_email_providers\n            )"
        subject.subject regex_match "38417"
        subject.subject regex_match ":completed"
        subject.subject regex_match "[il1]{2}mit.*ma[il1]{2} ?bo?x"
        subject.subject regex_match "[il][il][il]egai[ -]"
        subject.subject regex_match "[li][li][li]ega[li] attempt"
        subject.subject regex_match "[ng]-?[io]n .*block"
        subject.subject regex_match "[ng]-?[io]n .*cancel"
        subject.subject regex_match "[ng]-?[io]n .*deactiv"
        subject.subject regex_match "[ng]-?[io]n .*disabl"
        subject.subject regex_match "abandon.*package"
        subject.subject regex_match "about.your.account"
        subject.subject regex_match "acc(ou)?n?t (is )?on ho[li]d"
        subject.subject regex_match "acc(ou)?n?t.*terminat"
        subject.subject regex_match "acc(oun)?t.*[il1]{2}mitation"
        subject.subject regex_match "access.*limitation"
        subject.subject regex_match "account (will be )?block"
        subject.subject regex_match "account v[il]o[li]at"
        subject.subject regex_match "account.*de-?activat"
        subject.subject regex_match "account.*locked"
        subject.subject regex_match "account.*re-verification"
        subject.subject regex_match "account.*security"
        subject.subject regex_match "account.*suspension"
        subject.subject regex_match "account.has.been"
        subject.subject regex_match "account.has.expired"
        subject.subject regex_match "account.will.be.blocked"
        subject.subject regex_match "action.*required"
        subject.subject regex_match "activity.*acc(oun)?t"
        subject.subject regex_match "almost.full"
        subject.subject regex_match "app[li]e.[il]d"
        subject.subject regex_match "authenticate.*account"
        subject.subject regex_match "been.*suspend"
        subject.subject regex_match "clos.*of.*account.*processed"
        subject.subject regex_match "confirm.your.account"
        subject.subject regex_match "courier.*able"
        subject.subject regex_match "crediential.*notif"
        subject.subject regex_match "deactivation.*in.*progress"
        subject.subject regex_match "delivery.*attempt.*failed"
        subject.subject regex_match "document.received"
        subject.subject regex_match "documented.*shared.*with.*you"
        subject.subject regex_match "dropbox.*document"
        subject.subject regex_match "e-?ma[il1]+ .{010}suspen"
        subject.subject regex_match "e-?ma[il1]{1} user"
        subject.subject regex_match "e-?ma[il1]{2} acc"
        subject.subject regex_match "e-?ma[il1]{2}.*up.?grade"
        subject.subject regex_match "e.?ma[il1]{2}.*server"
        subject.subject regex_match "e.?ma[il1]{2}.*suspend"
        subject.subject regex_match "email.update"
        subject.subject regex_match "faxed you"
        subject.subject regex_match "fraud(ulent)?.*charge"
        subject.subject regex_match "from.helpdesk"
        subject.subject regex_match "fu[il1]{2}.*ma[il1]+[ -]?box"
        subject.subject regex_match "has.been.*suspended"
        subject.subject regex_match "has.been.limited"
        subject.subject regex_match "have.locked"
        subject.subject regex_match "he[li]p ?desk upgrade"
        subject.subject regex_match "heipdesk"
        subject.subject regex_match "i[il]iega[il]"
        subject.subject regex_match "ii[il]ega[il]"
        subject.subject regex_match "incoming e?mail"
        subject.subject regex_match "incoming.*fax"
        subject.subject regex_match "lock.*security"
        subject.subject regex_match "ma[il1]{1}[ -]?box.*quo"
        subject.subject regex_match "ma[il1]{2}[ -]?box.*fu[il1]"
        subject.subject regex_match "ma[il1]{2}box stor"
        subject.subject regex_match "ma[il1]{2}box.*[il1]{2}mit"
        subject.subject regex_match "mail on.?hold"
        subject.subject regex_match "mail.*box.*migration"
        subject.subject regex_match "mail.*de-?activat"
        subject.subject regex_match "mail.update.required"
        subject.subject regex_match "mails.*pending"
        subject.subject regex_match "messages.*pending"
        subject.subject regex_match "missed.*shipping.*notification"
        subject.subject regex_match "missed.shipment.notification"
        subject.subject regex_match "must.update.your.account"
        subject.subject regex_match "new [sl][io]g?[nig][ -]?in from"
        subject.subject regex_match "new voice ?-?mail"
        subject.subject regex_match "notifications.*pending"
        subject.subject regex_match "office.*3.*6.*5.*suspend"
        subject.subject regex_match "office365"
        subject.subject regex_match "on google docs with you"
        subject.subject regex_match "online doc"
        subject.subject regex_match "password.*compromised"
        subject.subject regex_match "periodic maintenance"
        subject.subject regex_match "potential(ly)? unauthorized"
        subject.subject regex_match "refund not approved"
        subject.subject regex_match "report"
        subject.subject regex_match "revised.*policy"
        subject.subject regex_match "scam"
        subject.subject regex_match "scanned.?invoice"
        subject.subject regex_match "secured?.update"
        subject.subject regex_match "security breach"
        subject.subject regex_match "securlty"
        subject.subject regex_match "signed.*delivery"
        subject.subject regex_match "status of your .{314}? ?delivery"
        subject.subject regex_match "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty"
        subject.subject regex_match "suspicious.*sign.*[io]n"
        subject.subject regex_match "suspicious.activit"
        subject.subject regex_match "temporar(il)?y deactivate"
        subject.subject regex_match "temporar[il1]{2}y disab[li]ed"
        subject.subject regex_match "temporarily.*lock"
        subject.subject regex_match "termination.*notice"
        subject.subject regex_match "un-?usua[li].activity"
        subject.subject regex_match "unable.*deliver"
        subject.subject regex_match "unauthorized.*activit"
        subject.subject regex_match "unauthorized.device"
        subject.subject regex_match "undelivered message"
        subject.subject regex_match "unread.*doc"
        subject.subject regex_match "unusual.activity"
        subject.subject regex_match "upgrade.*account"
        subject.subject regex_match "upgrade.notice"
        subject.subject regex_match "urgent message"
        subject.subject regex_match "urgent.verification"
        subject.subject regex_match "v[il1]o[li1]at[il1]on security"
        subject.subject regex_match "va[il1]{1}date.*ma[il1]{2}[ -]?box"
        subject.subject regex_match "verification ?-?require"
        subject.subject regex_match "verification( )?-?need"
        subject.subject regex_match "verify.your?.account"
        subject.subject regex_match "web ?-?ma[il1]{2}"
        subject.subject regex_match "web[ -]?ma[il1]{2}"
        subject.subject regex_match "will.be.suspended"
        subject.subject regex_match "your (customer )?account .as"
        subject.subject regex_match "your.office.365"
        subject.subject regex_match "your.online.access"
         macro "any($suspicious_subjects, strings.icontains(subject.subject, .))"
         macro "any(ml.nlu_classifier(body.current_thread.text).entities,\n              .name == \"request\"\n          )"
         macro "any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).entities,\n                 .name == \"request\"\n          )"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
       macro "any(file.parse_eml(.).body.links,\n                (\n                  ml.link_analysis(., mode=\"aggressive\").credphish.disposition == \"phishing\"\n                  and ml.link_analysis(., mode=\"aggressive\").credphish.confidence in (\n                    \"medium\",\n                    \"high\"\n                  )\n                )\n\n                // or any links in the final dom lead to a suspicious tld\n                or any(ml.link_analysis(.).final_dom.links,\n                       .href_url.domain.tld in $suspicious_tlds\n                       or ml.link_analysis(.href_url).effective_url.domain.tld in $suspicious_tlds\n                )\n\n                // link redirects to a suspicious TLD\n                or any(ml.link_analysis(., mode=\"aggressive\").redirect_history,\n                       .domain.tld in $suspicious_tlds\n                )\n                or (\n                  // suspicious redirects\n                  // 3 or more different domains with 2 or more different TLDs\n                  // careful because click trackers will always make this at least 2\n                  // different domains and not unlikely 2 or more TLDs\n                  length(distinct(map(ml.link_analysis(., mode=\"aggressive\").redirect_history,\n                                      .domain.tld\n                                  )\n                         )\n                  ) >= 2\n                  and length(distinct(map(ml.link_analysis(., mode=\"aggressive\").redirect_history,\n                                          .domain.domain\n                                      )\n                             )\n                  ) >= 3\n                )\n        )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  not
    any(attachments)
      attachments.content_type eq "message/delivery-status"
  not
    or
      sender.email.local_part match "administrator"
      sender.email.local_part match "mailer-daemon"
      sender.email.local_part match "postmaster"
  not
    any(headers.references)
      strings.contains func_call "strings.contains(body.html.display_text, .)"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  not
    sender.display_name starts_with "Auto-reply"
  not
    subject.subject regex_match "^(undeliverable|read:)"
  attachments length_compare "1"
  sender.email.domain.root_domain eq "optonline.net"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments
sender.email.local_partmatchadministratorexcludes:sender.email.local_part field:"sender.email.local_part" value:"administrator"
sender.email.local_partmatchmailer-daemonexcludes:sender.email.local_part field:"sender.email.local_part" value:"mailer-daemon"
sender.email.local_partmatchpostmasterexcludes:sender.email.local_part field:"sender.email.local_part" value:"postmaster"
headers.referencesarray_any(no value, null check)excludes:headers.references
sender.display_namestarts_withAuto-replyexcludes:sender.display_name field:"sender.display_name" value:"Auto-reply"
subject.subjectregex_match^(undeliverable|read:)excludes:subject.subject field:"subject.subject" value:"^(undeliverable|read:)"

Attachment: EML with QR code redirecting to Cloudflare challenges

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

Detects EML attachments containing office documents, PDFs, or images with embedded QR codes that redirect to Cloudflare challenge pages, potentially used to bypass security measures.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, QR code

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • recipients
  • recipients.to[0]
  • type

Rule Body

type.inbound
and length(recipients.to) == 1
and recipients.to[0].email.domain.valid
and any(attachments,
        // Email Attachments
        any(file.parse_eml(.).attachments,
            (
              // looks for office docs in the attached eml
              .file_extension in $file_extensions_macros
              and any(file.explode(.),
                      .scan.qr.type == "url"
                      and regex.icontains(ml.link_analysis(.scan.qr.url).final_dom.raw,
                                          'challenges\.cloudflare\.com',
                      )
              )
            )
            or (
              // looks for pdfs and images in the attached eml
              //
              // This rule makes use of a beta feature and is subject to change without notice
              // using the beta feature in custom rules is not suggested until it has been formally released
              //
              any(beta.scan_qr(.).items,
                  .type is not null
                  and regex.icontains(ml.link_analysis(.url).final_dom.raw,
                                      'challenges\.cloudflare\.com'
                  )
              )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects EML attachments containing office documents, PDFs, or images with embedded QR codes that redirect to Cloudflare challenge pages, potentially used to bypass security measures.

  1. inbound message
  2. length(recipients.to) == 1
  3. recipients.to[0].email.domain.valid
  4. any of attachments where:
    • any(file.parse_eml(.).attachments, ( // looks for office docs in the attached eml .file_extension in $file_extensions_macros and any(file.explode(.), .scan.qr.type == "url" and regex.icontains(ml.link_analysis(.scan.qr.url).final_dom.raw, 'challenges\.cloudflare\.com', ) ) ) or ( // looks for pdfs and images in the attached eml // // This rule makes use of a beta feature and is subject to change without notice // using the beta feature in custom rules is not suggested until it has been formally released // any(beta.scan_qr(.).items, .type is not null and regex.icontains(ml.link_analysis(.url).final_dom.raw, 'challenges\.cloudflare\.com' ) ) ) )

Inspects: recipients.to, recipients.to[0].email.domain.valid, type.inbound. Sensors: beta.scan_qr, file.explode, file.parse_eml, ml.link_analysis, regex.icontains. Reference lists: $file_extensions_macros.

Indicators Matched (2)

FieldMatchValue
file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.typeequalsurl
regex.icontainsregexchallenges\.cloudflare\.com

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
     macro "any(file.parse_eml(.).attachments,\n            (\n              // looks for office docs in the attached eml\n              .file_extension in $file_extensions_macros\n              and any(file.explode(.),\n                      .scan.qr.type == \"url\"\n                      and regex.icontains(ml.link_analysis(.scan.qr.url).final_dom.raw,\n                                          'challenges\\.cloudflare\\.com',\n                      )\n              )\n            )\n            or (\n              // looks for pdfs and images in the attached eml\n              //\n              // This rule makes use of a beta feature and is subject to change without notice\n              // using the beta feature in custom rules is not suggested until it has been formally released\n              //\n              any(beta.scan_qr(.).items,\n                  .type is not null\n                  and regex.icontains(ml.link_analysis(.url).final_dom.raw,\n                                      'challenges\\.cloudflare\\.com'\n                  )\n              )\n            )\n        )"
  recipients.to length_compare "1"
  recipients.to[0].email.domain.valid eq "true"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
recipients.to[0].email.domain.valideq
  • true transforms: boolean corpus 15 (mql 15)
field:"recipients.to[0].email.domain.valid" kind:eq value:"true"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: EML with suspicious indicators

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

Attached EML contains suspicious indicators, such as a missing sender email or short HTML body.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, HTML smuggling, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.html
  • headers
  • headers.auth_summary
  • recipients
  • recipients.to
  • sender.email
  • type

Rule Body

type.inbound
and (
  // a single attachmed EML
  length(attachments) == 1
  // or a single attached EML with one or more images used in the body of the message
  // likely within the signatures
  or (
    length(filter(attachments,
                  .file_extension == "eml" or .content_type == "message/rfc822"
           )
    ) == 1
    and length(filter(attachments,
                      .file_type in $file_types_images
                      and (
                        any(regex.extract(.content_id, '^<(?P<cid>.*)\>$'),
                            strings.icontains(body.html.raw,
                                              .named_groups["cid"]
                            )
                        )
                        or strings.icontains(body.html.raw, .content_id)
                      )
               )
    ) == length(attachments) - 1
  )
)
and (
  length(body.current_thread.text) < 300
  or body.current_thread.text is null
  or any(ml.nlu_classifier(body.current_thread.text).intents,
         .name in ("cred_theft", "steal_pii")
  )
)
and not any(ml.nlu_classifier(body.current_thread.text).intents,
            .name == "benign" and .confidence == "high"
)
and any(attachments,
        (.file_extension == "eml" or .content_type == "message/rfc822")
        and (
          // suspicious indicators
          file.parse_eml(.).sender.email.email == ""
          or length(file.parse_eml(.).body.html.raw) < 10
          or length(file.parse_eml(.).headers.hops) < 2
          // the sender of the outer message is the recipient of the outer message
          // and the sender and recipient of the inner message
          or (
            sender.email.email in map(recipients.to, .email.email)
            and length(recipients.to) == 1
            and sender.email.email == file.parse_eml(.).sender.email.email
            and sender.email.email in map(file.parse_eml(.).recipients.to,
                                          .email.email
            )
            and length(file.parse_eml(.).recipients.to) == 1
          )
        )
        and not (
          all(file.parse_eml(.).body.links,
              .href_url.domain.root_domain in ("aka.ms", "office365.com")
              or .href_url.url == "#additionalatt"
          )
          and strings.icontains(file.parse_eml(.).body.current_thread.text,
                                "We’re making sure your attachments are safe"
          )
        )
        and file.parse_eml(.).sender.email.domain.root_domain not in $org_domains
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Attached EML contains suspicious indicators, such as a missing sender email or short HTML body.

  1. inbound message
  2. any of:
    • length(attachments) == 1
    • all of:
      • length(filter(attachments, .file_extension == "eml" or .content_type == "message/rfc822" ) ) == 1
      • length(filter(attachments, .file_type in $file_types_images and ( any(regex.extract(.content_id, '^<(?P<cid>.*)\>$'), strings.icontains(body.html.raw, .named_groups["cid"] ) ) or strings.icontains(body.html.raw, .content_id) ) ) ) == length(attachments) - 1
  3. any of:
    • length(body.current_thread.text) < 300
    • body.current_thread.text is missing
    • any(ml.nlu_classifier(body.current_thread.text).intents, .name in ("cred_theft", "steal_pii") )
  4. not:
    • any(ml.nlu_classifier(body.current_thread.text).intents, .name == "benign" and .confidence == "high" )
  5. any of attachments where all hold:
    • any of:
      • .file_extension is 'eml'
      • .content_type is 'message/rfc822'
    • any of:
      • file.parse_eml(.).sender.email.email == ""
      • length(file.parse_eml(.).body.html.raw) < 10
      • length(file.parse_eml(.).headers.hops) < 2
      • all of:
        • sender.email.email in map(recipients.to, .email.email)
        • length(recipients.to) == 1
        • sender.email.email is file.parse_eml(.).sender.email.email
        • sender.email.email in map(file.parse_eml(.).recipients.to, .email.email )
        • length(file.parse_eml(.).recipients.to) == 1
    • not:
      • all of:
        • all(file.parse_eml(.).body.links, .href_url.domain.root_domain in ("aka.ms", "office365.com") or .href_url.url == "#additionalatt" )
        • strings.icontains(file.parse_eml(.).body.current_thread.text, "We’re making sure your attachments are safe" )
    • file.parse_eml(.).sender.email.domain.root_domain not in $org_domains
  6. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  7. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_id, attachments[].content_type, attachments[].file_extension, attachments[].file_type, body.current_thread.text, body.html.raw, headers.auth_summary.dmarc.pass, recipients.to, recipients.to[].email.email, sender.email.domain.root_domain, sender.email.email, type.inbound. Sensors: file.parse_eml, ml.nlu_classifier, profile.by_sender, regex.extract, strings.icontains. Reference lists: $file_types_images, $high_trust_sender_root_domains, $org_domains.

Indicators Matched (5)

FieldMatchValue
attachments[].file_extensionequalseml
attachments[].content_typeequalsmessage/rfc822
regex.extractregex^<(?P<cid>.*)\>$
ml.nlu_classifier(body.current_thread.text).intents[].namemembercred_theft
ml.nlu_classifier(body.current_thread.text).intents[].namemembersteal_pii

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          length func_call "length(file.parse_eml(.).recipients.to) == 1"
          recipients.to length_compare "1"
          sender.email.email macro "sender.email.email == file.parse_eml(.).sender.email.email"
          sender.email.email macro "sender.email.email in map(file.parse_eml(.).recipients.to,\n                                          .email.email\n            )"
          sender.email.email macro "sender.email.email in map(recipients.to, .email.email)"
        file.parse_eml func_call "file.parse_eml(.).sender.email.email == \"\""
        length func_call "length(file.parse_eml(.).body.html.raw) < 10"
        length func_call "length(file.parse_eml(.).headers.hops) < 2"
      not
        and
          strings.icontains func_call "strings.icontains(file.parse_eml(.).body.current_thread.text,\n                                \"We’re making sure your attachments are safe\"\n          )"
           macro "all(file.parse_eml(.).body.links,\n              .href_url.domain.root_domain in (\"aka.ms\", \"office365.com\")\n              or .href_url.url == \"#additionalatt\"\n          )"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
      file.parse_eml func_call "file.parse_eml(.).sender.email.domain.root_domain not in $org_domains"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    and
      length func_call "length(filter(attachments,\n                  .file_extension == \"eml\" or .content_type == \"message/rfc822\"\n           )\n    ) == 1"
       macro "length(filter(attachments,\n                      .file_type in $file_types_images\n                      and (\n                        any(regex.extract(.content_id, '^<(?P<cid>.*)\\>$'),\n                            strings.icontains(body.html.raw,\n                                              .named_groups[\"cid\"]\n                            )\n                        )\n                        or strings.icontains(body.html.raw, .content_id)\n                      )\n               )\n    ) == length(attachments) - 1"
    attachments length_compare "1"
  or
    body.current_thread.text is_null
    body.current_thread.text length_compare "300"
     macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n         .name in (\"cred_theft\", \"steal_pii\")\n  )"
  not
     macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n            .name == \"benign\" and .confidence == \"high\"\n)"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textis_null
  • (no value, null check)
field:"body.current_thread.text" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: Emotet heavily padded doc in zip file

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

Detects a potential Emotet delivery method using padded .doc files that compress into small zip files. Contents may include Red Dawn templates exceeding 500MB.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension == "zip"
        and any(file.explode(.),
                .depth == 0
                and .size < 1000000
                and not .depth > 0
                and strings.ends_with(.scan.exiftool.zip_file_name, ".doc")
                and .scan.exiftool.zip_uncompressed_size > 500000000
        )
)
and (
  profile.by_sender().prevalence in ("new", "outlier")
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Detects a potential Emotet delivery method using padded .doc files that compress into small zip files. Contents may include Red Dawn templates exceeding 500MB.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension is 'zip'
    • any(file.explode(.), .depth == 0 and .size < 1000000 and not .depth > 0 and strings.ends_with(.scan.exiftool.zip_file_name, ".doc") and .scan.exiftool.zip_uncompressed_size > 500000000 )
  3. any of:
    • profile.by_sender().prevalence in ("new", "outlier")
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, profile.by_sender, strings.ends_with.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalszip
strings.ends_withsuffix.doc

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
  any(attachments)
    and
      attachments.file_extension eq "zip"
       macro "any(file.explode(.),\n                .depth == 0\n                and .size < 1000000\n                and not .depth > 0\n                and strings.ends_with(.scan.exiftool.zip_file_name, \".doc\")\n                and .scan.exiftool.zip_uncompressed_size > 500000000\n        )"
  type.inbound eq "true"

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"

Attachment: Employment contract update with suspicious file naming

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

Detects messages containing two attachments where one is a PowerPoint file with suspicious character substitution in the filename ('Empl0yment' using zero instead of 'o') and body text claiming an employment contract has been updated.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • type

Rule Body

type.inbound
// two attachments, one png and one pptx
and length(attachments) == 2
// the pptx has Empl0yment in name
and length(filter(attachments, strings.contains(.file_name, "Empl0yment"))) == 1
and strings.icontains(body.current_thread.text,
                      "Your Employment Contract has being updated"
)

Detection Logic

Scope: inbound message.

Detects messages containing two attachments where one is a PowerPoint file with suspicious character substitution in the filename ('Empl0yment' using zero instead of 'o') and body text claiming an employment contract has been updated.

  1. inbound message
  2. length(attachments) == 2
  3. length(filter(attachments, strings.contains(.file_name, "Empl0yment"))) == 1
  4. body.current_thread.text contains 'Your Employment Contract has being updated'

Inspects: attachments[].file_name, body.current_thread.text, type.inbound. Sensors: strings.contains, strings.icontains.

Indicators Matched (2)

FieldMatchValue
strings.containssubstringEmpl0yment
strings.icontainssubstringYour Employment Contract has being updated

Stages and Predicates

Stage 1: mql_rule

and
  attachments length_compare "2"
  body.current_thread.text contains "Your Employment Contract has being updated"
  length func_call "length(filter(attachments, strings.contains(.file_name, \"Empl0yment\"))) == 1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • Your Employment Contract has being updated
field:"body.current_thread.text" kind:contains value:"Your Employment Contract has being updated"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: Encrypted Microsoft Office file (unsolicited)

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

Encrypted OLE2 (eg Microsoft Office) attachment from an unsolicited sender. Attachment encryption is a common technique used to bypass malware scanning products. Use if receiving encrypted attachments is not normal behavior in your environment.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEncryption, Macros, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and file.oletools(.).indicators.encryption.exists
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Encrypted OLE2 (eg Microsoft Office) attachment from an unsolicited sender. Attachment encryption is a common technique used to bypass malware scanning products. Use if receiving encrypted attachments is not normal behavior in your environment.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • file.oletools(.).indicators.encryption.exists
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.oletools, profile.by_sender. Reference lists: $file_extensions_macros.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
      file.oletools func_call "file.oletools(.).indicators.encryption.exists"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

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"

Attachment: Encrypted PDF With Credential Harvesting Indicators

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

Detects encrypted PDF attachments containing patterns and indicators commonly associated with credential harvesting operations, identified through YARA signature analysis.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEncryption, Evasion, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name in ("pdf_encrypted_cred_phish_001"))
        )
)

Detection Logic

Scope: inbound message.

Detects encrypted PDF attachments containing patterns and indicators commonly associated with credential harvesting operations, identified through YARA signature analysis.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("pdf_encrypted_cred_phish_001")) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_encrypted_cred_phish_001

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name in (\"pdf_encrypted_cred_phish_001\"))\n        )\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"

Attachment: Encrypted PDF with credential theft body

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

Attached PDF is encrypted, and email body contains credential theft language. Seen in-the-wild impersonating e-fax services.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEncryption, Evasion, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.previous_threads
  • headers
  • headers.auth_summary
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.exiftool.fields, .key == "Encryption")
            or (
              .scan.entropy.entropy > 7
              and any(.scan.strings.strings, strings.icontains(., "/Encrypt"))
            )
        )
        // Encrypted PDFs do not have child nodes with any data
        and all(filter(file.explode(.), .depth > 0), .size == 0)
)
and (
  any(ml.nlu_classifier(body.current_thread.text).intents,
      .name == "cred_theft" and .confidence in ("medium", "high")
  )
  or any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents,
         .name == "cred_theft" and .confidence in ("medium", "high")
  )
  or regex.icontains(body.current_thread.text,
                     'PDF\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))',
                     '(Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:',
                     'Th(?:is|e)\s+(?:file|document|pdf)\s+is\s+(?:pin|password)[-\s]?\s*protected[[:punct:]]\s*The\s+p(?:in|assword)\s+is\s*:?',
                     '(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)',
                     'The\s+(?:file|document|pdf|attachment)\s+(?:pass(?:code|word)|access\s*code)\s+is\s*'
  )
  or (
    (
      length(body.current_thread.text) <= 10
      or (body.current_thread.text is null)
    )
    and any(body.previous_threads,
            regex.icontains(.text,
                            'PDF\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))',
                            '(Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:',
                            'Th(?:is|e)\s+(?:file|document|pdf)\s+is\s+(?:pin|password)[-\s]?\s*protected[[:punct:]]\s*The\s+p(?:in|assword)\s+is\s*:?',
                            '(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)',
                            'The\s+(?:file|document|pdf|attachment)\s+(?:pass(?:code|word)|access\s*code)\s+is\s*'
            )
    )
  )
)
// not forwards/replies
and not (
  (length(headers.references) > 0 or headers.in_reply_to is not null)
  and (subject.is_forward or subject.is_reply)
  and length(body.previous_threads) >= 1
)
and (
  (
    profile.by_sender_email().prevalence in ("new", "outlier")
    and not profile.by_sender_email().solicited
  )
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
  or (
    length(recipients.to) == 0
    or all(recipients.to,
           strings.ilike(.display_name, "undisclosed?recipients")
    )
  )
  or (
    length(recipients.to) == 1
    and any(recipients.to, .email.email == sender.email.email)
  )
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Attached PDF is encrypted, and email body contains credential theft language. Seen in-the-wild impersonating e-fax services.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.exiftool.fields, .key == "Encryption") or ( .scan.entropy.entropy > 7 and any(.scan.strings.strings, strings.icontains(., "/Encrypt")) ) ) // Encrypted PDFs do not have child nodes with any data and all(filter(file.explode(.), .depth > 0), .size == 0) )
  3. any of:
    • any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence in ("medium", "high") )
    • any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents, .name == "cred_theft" and .confidence in ("medium", "high") )
    • body.current_thread.text matches any of 5 patterns
      • PDF\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))
      • (Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:
      • Th(?:is|e)\s+(?:file|document|pdf)\s+is\s+(?:pin|password)[-\s]?\s*protected[[:punct:]]\s*The\s+p(?:in|assword)\s+is\s*:?
      • (?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)
      • The\s+(?:file|document|pdf|attachment)\s+(?:pass(?:code|word)|access\s*code)\s+is\s*
    • all of:
      • any of:
        • length(body.current_thread.text) <= 10
        • body.current_thread.text is missing
      • any of body.previous_threads where:
        • .text matches any of 5 patterns
          • PDF\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))
          • (Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:
          • Th(?:is|e)\s+(?:file|document|pdf)\s+is\s+(?:pin|password)[-\s]?\s*protected[[:punct:]]\s*The\s+p(?:in|assword)\s+is\s*:?
          • (?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)
          • The\s+(?:file|document|pdf|attachment)\s+(?:pass(?:code|word)|access\s*code)\s+is\s*
  4. not:
    • all of:
      • any of:
        • length(headers.references) > 0
        • headers.in_reply_to is set
      • any of:
        • subject.is_forward
        • subject.is_reply
      • length(body.previous_threads) >= 1
  5. any of:
    • all of:
      • profile.by_sender_email().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender_email().solicited
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
    • any of:
      • length(recipients.to) == 0
      • all of recipients.to where:
        • .display_name matches 'undisclosed?recipients'
    • all of:
      • length(recipients.to) == 1
      • any of recipients.to where:
        • .email.email is sender.email.email
  6. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].file_type, body.current_thread.text, body.previous_threads, body.previous_threads[].text, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, recipients.to, recipients.to[].display_name, recipients.to[].email.email, sender.email.domain.root_domain, sender.email.email, subject.is_forward, subject.is_reply, type.inbound. Sensors: beta.ocr, file.explode, file.message_screenshot, ml.nlu_classifier, profile.by_sender_email, regex.icontains, strings.icontains, strings.ilike. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (15)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.exiftool.fields[].keyequalsEncryption
strings.icontainssubstring/Encrypt
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidencemembermedium
ml.nlu_classifier(body.current_thread.text).intents[].confidencememberhigh
ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents[].nameequalscred_theft
ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents[].confidencemembermedium
ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents[].confidencememberhigh
regex.icontainsregexPDF\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))
regex.icontainsregex(Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:
regex.icontainsregexTh(?:is|e)\s+(?:file|document|pdf)\s+is\s+(?:pin|password)[-\s]?\s*protected[[:punct:]]\s*The\s+p(?:in|assword)\s+is\s*:?
3 more
regex.icontainsregex(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)
regex.icontainsregexThe\s+(?:file|document|pdf|attachment)\s+(?:pass(?:code|word)|access\s*code)\s+is\s*
strings.ilikesubstringundisclosed?recipients

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      any(body.previous_threads)
        or
          body.previous_threads.text regex_match "(?:Access|Preview|Unlock|Decrypt)\\s+(?:\\S+\\s+){0,3}(?:PDF|statement)(?:\\S+\\s+){0,3}(?:pass(?:word|code)|\\s*with\\s+\\S+)"
          body.previous_threads.text regex_match "(Access|Preview|Unlock|Decrypt|Pass)\\s*(?:word|code)\\s*(?:\\S+\\s+){0,3}PDF\\s*is?\\s*:"
          body.previous_threads.text regex_match "PDF\\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))"
          body.previous_threads.text regex_match "Th(?:is|e)\\s+(?:file|document|pdf)\\s+is\\s+(?:pin|password)[-\\s]?\\s*protected[[:punct:]]\\s*The\\s+p(?:in|assword)\\s+is\\s*:?"
          body.previous_threads.text regex_match "The\\s+(?:file|document|pdf|attachment)\\s+(?:pass(?:code|word)|access\\s*code)\\s+is\\s*"
      or
        body.current_thread.text is_null
        body.current_thread.text length_compare "10"
    body.current_thread.text regex_match "(?:Access|Preview|Unlock|Decrypt)\\s+(?:\\S+\\s+){0,3}(?:PDF|statement)(?:\\S+\\s+){0,3}(?:pass(?:word|code)|\\s*with\\s+\\S+)"
    body.current_thread.text regex_match "(Access|Preview|Unlock|Decrypt|Pass)\\s*(?:word|code)\\s*(?:\\S+\\s+){0,3}PDF\\s*is?\\s*:"
    body.current_thread.text regex_match "PDF\\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))"
    body.current_thread.text regex_match "Th(?:is|e)\\s+(?:file|document|pdf)\\s+is\\s+(?:pin|password)[-\\s]?\\s*protected[[:punct:]]\\s*The\\s+p(?:in|assword)\\s+is\\s*:?"
    body.current_thread.text regex_match "The\\s+(?:file|document|pdf|attachment)\\s+(?:pass(?:code|word)|access\\s*code)\\s+is\\s*"
     macro "any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents,\n         .name == \"cred_theft\" and .confidence in (\"medium\", \"high\")\n  )"
     macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n      .name == \"cred_theft\" and .confidence in (\"medium\", \"high\")\n  )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    and
      or
        headers.in_reply_to is_not_null
        headers.references length_compare "0"
      or
        subject.is_forward eq "true"
        subject.is_reply eq "true"
      body.previous_threads length_compare "1"
  or
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().solicited"
      profile.by_sender_email func_call "profile.by_sender_email().prevalence in (\"new\", \"outlier\")"
    and
      any(recipients.to)
        recipients.to.email.email cross_field_compare "sender.email.email"
      recipients.to length_compare "1"
    recipients.to length_compare "0"
     macro "all(recipients.to,\n           strings.ilike(.display_name, \"undisclosed?recipients\")\n    )"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.exiftool.fields, .key == \"Encryption\")\n            or (\n              .scan.entropy.entropy > 7\n              and any(.scan.strings.strings, strings.icontains(., \"/Encrypt\"))\n            )\n        )\n        // Encrypted PDFs do not have child nodes with any data\n        and all(filter(file.explode(.), .depth > 0), .size == 0)\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textis_null
  • (no value, null check)
field:"body.current_thread.text" kind:is_null
body.current_thread.textregex_match
  • (?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)
  • (Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:
  • PDF\s*(?:Access|Preview|Unlock|Decrypt|pass(?:code|word))
  • Th(?:is|e)\s+(?:file|document|pdf)\s+is\s+(?:pin|password)[-\s]?\s*protected[[:punct:]]\s*The\s+p(?:in|assword)\s+is\s*:?
  • The\s+(?:file|document|pdf|attachment)\s+(?:pass(?:code|word)|access\s*code)\s+is\s*
field:"body.current_thread.text" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.in_reply_tois_not_null(no value, null check)excludes:headers.in_reply_to
headers.referenceslength_compare0excludes:headers.references field:"headers.references" value:"0"
subject.is_forwardeqtrueexcludes:subject.is_forward field:"subject.is_forward" value:"true"
subject.is_replyeqtrueexcludes:subject.is_reply field:"subject.is_reply" value:"true"
body.previous_threadslength_compare1excludes:body.previous_threads field:"body.previous_threads" value:"1"

Attachment: Encrypted PDF with credential theft language in EML

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

Attached PDF is encrypted, and email body contains credential theft language, wrapped in an attached .eml file. Seen in-the-wild impersonating e-fax services.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEncryption, Evasion, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • headers
  • headers.auth_summary
  • recipients
  • recipients.cc
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and any(attachments,
        any(filter(file.parse_eml(.).attachments, .file_type == "pdf"),
            any(file.explode(.),
                any(.scan.exiftool.fields, .key == "Encryption")
                or (
                  .scan.entropy.entropy > 7
                  and any(.scan.strings.strings,
                          strings.icontains(., "/Encrypt")
                  )
                )
            )
            // Encrypted PDFs do not have child nodes with any data
            and all(filter(file.explode(.), .depth > 0), .size == 0)
        )
        and (
          any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents,
              .name == "cred_theft" and .confidence in ("medium", "high")
          )
          or any(ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(.
                                                                 ).body.html
                                            )
                                   ).text
                 ).intents,
                 .name == "cred_theft" and .confidence in ("medium", "high")
          )
          or regex.icontains(file.parse_eml(.).body.current_thread.text,
                             'PDF\s*(?:Access|Preview|Unlock|Decrypt|passcode)',
                             '(?:Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:',
                             'This\s+(?:file|document|pdf)\s+is\s+(?:password[-\s]?)\s+protected\.\s*The\s+password\s+is\s*:?',
                             '(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)'
          )
          or (
            (
              length(file.parse_eml(.).body.current_thread.text) <= 10
              or (file.parse_eml(.).body.current_thread.text is null)
            )
            and any(file.parse_eml(.).body.previous_threads,
                    regex.icontains(.text,
                                    'PDF\s*(?:Access|Preview|Unlock|Decrypt|passcode)',
                                    '(?:Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:',
                                    'This\s+(?:file|document|pdf)\s+is\s+(?:password[-\s]?)\s+protected\.\s*The\s+password\s+is\s*:?',
                                    '(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)'
                    )
            )
          )
        )
)
// not forwards/replies
and not (
  (length(headers.references) > 0 or headers.in_reply_to is not null)
  and (subject.is_forward or subject.is_reply)
  and length(body.previous_threads) >= 1
)
and (
  (
    profile.by_sender_email().prevalence in ("new", "outlier")
    and not profile.by_sender_email().solicited
  )
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
  or (
    length(recipients.to) == 0
    or (
      all(recipients.to, .email.domain.valid == false)
      and all(recipients.cc, .email.domain.valid == false)
    )
  )
  or (
    length(recipients.to) == 1
    and any(recipients.to, .email.email == sender.email.email)
  )
)
// 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.

Attached PDF is encrypted, and email body contains credential theft language, wrapped in an attached .eml file. Seen in-the-wild impersonating e-fax services.

  1. inbound message
  2. any of attachments where all hold:
    • any(filter(file.parse_eml(.).attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.exiftool.fields, .key == "Encryption") or ( .scan.entropy.entropy > 7 and any(.scan.strings.strings, strings.icontains(., "/Encrypt") ) ) ) // Encrypted PDFs do not have child nodes with any data and all(filter(file.explode(.), .depth > 0), .size == 0) )
    • any of:
      • any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents, .name == "cred_theft" and .confidence in ("medium", "high") )
      • any(ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(. ).body.html ) ).text ).intents, .name == "cred_theft" and .confidence in ("medium", "high") )
      • regex.icontains(file.parse_eml(.).body.current_thread.text, 'PDF\s*(?:Access|Preview|Unlock|Decrypt|passcode)', '(?:Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:', 'This\s+(?:file|document|pdf)\s+is\s+(?:password[-\s]?)\s+protected\.\s*The\s+password\s+is\s*:?', '(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)' )
      • all of:
        • any of:
          • length(file.parse_eml(.).body.current_thread.text) <= 10
          • (file.parse_eml(.).body.current_thread.text is null)
        • any(file.parse_eml(.).body.previous_threads, regex.icontains(.text, 'PDF\s*(?:Access|Preview|Unlock|Decrypt|passcode)', '(?:Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:', 'This\s+(?:file|document|pdf)\s+is\s+(?:password[-\s]?)\s+protected\.\s*The\s+password\s+is\s*:?', '(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)' ) )
  3. not:
    • all of:
      • any of:
        • length(headers.references) > 0
        • headers.in_reply_to is set
      • any of:
        • subject.is_forward
        • subject.is_reply
      • length(body.previous_threads) >= 1
  4. any of:
    • all of:
      • profile.by_sender_email().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender_email().solicited
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
    • any of:
      • length(recipients.to) == 0
      • all of:
        • all of recipients.to where:
          • .email.domain.valid is False
        • all of recipients.cc where:
          • .email.domain.valid is False
    • all of:
      • length(recipients.to) == 1
      • any of recipients.to where:
        • .email.email is sender.email.email
  5. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: body.previous_threads, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, recipients.cc, recipients.cc[].email.domain.valid, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, sender.email.domain.root_domain, sender.email.email, subject.is_forward, subject.is_reply, type.inbound. Sensors: beta.ocr, file.explode, file.html_screenshot, file.parse_eml, ml.nlu_classifier, profile.by_sender_email, regex.icontains, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (13)

FieldMatchValue
file.parse_eml(attachments[]).attachments[].file_typeequalspdf
file.explode(filter(...)[])[].scan.exiftool.fields[].keyequalsEncryption
strings.icontainssubstring/Encrypt
ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].confidencemembermedium
ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].confidencememberhigh
ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(attachments[]).body.html)).text).intents[].nameequalscred_theft
ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(attachments[]).body.html)).text).intents[].confidencemembermedium
ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(attachments[]).body.html)).text).intents[].confidencememberhigh
regex.icontainsregexPDF\s*(?:Access|Preview|Unlock|Decrypt|passcode)
regex.icontainsregex(?:Access|Preview|Unlock|Decrypt|Pass)\s*(?:word|code)\s*(?:\S+\s+){0,3}PDF\s*is?\s*:
regex.icontainsregexThis\s+(?:file|document|pdf)\s+is\s+(?:password[-\s]?)\s+protected\.\s*The\s+password\s+is\s*:?
1 more
regex.icontainsregex(?:Access|Preview|Unlock|Decrypt)\s+(?:\S+\s+){0,3}(?:PDF|statement)(?:\S+\s+){0,3}(?:pass(?:word|code)|\s*with\s+\S+)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          or
            length func_call "length(file.parse_eml(.).body.current_thread.text) <= 10"
             macro "(file.parse_eml(.).body.current_thread.text is null)"
           macro "any(file.parse_eml(.).body.previous_threads,\n                    regex.icontains(.text,\n                                    'PDF\\s*(?:Access|Preview|Unlock|Decrypt|passcode)',\n                                    '(?:Access|Preview|Unlock|Decrypt|Pass)\\s*(?:word|code)\\s*(?:\\S+\\s+){0,3}PDF\\s*is?\\s*:',\n                                    'This\\s+(?:file|document|pdf)\\s+is\\s+(?:password[-\\s]?)\\s+protected\\.\\s*The\\s+password\\s+is\\s*:?',\n                                    '(?:Access|Preview|Unlock|Decrypt)\\s+(?:\\S+\\s+){0,3}(?:PDF|statement)(?:\\S+\\s+){0,3}(?:pass(?:word|code)|\\s*with\\s+\\S+)'\n                    )\n            )"
        regex.icontains func_call "regex.icontains(file.parse_eml(.).body.current_thread.text,\n                             'PDF\\s*(?:Access|Preview|Unlock|Decrypt|passcode)',\n                             '(?:Access|Preview|Unlock|Decrypt|Pass)\\s*(?:word|code)\\s*(?:\\S+\\s+){0,3}PDF\\s*is?\\s*:',\n                             'This\\s+(?:file|document|pdf)\\s+is\\s+(?:password[-\\s]?)\\s+protected\\.\\s*The\\s+password\\s+is\\s*:?',\n                             '(?:Access|Preview|Unlock|Decrypt)\\s+(?:\\S+\\s+){0,3}(?:PDF|statement)(?:\\S+\\s+){0,3}(?:pass(?:word|code)|\\s*with\\s+\\S+)'\n          )"
         macro "any(ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(.\n                                                                 ).body.html\n                                            )\n                                   ).text\n                 ).intents,\n                 .name == \"cred_theft\" and .confidence in (\"medium\", \"high\")\n          )"
         macro "any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents,\n              .name == \"cred_theft\" and .confidence in (\"medium\", \"high\")\n          )"
       macro "any(filter(file.parse_eml(.).attachments, .file_type == \"pdf\"),\n            any(file.explode(.),\n                any(.scan.exiftool.fields, .key == \"Encryption\")\n                or (\n                  .scan.entropy.entropy > 7\n                  and any(.scan.strings.strings,\n                          strings.icontains(., \"/Encrypt\")\n                  )\n                )\n            )\n            // Encrypted PDFs do not have child nodes with any data\n            and all(filter(file.explode(.), .depth > 0), .size == 0)\n        )"
  not
    and
      or
        headers.in_reply_to is_not_null
        headers.references length_compare "0"
      or
        subject.is_forward eq "true"
        subject.is_reply eq "true"
      body.previous_threads length_compare "1"
  or
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().solicited"
      profile.by_sender_email func_call "profile.by_sender_email().prevalence in (\"new\", \"outlier\")"
    and
      any(recipients.to)
        recipients.to.email.email cross_field_compare "sender.email.email"
      recipients.to length_compare "1"
    and
       macro "all(recipients.cc, .email.domain.valid == false)"
       macro "all(recipients.to, .email.domain.valid == false)"
    recipients.to length_compare "0"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.in_reply_tois_not_null(no value, null check)excludes:headers.in_reply_to
headers.referenceslength_compare0excludes:headers.references field:"headers.references" value:"0"
subject.is_forwardeqtrueexcludes:subject.is_forward field:"subject.is_forward" value:"true"
subject.is_replyeqtrueexcludes:subject.is_reply field:"subject.is_reply" value:"true"
body.previous_threadslength_compare1excludes:body.previous_threads field:"body.previous_threads" value:"1"
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: Encrypted ZIP containing VHDX file

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

Detects ZIP attachments that are encrypted and contain VHDX files, which may be used to bypass security controls or deliver malicious payloads.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEncryption, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "zip"),
        any(file.explode(.),
            .scan.zip.encrypted == true
            and any(.scan.zip.all_paths, strings.ends_with(., "vhdx"))
        )
)

Detection Logic

Scope: inbound message.

Detects ZIP attachments that are encrypted and contain VHDX files, which may be used to bypass security controls or deliver malicious payloads.

  1. inbound message
  2. any(filter(attachments, .file_type == "zip"), any(file.explode(.), .scan.zip.encrypted == true and any(.scan.zip.all_paths, strings.ends_with(., "vhdx")) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, strings.ends_with.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalszip
strings.ends_withsuffixvhdx

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"zip\"),\n        any(file.explode(.),\n            .scan.zip.encrypted == true\n            and any(.scan.zip.all_paths, strings.ends_with(., \"vhdx\"))\n        )\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"

Attachment: Excel file with document sharing lure created by Go Excelize

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

Detects Excel macro files created with the Go Excelize library containing document sharing language such as 'sent document', 'shared file', or 'REVIEW DOCUMENT'. These files are often used as lures to trick users into enabling macros or downloading malicious content.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesMacros, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments,
               .file_extension in $file_extensions_macros
               // limit the size to reduce FPs, the larger the document, the more likely it is for FPs on benign automated reports
               and .size < 2000000
        ),
        any(file.explode(.),
            // document sharing lure
            (
              length(.scan.strings.raw, ) < 1000
              and regex.icontains(.scan.strings.raw,
                                  '(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)',
              )
            )
            or strings.icontains(.scan.strings.raw,
                                 'Please download this spreadsheet or SVG and click'
            )
            or (
              length(.scan.strings.raw) < 500
              and strings.contains(.scan.strings.raw, 'REVIEW DOCUMENT')
            )
        )
        and beta.parse_exif(.).creator == "xuri"
        and any(beta.parse_exif(.).fields,
                .key == "Application" and .value == "Go Excelize"
        )
)

Detection Logic

Scope: inbound message.

Detects Excel macro files created with the Go Excelize library containing document sharing language such as 'sent document', 'shared file', or 'REVIEW DOCUMENT'. These files are often used as lures to trick users into enabling macros or downloading malicious content.

  1. inbound message
  2. any(filter(attachments, .file_extension in $file_extensions_macros // limit the size to reduce FPs, the larger the document, the more likely it is for FPs on benign automated reports and .size < 2000000 ), any(file.explode(.), // document sharing lure ( length(.scan.strings.raw, ) < 1000 and regex.icontains(.scan.strings.raw, '(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)', ) ) or strings.icontains(.scan.strings.raw, 'Please download this spreadsheet or SVG and click' ) or ( length(.scan.strings.raw) < 500 and strings.contains(.scan.strings.raw, 'REVIEW DOCUMENT') ) ) and beta.parse_exif(.).creator == "xuri" and any(beta.parse_exif(.).fields, .key == "Application" and .value == "Go Excelize" ) )

Inspects: attachments[].file_extension, attachments[].size, type.inbound. Sensors: beta.parse_exif, file.explode, regex.icontains, strings.contains, strings.icontains. Reference lists: $file_extensions_macros.

Indicators Matched (5)

FieldMatchValue
regex.icontainsregex(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)
strings.icontainssubstringPlease download this spreadsheet or SVG and click
strings.containssubstringREVIEW DOCUMENT
beta.parse_exif(filter(attachments)[]).fields[].keyequalsApplication
beta.parse_exif(filter(attachments)[]).fields[].valueequalsGo Excelize

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .file_extension in $file_extensions_macros\n               // limit the size to reduce FPs, the larger the document, the more likely it is for FPs on benign automated reports\n               and .size < 2000000\n        ),\n        any(file.explode(.),\n            // document sharing lure\n            (\n              length(.scan.strings.raw, ) < 1000\n              and regex.icontains(.scan.strings.raw,\n                                  '(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)',\n              )\n            )\n            or strings.icontains(.scan.strings.raw,\n                                 'Please download this spreadsheet or SVG and click'\n            )\n            or (\n              length(.scan.strings.raw) < 500\n              and strings.contains(.scan.strings.raw, 'REVIEW DOCUMENT')\n            )\n        )\n        and beta.parse_exif(.).creator == \"xuri\"\n        and any(beta.parse_exif(.).fields,\n                .key == \"Application\" and .value == \"Go Excelize\"\n        )\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"

Attachment: Excel file with suspicious template identifier

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

Detects Excel attachments containing a specific template identifier (TM16390866) in the EXIF metadata, which may indicate malicious or suspicious document templates being used to distribute harmful content.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Macros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type == "xlsx"
        and any(beta.parse_exif(.).fields,
                .key == "Template" and .value == "TM16390866"
        )
)

Detection Logic

Scope: inbound message.

Detects Excel attachments containing a specific template identifier (TM16390866) in the EXIF metadata, which may indicate malicious or suspicious document templates being used to distribute harmful content.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'xlsx'
    • any(beta.parse_exif(.).fields, .key == "Template" and .value == "TM16390866" )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsxlsx
beta.parse_exif(attachments[]).fields[].keyequalsTemplate
beta.parse_exif(attachments[]).fields[].valueequalsTM16390866

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type eq "xlsx"
       macro "any(beta.parse_exif(.).fields,\n                .key == \"Template\" and .value == \"TM16390866\"\n        )"
  type.inbound eq "true"

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"

Attachment: Excel Web Query File (IQY)

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

Recursively scans files and archives to detect IQY files. Coercing a target user into providing credentials to an attacker-controlled web server, or for SMB relaying.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and (
  any(attachments, .file_extension =~ "iqy")
  or (
    any(attachments,
        .file_extension in~ $file_extensions_common_archives
        and any(file.explode(.), .file_extension =~ "iqy")
    )
  )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect IQY files. Coercing a target user into providing credentials to an attacker-controlled web server, or for SMB relaying.

  1. inbound message
  2. any of:
    • any of attachments where:
      • .file_extension is 'iqy'
    • any of attachments where all hold:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), .file_extension =~ "iqy")

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalsiqy
file.explode(attachments[])[].file_extensionequalsiqy

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.), .file_extension =~ \"iqy\")"
    any(attachments)
      attachments.file_extension eq "iqy"
  type.inbound eq "true"

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"

Attachment: Fake attachment image lure

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

Message (or attached message) contains an image impersonating an Outlook attachment button.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, Image as content, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.html
  • headers
  • headers.auth_summary
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and length(attachments) < 15
and (
  // fake file attachment preview in original email
  any(attachments,
      .file_type in $file_types_images
      and (
        any(ml.logo_detect(.).brands,
            .name == "FakeAttachment" and .confidence == "high"
        )
        or (
          .size < 30000
          and any(file.explode(.),
                  strings.icontains(.scan.ocr.raw, 'sent you')
                  // the attached image includes a filesize string
                  and regex.icontains(.scan.ocr.raw,
                                      '\b\d+.\d{1,2}\s?(k|m)b(\s|$)'
                  )
          )
        )
      )
  )
  // message body/screenhot
  or any(ml.logo_detect(file.message_screenshot()).brands,
         .name == "FakeAttachment" and .confidence == "high"
  )

  // Suspicious table with file size indicators
  or regex.contains(body.html.raw,
                    "<table[^>]*>.*?<img[^>]+src=[\"']cid:[^\"']+[\"'][^>]*>.*?\\.(pdf|doc(x)|xls(x)?).*?<font[^>]*>\\s*\\d{1,4}\\.\\d{1,2}\\s*k[bB]"
  )

  // fake file attachment preview in attached EML
  or any(attachments,
         (.content_type == "message/rfc822" or .file_extension == "eml")
         and any(file.parse_eml(.).attachments,
                 .file_type in $file_types_images
                 and (
                   any(ml.logo_detect(.).brands, .name == "FakeAttachment")
                   or (
                     .size < 30000
                     and any(file.explode(.),
                             strings.icontains(.scan.ocr.raw, 'sent you')
                             // the attached image includes a filesize string
                             and regex.icontains(.scan.ocr.raw,
                                                 '\b\d+.\d{1,2}\s?(k|m)b(\s|$)'
                             )
                     )
                   )
                 )
         )
  )
)
and not (
  (
    strings.istarts_with(subject.subject, "RE:")
    or strings.istarts_with(subject.subject, "R:")
    or strings.istarts_with(subject.subject, "ODG:")
    or strings.istarts_with(subject.subject, "答复:")
    or strings.istarts_with(subject.subject, "AW:")
    or strings.istarts_with(subject.subject, "TR:")
    or strings.istarts_with(subject.subject, "FWD:")
    or regex.imatch(subject.subject, '(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:')
    or regex.imatch(subject.subject,
                    '^\[?(EXT|EXTERNAL)\]?[: ]\s*(RE|FWD?|FW|AW|TR|ODG|答复):.*'
    )
  )
  and (length(headers.references) > 0 or headers.in_reply_to is not null)
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  sender.email.domain.root_domain not in ("sharepointonline.com")
  or not headers.auth_summary.dmarc.pass
)

Detection Logic

Scope: inbound message.

Message (or attached message) contains an image impersonating an Outlook attachment button.

  1. inbound message
  2. length(attachments) < 15
  3. any of:
    • any of attachments where all hold:
      • .file_type in $file_types_images
      • any of:
        • any(ml.logo_detect(.).brands, .name == "FakeAttachment" and .confidence == "high" )
        • all of:
          • .size < 30000
          • any(file.explode(.), strings.icontains(.scan.ocr.raw, 'sent you') // the attached image includes a filesize string and regex.icontains(.scan.ocr.raw, '\b\d+.\d{1,2}\s?(k|m)b(\s|$)' ) )
    • any(ml.logo_detect(file.message_screenshot()).brands, .name == "FakeAttachment" and .confidence == "high" )
    • body.html.raw matches '<table[^>]*>.*?<img[^>]+src=[\\"\']cid:[^\\"\']+[\\"\'][^>]*>.*?\\\\.(pdf|doc(x)|xls(x)?).*?<font[^>]*>\\\\s*\\\\d{1,4}\\\\.\\\\d{1,2}\\\\s*k[bB]'
    • any of attachments where all hold:
      • any of:
        • .content_type is 'message/rfc822'
        • .file_extension is 'eml'
      • any(file.parse_eml(.).attachments, .file_type in $file_types_images and ( any(ml.logo_detect(.).brands, .name == "FakeAttachment") or ( .size < 30000 and any(file.explode(.), strings.icontains(.scan.ocr.raw, 'sent you') // the attached image includes a filesize string and regex.icontains(.scan.ocr.raw, '\b\d+.\d{1,2}\s?(k|m)b(\s|$)' ) ) ) ) )
  4. not:
    • all of:
      • any of:
        • subject.subject starts with 'RE:'
        • subject.subject starts with 'R:'
        • subject.subject starts with 'ODG:'
        • subject.subject starts with '答复:'
        • subject.subject starts with 'AW:'
        • subject.subject starts with 'TR:'
        • subject.subject starts with 'FWD:'
        • subject.subject matches '(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?)\\s?:'
        • subject.subject matches '^\\[?(EXT|EXTERNAL)\\]?[: ]\\s*(RE|FWD?|FW|AW|TR|ODG|答复):.*'
      • any of:
        • length(headers.references) > 0
        • headers.in_reply_to is set
  5. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  6. any of:
    • sender.email.domain.root_domain not in ('sharepointonline.com')
    • not:
      • headers.auth_summary.dmarc.pass

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, body.html.raw, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, file.message_screenshot, file.parse_eml, ml.logo_detect, regex.contains, regex.icontains, regex.imatch, strings.icontains, strings.istarts_with. Reference lists: $file_types_images, $high_trust_sender_root_domains.

Indicators Matched (10)

FieldMatchValue
ml.logo_detect(attachments[]).brands[].nameequalsFakeAttachment
ml.logo_detect(attachments[]).brands[].confidenceequalshigh
strings.icontainssubstringsent you
regex.icontainsregex\b\d+.\d{1,2}\s?(k|m)b(\s|$)
ml.logo_detect(file.message_screenshot()).brands[].nameequalsFakeAttachment
ml.logo_detect(file.message_screenshot()).brands[].confidenceequalshigh
regex.containsregex<table[^>]*>.*?<img[^>]+src=[\"']cid:[^\"']+[\"'][^>]*>.*?\\.(pdf|doc(x)|xls(x)?).*?<font[^>]*>\\s*\\d{1,4}\\.\\d{1,2}\\s*k[bB]
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionequalseml
ml.logo_detect(file.parse_eml(attachments[]).attachments[]).brands[].nameequalsFakeAttachment

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        or
          and
            attachments.size lt "30000"
             macro "any(file.explode(.),\n                  strings.icontains(.scan.ocr.raw, 'sent you')\n                  // the attached image includes a filesize string\n                  and regex.icontains(.scan.ocr.raw,\n                                      '\\b\\d+.\\d{1,2}\\s?(k|m)b(\\s|$)'\n                  )\n          )"
           macro "any(ml.logo_detect(.).brands,\n            .name == \"FakeAttachment\" and .confidence == \"high\"\n        )"
        attachments.file_type macro "attachments[].file_type in file_types_images"
    any(attachments)
      and
        or
          attachments.content_type eq "message/rfc822"
          attachments.file_extension eq "eml"
         macro "any(file.parse_eml(.).attachments,\n                 .file_type in $file_types_images\n                 and (\n                   any(ml.logo_detect(.).brands, .name == \"FakeAttachment\")\n                   or (\n                     .size < 30000\n                     and any(file.explode(.),\n                             strings.icontains(.scan.ocr.raw, 'sent you')\n                             // the attached image includes a filesize string\n                             and regex.icontains(.scan.ocr.raw,\n                                                 '\\b\\d+.\\d{1,2}\\s?(k|m)b(\\s|$)'\n                             )\n                     )\n                   )\n                 )\n         )"
    body.html.raw regex_match "<table[^>]*>.*?<img[^>]+src=[\\\"']cid:[^\\\"']+[\\\"'][^>]*>.*?\\\\.(pdf|doc(x)|xls(x)?).*?<font[^>]*>\\\\s*\\\\d{1,4}\\\\.\\\\d{1,2}\\\\s*k[bB]"
     macro "any(ml.logo_detect(file.message_screenshot()).brands,\n         .name == \"FakeAttachment\" and .confidence == \"high\"\n  )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    and
      or
        headers.in_reply_to is_not_null
        headers.references length_compare "0"
      or
        subject.subject regex_match "(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?)\\s?:"
        subject.subject regex_match "^\\[?(EXT|EXTERNAL)\\]?[: ]\\s*(RE|FWD?|FW|AW|TR|ODG|答复):.*"
        subject.subject starts_with "AW:"
        subject.subject starts_with "FWD:"
        subject.subject starts_with "ODG:"
        subject.subject starts_with "R:"
        subject.subject starts_with "RE:"
        subject.subject starts_with "TR:"
        subject.subject starts_with "答复:"
  or
    not
      headers.auth_summary.dmarc.pass eq "true"
    not
      sender.email.domain.root_domain eq "sharepointonline.com"
  attachments length_compare "15"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.html.rawregex_match
  • <table[^>]*>.*?<img[^>]+src=[\"']cid:[^\"']+[\"'][^>]*>.*?\.(pdf|doc(x)|xls(x)?).*?<font[^>]*>\s*\d{1,4}\.\d{1,2}\s*k[bB]
field:"body.html.raw" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.in_reply_tois_not_null(no value, null check)excludes:headers.in_reply_to
headers.referenceslength_compare0excludes:headers.references field:"headers.references" value:"0"
subject.subjectregex_match([[^]]+]\s?){0,3}(re|fwd?)\s?:excludes:subject.subject field:"subject.subject" value:"([[^]]+]\s?){0,3}(re|fwd?)\s?:"
subject.subjectregex_match^[?(EXT|EXTERNAL)]?[: ]\s*(RE|FWD?|FW|AW|TR|ODG|答复):.*excludes:subject.subject field:"subject.subject" value:"^[?(EXT|EXTERNAL)]?[: ]\s*(RE|FWD?|FW|AW|TR|ODG|答复):.*"
subject.subjectstarts_withAW:excludes:subject.subject field:"subject.subject" value:"AW:"
subject.subjectstarts_withFWD:excludes:subject.subject field:"subject.subject" value:"FWD:"
subject.subjectstarts_withODG:excludes:subject.subject field:"subject.subject" value:"ODG:"
subject.subjectstarts_withR:excludes:subject.subject field:"subject.subject" value:"R:"
subject.subjectstarts_withRE:excludes:subject.subject field:"subject.subject" value:"RE:"
subject.subjectstarts_withTR:excludes:subject.subject field:"subject.subject" value:"TR:"
subject.subjectstarts_with答复:excludes:subject.subject field:"subject.subject" value:"答复:"

Attachment: Fake lawyer & sports agent identities

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

Detects messages containing attachments or content that reference known fake identities used in FC Barcelona scams, including fake lawyer Michael Gerardus Hermanus Demon and sports agents with the surname Giuffrida. The rule examines EXIF metadata, OCR text from attachments, and message body content for these specific identity markers.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesImpersonation: VIP, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments[0]
  • type

Rule Body

type.inbound
and length(attachments) == 1
and beta.parse_exif(attachments[0]).creator == "Gabriele Giuffrida"

Detection Logic

Scope: inbound message.

Detects messages containing attachments or content that reference known fake identities used in FC Barcelona scams, including fake lawyer Michael Gerardus Hermanus Demon and sports agents with the surname Giuffrida. The rule examines EXIF metadata, OCR text from attachments, and message body content for these specific identity markers.

  1. inbound message
  2. length(attachments) == 1
  3. beta.parse_exif(attachments[0]).creator == "Gabriele Giuffrida"

Inspects: attachments[0], type.inbound. Sensors: beta.parse_exif.

Stages and Predicates

Stage 1: mql_rule

and
  attachments length_compare "1"
  beta.parse_exif func_call "beta.parse_exif(attachments[0]).creator == \"Gabriele Giuffrida\""
  type.inbound eq "true"

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"

Attachment: Fake PDF Invoices Yara

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

These yara signatures match fake invoice PDFs with specific artifiacts including images and link locations.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name in (
                  "fake_invoice_pdf_structure_01",
                  "fake_invoice_pdf_images_01",
                )
            )
        )
)

Detection Logic

Scope: inbound message.

These yara signatures match fake invoice PDFs with specific artifiacts including images and link locations.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ( "fake_invoice_pdf_structure_01", "fake_invoice_pdf_images_01", ) ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberfake_invoice_pdf_structure_01
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberfake_invoice_pdf_images_01

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name in (\n                  \"fake_invoice_pdf_structure_01\",\n                  \"fake_invoice_pdf_images_01\",\n                )\n            )\n        )\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"

Attachment: Fake research internship offer

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

Detects inbound, non-reply/forward emails referencing research, internship, or fellowship opportunities with weekly stipend language, accompanied by a PDF attachment whose OCR-extracted text confirms a research/internship role, cites a weekly dollar stipend, and directs recipients to respond via personal free-mail addresses, text message, or an alternate email—hallmarks of fraudulent job/internship scams designed to harvest personal information or payment.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Spam
Tactics and techniquesPDF, Social engineering, Out of band pivot, Free email provider

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • subject
  • type

Rule Body

type.inbound
and not (subject.is_reply or subject.is_forward)
and any([subject.base, body.current_thread.text],
        strings.icontains(.,
                          'research',
                          'intern',
                          'fellowship',
                          'recruit',
                          'placement',
                          'opening',
                          'opportunit',
                          'stipend',
                          'hiring',
                          'per week',
                          'weekly'
        )
)
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            regex.icontains(.scan.ocr.raw,
                            'research (?:intern|assistant|associate|support|role|position|study|fellow|participant)',
                            '\binternship\b'
            )
            and regex.icontains(.scan.ocr.raw,
                                '\$\s?\d{2,4}\s*(?:/|per)\s*week',
                                '\$\s?\d{2,4}\s+weekly'
            )
            and regex.icontains(.scan.ocr.raw,
                                '@(?:g[a-z]{0,2}mail|hotmail|outlook|yahoo|aol|icloud|proton(?:mail)?|gmx|zoho|live|msn)\.',
                                'email (?:the )?(?:supervising |fellowship )?(?:professor|mentor)',
                                '(?:by|via|through) text',
                                'send (?:a |an )?text',
                                'text (?:you|me|us|back|the professor|the mentor)',
                                'reach out[^\n]{0,20}text',
                                'alternate email'
            )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound, non-reply/forward emails referencing research, internship, or fellowship opportunities with weekly stipend language, accompanied by a PDF attachment whose OCR-extracted text confirms a research/internship role, cites a weekly dollar stipend, and directs recipients to respond via personal free-mail addresses, text message, or an alternate email—hallmarks of fraudulent job/internship scams designed to harvest personal information or payment.

  1. inbound message
  2. none of:
    • subject.is_reply
    • subject.is_forward
  3. any([subject.base, body.current_thread.text], strings.icontains(., 'research', 'intern', 'fellowship', 'recruit', 'placement', 'opening', 'opportunit', 'stipend', 'hiring', 'per week', 'weekly' ) )
  4. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), regex.icontains(.scan.ocr.raw, 'research (?:intern|assistant|associate|support|role|position|study|fellow|participant)', '\binternship\b' ) and regex.icontains(.scan.ocr.raw, '\$\s?\d{2,4}\s*(?:/|per)\s*week', '\$\s?\d{2,4}\s+weekly' ) and regex.icontains(.scan.ocr.raw, '@(?:g[a-z]{0,2}mail|hotmail|outlook|yahoo|aol|icloud|proton(?:mail)?|gmx|zoho|live|msn)\.', 'email (?:the )?(?:supervising |fellowship )?(?:professor|mentor)', '(?:by|via|through) text', 'send (?:a |an )?text', 'text (?:you|me|us|back|the professor|the mentor)', 'reach out[^\n]{0,20}text', 'alternate email' ) ) )

Inspects: attachments[].file_type, body.current_thread.text, subject.base, subject.is_forward, subject.is_reply, type.inbound. Sensors: file.explode, regex.icontains, strings.icontains.

Indicators Matched (23)

FieldMatchValue
strings.icontainssubstringresearch
strings.icontainssubstringintern
strings.icontainssubstringfellowship
strings.icontainssubstringrecruit
strings.icontainssubstringplacement
strings.icontainssubstringopening
strings.icontainssubstringopportunit
strings.icontainssubstringstipend
strings.icontainssubstringhiring
strings.icontainssubstringper week
strings.icontainssubstringweekly
attachments[].file_typeequalspdf
11 more
regex.icontainsregexresearch (?:intern|assistant|associate|support|role|position|study|fellow|participant)
regex.icontainsregex\binternship\b
regex.icontainsregex\$\s?\d{2,4}\s*(?:/|per)\s*week
regex.icontainsregex\$\s?\d{2,4}\s+weekly
regex.icontainsregex@(?:g[a-z]{0,2}mail|hotmail|outlook|yahoo|aol|icloud|proton(?:mail)?|gmx|zoho|live|msn)\.
regex.icontainsregexemail (?:the )?(?:supervising |fellowship )?(?:professor|mentor)
regex.icontainsregex(?:by|via|through) text
regex.icontainsregexsend (?:a |an )?text
regex.icontainsregextext (?:you|me|us|back|the professor|the mentor)
regex.icontainsregexreach out[^\n]{0,20}text
regex.icontainsregexalternate email

Stages and Predicates

Stage 1: mql_rule

and
  not
    or
      subject.is_forward eq "true"
      subject.is_reply eq "true"
  type.inbound eq "true"
   macro "any([subject.base, body.current_thread.text],\n        strings.icontains(.,\n                          'research',\n                          'intern',\n                          'fellowship',\n                          'recruit',\n                          'placement',\n                          'opening',\n                          'opportunit',\n                          'stipend',\n                          'hiring',\n                          'per week',\n                          'weekly'\n        )\n)"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            regex.icontains(.scan.ocr.raw,\n                            'research (?:intern|assistant|associate|support|role|position|study|fellow|participant)',\n                            '\\binternship\\b'\n            )\n            and regex.icontains(.scan.ocr.raw,\n                                '\\$\\s?\\d{2,4}\\s*(?:/|per)\\s*week',\n                                '\\$\\s?\\d{2,4}\\s+weekly'\n            )\n            and regex.icontains(.scan.ocr.raw,\n                                '@(?:g[a-z]{0,2}mail|hotmail|outlook|yahoo|aol|icloud|proton(?:mail)?|gmx|zoho|live|msn)\\.',\n                                'email (?:the )?(?:supervising |fellowship )?(?:professor|mentor)',\n                                '(?:by|via|through) text',\n                                'send (?:a |an )?text',\n                                'text (?:you|me|us|back|the professor|the mentor)',\n                                'reach out[^\\n]{0,20}text',\n                                'alternate email'\n            )\n        )\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"

Exclusions

The rule actively suppresses these predicates.

Attachment: Fake scan-to-email

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

Message and attachment resemble an email from a scan-to-email service or device with credential theft language.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree file host, Image as content, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • sender.email
  • type

Rule Body

type.inbound
and (
  length(body.current_thread.text) < 1500
  // body length without disclaimer is shorter than 1500 characters
  or (
    any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,
                   .name == "disclaimer"
            ),
            .text
        ),
        (length(body.current_thread.text) - length(.)) < 1500
    )
  )
)
and (
  3 of (
    strings.icontains(body.current_thread.text, "Number of Images:"),
    strings.icontains(body.current_thread.text, "Attachment File Type:"),
    strings.icontains(body.current_thread.text, "Device Model:"),
    strings.icontains(body.current_thread.text, "Device Name:"),
    strings.icontains(body.current_thread.text, "Resolution:"),
    strings.icontains(body.current_thread.text, "File Format:"),
    strings.icontains(body.current_thread.text, "Device Location:")
  )
  or (
    3 of (
      strings.ilike(body.current_thread.text, "*scan date*"),
      strings.ilike(body.current_thread.text, "*was sent from*"),
      strings.ilike(body.current_thread.text, "*of pages*"),
      strings.ilike(body.current_thread.text, "*scanned file*"),
    )
    or any(file.explode(file.message_screenshot()),
           3 of (
             strings.ilike(body.current_thread.text, "*scan date*"),
             strings.ilike(body.current_thread.text, "*was sent from*"),
             strings.ilike(body.current_thread.text, "*of pages*"),
             strings.ilike(body.current_thread.text, "*scanned file*"),
             strings.icontains(body.current_thread.text, "Number of Images:"),
             strings.icontains(body.current_thread.text,
                               "Attachment File Type:"
             ),
             strings.icontains(body.current_thread.text, "Device Name:"),
             strings.icontains(body.current_thread.text, "Device Location:"),
             strings.icontains(body.current_thread.text, "Device Model:")
           )
    )
  )
)
and (
  (
    length(filter(attachments, .file_type in ("pdf"))) == 1
    and any(attachments,
            .file_type == "pdf"
            and (
              any(file.explode(.),
                  (
                    strings.ilike(.scan.ocr.raw,
                                  "*scan date*",
                                  "*was sent from*",
                                  "*of pages*",
                                  "*verif*document*",
                                  "*scanned file*"
                    )
                    or any(ml.nlu_classifier(.scan.ocr.raw).intents,
                           .name == "cred_theft"
                    )
                    or any(ml.logo_detect(..).brands,
                           .name in ("DocuSign", "Microsoft")
                    )
                  )
                  and length(.scan.url.urls) == 1
              )
              // encrypted pdf
              or any(file.explode(.),
                     any(.scan.exiftool.fields, .key == "Encryption")
                     or (
                       .scan.entropy.entropy > 7
                       and any(.scan.strings.strings,
                               strings.icontains(., "/Encrypt")
                       )
                     )
              )
            )
    )
  )
  or length(filter(attachments, .file_type in ("doc", "docx"))) == 1
)
and sender.email.domain.domain not in~ $org_domains
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Message and attachment resemble an email from a scan-to-email service or device with credential theft language.

  1. inbound message
  2. any of:
    • length(body.current_thread.text) < 1500
    • ( any(map(filter(ml.nlu_classifier(body.current_thread.text).entities, .name == "disclaimer" ), .text ), (length(body.current_thread.text) - length(.)) < 1500 ) )
  3. any of:
    • at least 3 of 7: body.current_thread.text contains any of 7 patterns
      • Number of Images:
      • Attachment File Type:
      • Device Model:
      • Device Name:
      • Resolution:
      • File Format:
      • Device Location:
    • any of:
      • at least 3 of 4: body.current_thread.text matches any of 4 patterns
        • *scan date*
        • *was sent from*
        • *of pages*
        • *scanned file*
      • any(file.explode(file.message_screenshot()), 3 of ( strings.ilike(body.current_thread.text, "*scan date*"), strings.ilike(body.current_thread.text, "*was sent from*"), strings.ilike(body.current_thread.text, "*of pages*"), strings.ilike(body.current_thread.text, "*scanned file*"), strings.icontains(body.current_thread.text, "Number of Images:"), strings.icontains(body.current_thread.text, "Attachment File Type:" ), strings.icontains(body.current_thread.text, "Device Name:"), strings.icontains(body.current_thread.text, "Device Location:"), strings.icontains(body.current_thread.text, "Device Model:") ) )
  4. any of:
    • all of:
      • length(filter(attachments, .file_type in ("pdf"))) == 1
      • any of attachments where all hold:
        • .file_type is 'pdf'
        • any of:
          • any(file.explode(.), ( strings.ilike(.scan.ocr.raw, "*scan date*", "*was sent from*", "*of pages*", "*verif*document*", "*scanned file*" ) or any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" ) or any(ml.logo_detect(..).brands, .name in ("DocuSign", "Microsoft") ) ) and length(.scan.url.urls) == 1 )
          • any(file.explode(.), any(.scan.exiftool.fields, .key == "Encryption") or ( .scan.entropy.entropy > 7 and any(.scan.strings.strings, strings.icontains(., "/Encrypt") ) ) )
    • length(filter(attachments, .file_type in ("doc", "docx"))) == 1
  5. sender.email.domain.domain not in $org_domains
  6. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  7. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].file_type, body.current_thread.text, sender.email.domain.domain, type.inbound. Sensors: file.explode, file.message_screenshot, ml.logo_detect, ml.nlu_classifier, profile.by_sender, strings.icontains, strings.ilike. Reference lists: $org_domains.

Indicators Matched (22)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsdisclaimer
strings.icontainssubstringNumber of Images:
strings.icontainssubstringAttachment File Type:
strings.icontainssubstringDevice Model:
strings.icontainssubstringDevice Name:
strings.icontainssubstringResolution:
strings.icontainssubstringFile Format:
strings.icontainssubstringDevice Location:
strings.ilikesubstring*scan date*
strings.ilikesubstring*was sent from*
strings.ilikesubstring*of pages*
strings.ilikesubstring*scanned file*
10 more
attachments[].file_typememberpdf
attachments[].file_typeequalspdf
strings.ilikesubstring*verif*document*
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.logo_detect(attachments[]).brands[].namememberDocuSign
ml.logo_detect(attachments[]).brands[].namememberMicrosoft
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsEncryption
strings.icontainssubstring/Encrypt
attachments[].file_typememberdoc
attachments[].file_typememberdocx

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      any(attachments)
        and
          or
             macro "any(file.explode(.),\n                     any(.scan.exiftool.fields, .key == \"Encryption\")\n                     or (\n                       .scan.entropy.entropy > 7\n                       and any(.scan.strings.strings,\n                               strings.icontains(., \"/Encrypt\")\n                       )\n                     )\n              )"
             macro "any(file.explode(.),\n                  (\n                    strings.ilike(.scan.ocr.raw,\n                                  \"*scan date*\",\n                                  \"*was sent from*\",\n                                  \"*of pages*\",\n                                  \"*verif*document*\",\n                                  \"*scanned file*\"\n                    )\n                    or any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                           .name == \"cred_theft\"\n                    )\n                    or any(ml.logo_detect(..).brands,\n                           .name in (\"DocuSign\", \"Microsoft\")\n                    )\n                  )\n                  and length(.scan.url.urls) == 1\n              )"
          attachments.file_type eq "pdf"
      length func_call "length(filter(attachments, .file_type in (\"pdf\"))) == 1"
    length func_call "length(filter(attachments, .file_type in (\"doc\", \"docx\"))) == 1"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Model:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Name:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "File Format:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Device Name:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "File Format:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "File Format:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Attachment File Type:"
      body.current_thread.text contains "Number of Images:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Device Name:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "File Format:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "File Format:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Location:"
      body.current_thread.text contains "Number of Images:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "File Format:"
    and
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Model:"
      body.current_thread.text contains "Number of Images:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Number of Images:"
    and
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "Device Name:"
      body.current_thread.text contains "Number of Images:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text contains "File Format:"
      body.current_thread.text contains "Number of Images:"
      body.current_thread.text contains "Resolution:"
    and
      body.current_thread.text match "of pages"
      body.current_thread.text match "scan date"
      body.current_thread.text match "scanned file"
    and
      body.current_thread.text match "of pages"
      body.current_thread.text match "scan date"
      body.current_thread.text match "was sent from"
    and
      body.current_thread.text match "of pages"
      body.current_thread.text match "scanned file"
      body.current_thread.text match "was sent from"
    and
      body.current_thread.text match "scan date"
      body.current_thread.text match "scanned file"
      body.current_thread.text match "was sent from"
     macro "any(file.explode(file.message_screenshot()),\n           3 of (\n             strings.ilike(body.current_thread.text, \"*scan date*\"),\n             strings.ilike(body.current_thread.text, \"*was sent from*\"),\n             strings.ilike(body.current_thread.text, \"*of pages*\"),\n             strings.ilike(body.current_thread.text, \"*scanned file*\"),\n             strings.icontains(body.current_thread.text, \"Number of Images:\"),\n             strings.icontains(body.current_thread.text,\n                               \"Attachment File Type:\"\n             ),\n             strings.icontains(body.current_thread.text, \"Device Name:\"),\n             strings.icontains(body.current_thread.text, \"Device Location:\"),\n             strings.icontains(body.current_thread.text, \"Device Model:\")\n           )\n    )"
  or
    body.current_thread.text length_compare "1500"
     macro "(\n    any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,\n                   .name == \"disclaimer\"\n            ),\n            .text\n        ),\n        (length(body.current_thread.text) - length(.)) < 1500\n    )\n  )"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  sender.email.domain.domain macro "sender.email.domain.domain not in org_domains"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • Attachment File Type:
  • Device Location:
  • Device Model:
  • Device Name:
  • File Format:
  • Number of Images:
  • Resolution:
field:"body.current_thread.text" kind:contains
body.current_thread.textwildcard
  • *of pages*
  • *scan date* corpus 2 (mql 2)
  • *scanned file*
  • *was sent from* corpus 2 (mql 2)
field:"body.current_thread.text" kind:wildcard
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: Fake secure message and suspicious indicators

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

Body contains language resembling credential theft, and an attached "secure message" from an untrusted sender.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImage as content, Impersonation: Brand, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • body.current_thread
  • body.links
  • headers
  • headers.auth_summary
  • headers.domains
  • headers.hops
  • sender.email
  • type

Rule Body

type.inbound
and any(ml.nlu_classifier(body.current_thread.text).intents,
        .name == "cred_theft" and .confidence == "high"
)

// ----- other suspicious signals here -----
and any(attachments,
        any(file.explode(.),
            any(.scan.strings.strings, strings.icontains(., "secure message"))
            and (
              any(.scan.url.urls, .domain.tld in $suspicious_tlds)
              or any(.scan.url.urls,
                     any(.rewrite.encoders,
                         strings.icontains(., "open_redirect")
                     )
              )
            )
            and (
              any(.scan.url.urls,
                  .domain.root_domain != sender.email.domain.root_domain
              )
              or not sender.email.domain.valid
            )
        )
)

// negate legitimate message senders
and (
  (
    sender.email.domain.root_domain not in ("protectedtrust.com")
    or not sender.email.domain.valid
  )
  and any(headers.hops,
          .index == 0
          and not any(.fields,
                      strings.contains(.value,
                                       'multipart/mixed; boundary="PROOFPOINT_BOUNDARY_1"'
                      )
          )
  )
  and not (
    any(headers.hops, any(.fields, .name == 'X-ZixNet'))
    and any(headers.domains,
            .root_domain in ("zixport.com", "zixcorp.com", "zixmail.net")
    )
  )
  and not all(body.links,
              .href_url.domain.root_domain in ("mimecast.com", "cisco.com")
  )
)
and (
  (
    profile.by_sender().prevalence in ("new", "outlier")
    and not profile.by_sender().solicited
  )
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Body contains language resembling credential theft, and an attached "secure message" from an untrusted sender.

  1. inbound message
  2. any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence == "high" )
  3. any of attachments where:
    • any(file.explode(.), any(.scan.strings.strings, strings.icontains(., "secure message")) and ( any(.scan.url.urls, .domain.tld in $suspicious_tlds) or any(.scan.url.urls, any(.rewrite.encoders, strings.icontains(., "open_redirect") ) ) ) and ( any(.scan.url.urls, .domain.root_domain != sender.email.domain.root_domain ) or not sender.email.domain.valid ) )
  4. all of:
    • any of:
      • sender.email.domain.root_domain not in ('protectedtrust.com')
      • not:
        • sender.email.domain.valid
    • any of headers.hops where all hold:
      • .index is 0
      • not:
        • any of .fields where:
          • .value contains 'multipart/mixed; boundary="PROOFPOINT_BOUNDARY_1"'
    • not:
      • all of:
        • any of headers.hops where:
          • any of .fields where:
            • .name is 'X-ZixNet'
        • any of headers.domains where:
          • .root_domain in ('zixport.com', 'zixcorp.com', 'zixmail.net')
    • not:
      • all of body.links where:
        • .href_url.domain.root_domain in ('mimecast.com', 'cisco.com')
  5. any of:
    • all of:
      • profile.by_sender().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  6. not:
    • profile.by_sender().any_messages_benign
  7. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: body.current_thread.text, body.links, body.links[].href_url.domain.root_domain, headers.auth_summary.dmarc.pass, headers.domains, headers.domains[].root_domain, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, headers.hops[].fields[].value, headers.hops[].index, sender.email.domain.root_domain, sender.email.domain.valid, type.inbound. Sensors: file.explode, ml.nlu_classifier, profile.by_sender, strings.contains, strings.icontains. Reference lists: $high_trust_sender_root_domains, $suspicious_tlds.

Indicators Matched (4)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidenceequalshigh
strings.icontainssubstringsecure message
strings.icontainssubstringopen_redirect

Stages and Predicates

Stage 1: mql_rule

and
  not
    and
      any(headers.hops)
        any(headers.hops.fields)
          headers.hops.fields.name eq "X-ZixNet"
      any(headers.domains)
        headers.domains.root_domain in ["zixcorp.com", "zixmail.net", "zixport.com"]
  any(headers.hops)
    and
      not
        any(headers.hops.fields)
          headers.hops.fields.value contains "multipart/mixed; boundary=\"PROOFPOINT_BOUNDARY_1\""
      headers.hops.index eq "0"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender func_call "profile.by_sender().solicited"
      profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
  or
    not
      sender.email.domain.root_domain eq "protectedtrust.com"
    not
      sender.email.domain.valid eq "true"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  not
     macro "all(body.links,\n              .href_url.domain.root_domain in (\"mimecast.com\", \"cisco.com\")\n  )"
  any(attachments)
     macro "any(file.explode(.),\n            any(.scan.strings.strings, strings.icontains(., \"secure message\"))\n            and (\n              any(.scan.url.urls, .domain.tld in $suspicious_tlds)\n              or any(.scan.url.urls,\n                     any(.rewrite.encoders,\n                         strings.icontains(., \"open_redirect\")\n                     )\n              )\n            )\n            and (\n              any(.scan.url.urls,\n                  .domain.root_domain != sender.email.domain.root_domain\n              )\n              or not sender.email.domain.valid\n            )\n        )"
  type.inbound eq "true"
   macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n        .name == \"cred_theft\" and .confidence == \"high\"\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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops
headers.domainsarray_any(no value, null check)excludes:headers.domains

Attachment: Fake Slack installer

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

HTML attachment contains a Slack logo, request language, and a link to an executable. Observed in the wild.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Impersonation: Brand, Scripting, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and (
  any(attachments,
      (
        .file_extension in~ ("html", "htm", "shtml", "dhtml")
        or .file_type == "html"
        or .content_type == "text/html"
      )
      and any(ml.logo_detect(file.html_screenshot(.)).brands,
              .name == "Slack" and .confidence in ("medium", "high")
      )
      and any(ml.nlu_classifier(file.parse_html(.).display_text).entities,
              .name == "request" and .text =~ "download"
      )
      and any(file.explode(.),
              any(.scan.url.urls,
                  strings.iends_with(.path, ".exe")
                  and .domain.root_domain not in $org_domains
              )
      )
  )
)

Detection Logic

Scope: inbound message.

HTML attachment contains a Slack logo, request language, and a link to an executable. Observed in the wild.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_type is 'html'
      • .content_type is 'text/html'
    • any(ml.logo_detect(file.html_screenshot(.)).brands, .name == "Slack" and .confidence in ("medium", "high") )
    • any(ml.nlu_classifier(file.parse_html(.).display_text).entities, .name == "request" and .text =~ "download" )
    • any(file.explode(.), any(.scan.url.urls, strings.iends_with(.path, ".exe") and .domain.root_domain not in $org_domains ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, file.html_screenshot, file.parse_html, ml.logo_detect, ml.nlu_classifier, strings.iends_with. Reference lists: $org_domains.

Indicators Matched (12)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
ml.logo_detect(file.html_screenshot(attachments[])).brands[].nameequalsSlack
ml.logo_detect(file.html_screenshot(attachments[])).brands[].confidencemembermedium
ml.logo_detect(file.html_screenshot(attachments[])).brands[].confidencememberhigh
ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].nameequalsrequest
ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].textequalsdownload
strings.iends_withsuffix.exe

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n              any(.scan.url.urls,\n                  strings.iends_with(.path, \".exe\")\n                  and .domain.root_domain not in $org_domains\n              )\n      )"
       macro "any(ml.logo_detect(file.html_screenshot(.)).brands,\n              .name == \"Slack\" and .confidence in (\"medium\", \"high\")\n      )"
       macro "any(ml.nlu_classifier(file.parse_html(.).display_text).entities,\n              .name == \"request\" and .text =~ \"download\"\n      )"
  type.inbound eq "true"

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"

Attachment: Fake voicemail via PDF

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

Identifies inbound messages containing a single-page PDF attachment related to voicemail or missed call notifications that includes either a URL or QR code.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, QR code, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • sender.email
  • subject
  • type

Rule Body

type.inbound
// a single PDF attachment
and length(attachments) == 1
// the subject doesn't contain fax, which is currently a common match for the topic
and not strings.icontains(subject.base, 'fax')
and (
  length(body.current_thread.text) == 0
  or (
    ml.nlu_classifier(body.current_thread.text).language == "english"
    and (
      any(ml.nlu_classifier(body.current_thread.text).topics,
          .confidence == "high"
          and .name == "Voicemail Call and Missed Call Notifications"
      )
      or any(ml.nlu_classifier(body.current_thread.text).intents,
             .confidence == "high" and .name == "bec"
      )
    )
  )
)
// the Topic analysis of the PDF is Voicemail
and any(attachments,
        .file_extension == "pdf"
        // the NLU detected language is english
        and ml.nlu_classifier(beta.ocr(.).text).language == "english"
        and length(beta.ocr(.).text) > 95
        and any(ml.nlu_classifier(beta.ocr(.).text).topics,
                .confidence == "high"
                and .name == "Voicemail Call and Missed Call Notifications"
        )
        and beta.ocr(.).success
        // contains a link or QR code
        and any(file.explode(.),
                0 < length(.scan.pdf.urls) <= 2 or .scan.qr.url.url is not null
        )
        // there is only a single page
        and any(file.explode(.), .depth == 0 and .scan.exiftool.page_count == 1)
)
and not (
  sender.email.domain.root_domain == "zendesk.com"
  and coalesce(headers.auth_summary.dmarc.pass, false)
)

Detection Logic

Scope: inbound message.

Identifies inbound messages containing a single-page PDF attachment related to voicemail or missed call notifications that includes either a URL or QR code.

  1. inbound message
  2. length(attachments) == 1
  3. not:
    • subject.base contains 'fax'
  4. any of:
    • length(body.current_thread.text) == 0
    • all of:
      • ml.nlu_classifier(body.current_thread.text).language == "english"
      • any of:
        • any(ml.nlu_classifier(body.current_thread.text).topics, .confidence == "high" and .name == "Voicemail Call and Missed Call Notifications" )
        • any(ml.nlu_classifier(body.current_thread.text).intents, .confidence == "high" and .name == "bec" )
  5. any of attachments where all hold:
    • .file_extension is 'pdf'
    • ml.nlu_classifier(beta.ocr(.).text).language == "english"
    • length(beta.ocr(.).text) > 95
    • any(ml.nlu_classifier(beta.ocr(.).text).topics, .confidence == "high" and .name == "Voicemail Call and Missed Call Notifications" )
    • beta.ocr(.).success
    • any(file.explode(.), 0 < length(.scan.pdf.urls) <= 2 or .scan.qr.url.url is not null )
    • any(file.explode(.), .depth == 0 and .scan.exiftool.page_count == 1)
  6. not:
    • all of:
      • sender.email.domain.root_domain is 'zendesk.com'
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_extension, body.current_thread.text, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, subject.base, type.inbound. Sensors: beta.ocr, file.explode, ml.nlu_classifier, strings.icontains.

Indicators Matched (7)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).topics[].confidenceequalshigh
ml.nlu_classifier(body.current_thread.text).topics[].nameequalsVoicemail Call and Missed Call Notifications
ml.nlu_classifier(body.current_thread.text).intents[].confidenceequalshigh
ml.nlu_classifier(body.current_thread.text).intents[].nameequalsbec
attachments[].file_extensionequalspdf
ml.nlu_classifier(beta.ocr(attachments[]).text).topics[].confidenceequalshigh
ml.nlu_classifier(beta.ocr(attachments[]).text).topics[].nameequalsVoicemail Call and Missed Call Notifications

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      or
         macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n             .confidence == \"high\" and .name == \"bec\"\n      )"
         macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n          .confidence == \"high\"\n          and .name == \"Voicemail Call and Missed Call Notifications\"\n      )"
      ml.nlu_classifier func_call "ml.nlu_classifier(body.current_thread.text).language == \"english\""
    body.current_thread.text length_compare "0"
  any(attachments)
    and
      attachments.file_extension eq "pdf"
      beta.ocr func_call "beta.ocr(.).success"
      length func_call "length(beta.ocr(.).text) > 95"
      ml.nlu_classifier func_call "ml.nlu_classifier(beta.ocr(.).text).language == \"english\""
       macro "any(file.explode(.), .depth == 0 and .scan.exiftool.page_count == 1)"
       macro "any(file.explode(.),\n                0 < length(.scan.pdf.urls) <= 2 or .scan.qr.url.url is not null\n        )"
       macro "any(ml.nlu_classifier(beta.ocr(.).text).topics,\n                .confidence == \"high\"\n                and .name == \"Voicemail Call and Missed Call Notifications\"\n        )"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain eq "zendesk.com"
  not
    subject.base contains "fax"
  attachments length_compare "1"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass
sender.email.domain.root_domaineqzendesk.comexcludes:sender.email.domain.root_domain field:"sender.email.domain.root_domain" value:"zendesk.com"
subject.basecontainsfaxexcludes:subject.base field:"subject.base" value:"fax"

Attachment: Fake Zoom installer

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

HTML attachment contains a Zoom logo, request language, and a link to an executable. Observed in the wild.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Impersonation: Brand, Scripting, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_type == "html"
          or .content_type == "text/html"
        )
        and any(ml.logo_detect(file.html_screenshot(.)).brands,
                .name == "Zoom" and .confidence in ("medium", "high")
        )
        and any(ml.nlu_classifier(file.parse_html(.).display_text).entities,
                .name == "request" and .text =~ "download"
        )
        and any(file.explode(.),
                any(.scan.url.urls,
                    strings.iends_with(.path, ".exe")
                    and .domain.root_domain not in $org_domains
                )
        )
)

Detection Logic

Scope: inbound message.

HTML attachment contains a Zoom logo, request language, and a link to an executable. Observed in the wild.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_type is 'html'
      • .content_type is 'text/html'
    • any(ml.logo_detect(file.html_screenshot(.)).brands, .name == "Zoom" and .confidence in ("medium", "high") )
    • any(ml.nlu_classifier(file.parse_html(.).display_text).entities, .name == "request" and .text =~ "download" )
    • any(file.explode(.), any(.scan.url.urls, strings.iends_with(.path, ".exe") and .domain.root_domain not in $org_domains ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, file.html_screenshot, file.parse_html, ml.logo_detect, ml.nlu_classifier, strings.iends_with. Reference lists: $org_domains.

Indicators Matched (12)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
ml.logo_detect(file.html_screenshot(attachments[])).brands[].nameequalsZoom
ml.logo_detect(file.html_screenshot(attachments[])).brands[].confidencemembermedium
ml.logo_detect(file.html_screenshot(attachments[])).brands[].confidencememberhigh
ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].nameequalsrequest
ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].textequalsdownload
strings.iends_withsuffix.exe

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.url.urls,\n                    strings.iends_with(.path, \".exe\")\n                    and .domain.root_domain not in $org_domains\n                )\n        )"
       macro "any(ml.logo_detect(file.html_screenshot(.)).brands,\n                .name == \"Zoom\" and .confidence in (\"medium\", \"high\")\n        )"
       macro "any(ml.nlu_classifier(file.parse_html(.).display_text).entities,\n                .name == \"request\" and .text =~ \"download\"\n        )"
  type.inbound eq "true"

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"

Attachment: File execution via Javascript

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

Javascript contains identifiers or strings that may attempt to execute files.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type in $file_extensions_common_archives
        and any(file.explode(.),
                any(.scan.javascript.identifiers,
                    strings.ilike(., 'ActiveXObject', 'ShellExecute')
                )
                or (
                  length(.scan.javascript.strings) > 0
                  and all(.scan.javascript.strings,
                          strings.ilike(., 'Shell.Application', '*.exe')
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

Javascript contains identifiers or strings that may attempt to execute files.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type in $file_extensions_common_archives
    • any(file.explode(.), any(.scan.javascript.identifiers, strings.ilike(., 'ActiveXObject', 'ShellExecute') ) or ( length(.scan.javascript.strings) > 0 and all(.scan.javascript.strings, strings.ilike(., 'Shell.Application', '*.exe') ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (4)

FieldMatchValue
strings.ilikesubstringActiveXObject
strings.ilikesubstringShellExecute
strings.ilikesubstringShell.Application
strings.ilikesubstring*.exe

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type macro "attachments[].file_type in file_extensions_common_archives"
       macro "any(file.explode(.),\n                any(.scan.javascript.identifiers,\n                    strings.ilike(., 'ActiveXObject', 'ShellExecute')\n                )\n                or (\n                  length(.scan.javascript.strings) > 0\n                  and all(.scan.javascript.strings,\n                          strings.ilike(., 'Shell.Application', '*.exe')\n                  )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: Filename containing Unicode braille pattern blank character

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

Recursively identifies attachments that attempt to conceal their true file extension by using Braille Pattern Blank characters

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        regex.icontains(.file_name, '\x{2800}')
        or (
          .file_extension in~ $file_extensions_common_archives
          and any(file.explode(.), regex.icontains(.file_name, '\x{2800}'))
        )
)

Detection Logic

Scope: inbound message.

Recursively identifies attachments that attempt to conceal their true file extension by using Braille Pattern Blank characters

  1. inbound message
  2. any of attachments where any holds:
    • .file_name matches '\\x{2800}'
    • all of:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), regex.icontains(.file_name, '\x{2800}'))

Inspects: attachments[].file_extension, attachments[].file_name, type.inbound. Sensors: file.explode, regex.icontains. Reference lists: $file_extensions_common_archives.

Indicators Matched (1)

FieldMatchValue
regex.icontainsregex\x{2800}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.), regex.icontains(.file_name, '\\x{2800}'))"
      attachments.file_name regex_match "\\x{2800}"
  type.inbound eq "true"

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"

Attachment: Filename containing Unicode right-to-left override character

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

Recursively identifies attachments that attempt to conceal their true file extension by using right-to-left override characters

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        regex.icontains(.file_name, '\x{202E}', '\x{202D}')
        or (
          .file_extension in~ $file_extensions_common_archives
          and any(file.explode(.),
                  regex.icontains(.file_name, '\x{202E}', '\x{202D}')
          )
        )
)

Detection Logic

Scope: inbound message.

Recursively identifies attachments that attempt to conceal their true file extension by using right-to-left override characters

  1. inbound message
  2. any of attachments where any holds:
    • .file_name matches any of 2 patterns
      • \x{202E}
      • \x{202D}
    • all of:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), regex.icontains(.file_name, '\x{202E}', '\x{202D}') )

Inspects: attachments[].file_extension, attachments[].file_name, type.inbound. Sensors: file.explode, regex.icontains. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
regex.icontainsregex\x{202E}
regex.icontainsregex\x{202D}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.),\n                  regex.icontains(.file_name, '\\x{202E}', '\\x{202D}')\n          )"
      attachments.file_name regex_match "\\x{202D}"
      attachments.file_name regex_match "\\x{202E}"
  type.inbound eq "true"

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"

Attachment: Finance themed PDF with observed phishing template

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

Detects PDF attachments containing a specific rectangular coordinate pattern at position [249.75 560 407.25 599.75], which may indicate a templated or malicious document structure.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.strings.strings,
                strings.contains(., "/Rect [ 249.75 560 407.25 599.75 ]")
            )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing a specific rectangular coordinate pattern at position [249.75 560 407.25 599.75], which may indicate a templated or malicious document structure.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.strings.strings, strings.contains(., "/Rect [ 249.75 560 407.25 599.75 ]") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, strings.contains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
strings.containssubstring/Rect [ 249.75 560 407.25 599.75 ]

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.strings.strings,\n                strings.contains(., \"/Rect [ 249.75 560 407.25 599.75 ]\")\n            )\n        )\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"

Attachment: GZ archive with credential theft content

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

Detects inbound messages containing a .gz attachment that, when exploded, contains an email or HTML file. The rule then inspects the inner content for credential theft intent—either by parsing a well-formed embedded EML and running NLU classification on the message body, or, if the EML is malformed, by extracting HTML content, pulling href links, and running link analysis plus NLU classification on the resulting page text to identify high-confidence credential theft indicators.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "gz"),
        // archive contains an email or an html payload
        any(file.explode(.),
            any(.flavors.yara, . in ("email_file", "html_file"))
        )
        and (
          // well-formed inner eml, NLU on parsed body
          any(file.expand_archives(.).files,
              any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents,
                  .name == "cred_theft" and .confidence == "high"
              )
          )
          // malformed inner eml, byte-scan html + link_analysis
          or any(filter(file.explode(.), any(.flavors.yara, . == "html_file")),
                 any(html.xpath(strings.parse_html(.scan.strings.raw),
                                '//a/@href'
                     ).nodes,
                     any(ml.nlu_classifier(ml.link_analysis(strings.parse_url(.raw
                                                            )
                                           ).final_dom.inner_text
                         ).intents,
                         .name == "cred_theft" and .confidence == "high"
                     )
                 )
          )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing a .gz attachment that, when exploded, contains an email or HTML file. The rule then inspects the inner content for credential theft intent—either by parsing a well-formed embedded EML and running NLU classification on the message body, or, if the EML is malformed, by extracting HTML content, pulling href links, and running link analysis plus NLU classification on the resulting page text to identify high-confidence credential theft indicators.

  1. inbound message
  2. any(filter(attachments, .file_type == "gz"), // archive contains an email or an html payload any(file.explode(.), any(.flavors.yara, . in ("email_file", "html_file")) ) and ( // well-formed inner eml, NLU on parsed body any(file.expand_archives(.).files, any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents, .name == "cred_theft" and .confidence == "high" ) ) // malformed inner eml, byte-scan html + link_analysis or any(filter(file.explode(.), any(.flavors.yara, . == "html_file")), any(html.xpath(strings.parse_html(.scan.strings.raw), '//a/@href' ).nodes, any(ml.nlu_classifier(ml.link_analysis(strings.parse_url(.raw ) ).final_dom.inner_text ).intents, .name == "cred_theft" and .confidence == "high" ) ) ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.expand_archives, file.explode, file.parse_eml, html.xpath, ml.link_analysis, ml.nlu_classifier, strings.parse_html, strings.parse_url.

Indicators Matched (8)

FieldMatchValue
attachments[].file_typeequalsgz
file.explode(filter(attachments)[])[].flavors.yara[]memberemail_file
file.explode(filter(attachments)[])[].flavors.yara[]memberhtml_file
ml.nlu_classifier(file.parse_eml(file.expand_archives(filter(attachments)[]).files[]).body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(file.parse_eml(file.expand_archives(filter(attachments)[]).files[]).body.current_thread.text).intents[].confidenceequalshigh
file.explode(filter(attachments)[])[].flavors.yara[]equalshtml_file
ml.nlu_classifier(ml.link_analysis(strings.parse_url(html.xpath(strings.parse_html(filter(...)[].scan.strings.raw), '//a/@href').nodes[].raw)).final_dom.inner_text).intents[].nameequalscred_theft
ml.nlu_classifier(ml.link_analysis(strings.parse_url(html.xpath(strings.parse_html(filter(...)[].scan.strings.raw), '//a/@href').nodes[].raw)).final_dom.inner_text).intents[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"gz\"),\n        // archive contains an email or an html payload\n        any(file.explode(.),\n            any(.flavors.yara, . in (\"email_file\", \"html_file\"))\n        )\n        and (\n          // well-formed inner eml, NLU on parsed body\n          any(file.expand_archives(.).files,\n              any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents,\n                  .name == \"cred_theft\" and .confidence == \"high\"\n              )\n          )\n          // malformed inner eml, byte-scan html + link_analysis\n          or any(filter(file.explode(.), any(.flavors.yara, . == \"html_file\")),\n                 any(html.xpath(strings.parse_html(.scan.strings.raw),\n                                '//a/@href'\n                     ).nodes,\n                     any(ml.nlu_classifier(ml.link_analysis(strings.parse_url(.raw\n                                                            )\n                                           ).final_dom.inner_text\n                         ).intents,\n                         .name == \"cred_theft\" and .confidence == \"high\"\n                     )\n                 )\n          )\n        )\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"

Attachment: Gzip-archived with nested HTML file containing image and button link

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

Flags messages containing a gzip attachment that unpacks to an HTML file (identified via YARA), or messages whose body contains a base64-encoded image alongside an anchor tag styled as a rounded button, where the link's underlying domain resolves to a valid address. This pattern is commonly used to disguise phishing content and evade detection by embedding the malicious link within an image-styled button or compressed HTML payload.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesHTML smuggling, Image as content, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "gz"),
        any(file.explode(.),
            any(.flavors.yara, . == "html_file")
            and strings.icontains(.scan.strings.raw, "data:image")
            and any(html.xpath(strings.parse_html(.scan.strings.raw),
                               '//a[.//span[contains(@style,"border-radius")]]/@href'
                    ).nodes,
                    strings.parse_url(.raw).domain.valid
            )
        )
)

Detection Logic

Scope: inbound message.

Flags messages containing a gzip attachment that unpacks to an HTML file (identified via YARA), or messages whose body contains a base64-encoded image alongside an anchor tag styled as a rounded button, where the link's underlying domain resolves to a valid address. This pattern is commonly used to disguise phishing content and evade detection by embedding the malicious link within an image-styled button or compressed HTML payload.

  1. inbound message
  2. any(filter(attachments, .file_type == "gz"), any(file.explode(.), any(.flavors.yara, . == "html_file") and strings.icontains(.scan.strings.raw, "data:image") and any(html.xpath(strings.parse_html(.scan.strings.raw), '//a[.//span[contains(@style,"border-radius")]]/@href' ).nodes, strings.parse_url(.raw).domain.valid ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, html.xpath, strings.icontains, strings.parse_html, strings.parse_url.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsgz
file.explode(filter(attachments)[])[].flavors.yara[]equalshtml_file
strings.icontainssubstringdata:image

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"gz\"),\n        any(file.explode(.),\n            any(.flavors.yara, . == \"html_file\")\n            and strings.icontains(.scan.strings.raw, \"data:image\")\n            and any(html.xpath(strings.parse_html(.scan.strings.raw),\n                               '//a[.//span[contains(@style,\"border-radius\")]]/@href'\n                    ).nodes,\n                    strings.parse_url(.raw).domain.valid\n            )\n        )\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"

Attachment: HTML attachment with Javascript location

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
        )
        and .size <= 5000
        and any(file.explode(.),
                any(.scan.javascript.identifiers, . == "location")
                and length(.scan.javascript.identifiers) < 100
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • .size ≤ 5000
    • any(file.explode(.), any(.scan.javascript.identifiers, . == "location") and length(.scan.javascript.identifiers) < 100 )

Inspects: attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].scan.javascript.identifiers[]equalslocation

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
      attachments.size le "5000"
       macro "any(file.explode(.),\n                any(.scan.javascript.identifiers, . == \"location\")\n                and length(.scan.javascript.identifiers) < 100\n        )"
  type.inbound eq "true"

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"

Attachment: HTML attachment with login portal indicators

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

Recursively scans files and archives to detect indicators of login portals implemented in HTML files. This is a known credential theft technique used by threat actors.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesHTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
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(.),
                // suspicious strings found in javascript
                (
                  length(filter(.scan.javascript.strings,
                                strings.ilike(., "*password*", )
                         )
                  ) >= 2
                  and 2 of (
                    any(.scan.javascript.strings,
                        strings.ilike(., "*incorrect*")
                    ),
                    any(.scan.javascript.strings, strings.ilike(., "*invalid*")),
                    any(.scan.javascript.strings, strings.ilike(., "*login*")),
                    any(.scan.javascript.strings, regex.icontains(., "sign.in")),
                  )
                )
                or (
                  // suspicious strings found outside of javascript, but binexplode'd file still of HTML type
                  length(filter(.scan.strings.strings,
                                strings.ilike(., "*password*", )
                         )
                  ) >= 2
                  and 2 of (
                    any(.scan.strings.strings, strings.ilike(., "*incorrect*")),
                    any(.scan.strings.strings, strings.ilike(., "*invalid*")),
                    any(.scan.strings.strings, strings.ilike(., "*login*")),
                    any(.scan.strings.strings, strings.ilike(., "*<script>*")),
                    any(.scan.strings.strings, regex.icontains(., "sign.in")),
                    any(.scan.strings.strings,
                        regex.icontains(.,
                                        '<title>.[^<]+(Payment|Invoice|Statement|Login|Microsoft|Email|Excel)'
                        )
                    )
                  )
                )
                or 
                // Known phishing obfuscation
                2 of (
                  // Enter password
                  any(.scan.strings.strings,
                      strings.ilike(.,
                                    "*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*"
                      )
                  ),

                  // Forgotten my password
                  any(.scan.strings.strings,
                      strings.ilike(.,
                                    "*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*"
                      )
                  ),

                  // Sign in
                  any(.scan.strings.strings,
                      strings.ilike(.,
                                    "*&#83;&#105;&#103;&#110;&#32;&#105;&#110*"
                      )
                  )
                )
        )
)
and (
  (
    // exclude internal mailers where there is no SPF configured.
    // if the sender's root domain is an org domain, we
    // ensure there's an SPF pass
    // we use root_domain because it's typically subdomains that are misconfigured
    sender.email.domain.root_domain in $org_domains
    and headers.auth_summary.spf.pass
  )
  or sender.email.domain.root_domain not in $org_domains
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  (
    not profile.by_sender().solicited
    and profile.by_sender().prevalence in ("new", "outlier")
  )
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect indicators of login portals implemented in HTML files. This is a known credential theft technique used by threat actors.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), // suspicious strings found in javascript ( length(filter(.scan.javascript.strings, strings.ilike(., "*password*", ) ) ) >= 2 and 2 of ( any(.scan.javascript.strings, strings.ilike(., "*incorrect*") ), any(.scan.javascript.strings, strings.ilike(., "*invalid*")), any(.scan.javascript.strings, strings.ilike(., "*login*")), any(.scan.javascript.strings, regex.icontains(., "sign.in")), ) ) or ( // suspicious strings found outside of javascript, but binexplode'd file still of HTML type length(filter(.scan.strings.strings, strings.ilike(., "*password*", ) ) ) >= 2 and 2 of ( any(.scan.strings.strings, strings.ilike(., "*incorrect*")), any(.scan.strings.strings, strings.ilike(., "*invalid*")), any(.scan.strings.strings, strings.ilike(., "*login*")), any(.scan.strings.strings, strings.ilike(., "*<script>*")), any(.scan.strings.strings, regex.icontains(., "sign.in")), any(.scan.strings.strings, regex.icontains(., '<title>.[^<]+(Payment|Invoice|Statement|Login|Microsoft|Email|Excel)' ) ) ) ) or // Known phishing obfuscation 2 of ( // Enter password any(.scan.strings.strings, strings.ilike(., "*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*" ) ), // Forgotten my password any(.scan.strings.strings, strings.ilike(., "*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*" ) ), // Sign in any(.scan.strings.strings, strings.ilike(., "*&#83;&#105;&#103;&#110;&#32;&#105;&#110*" ) ) ) )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $org_domains
      • headers.auth_summary.spf.pass
    • sender.email.domain.root_domain not in $org_domains
  4. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  5. any of:
    • all of:
      • not:
        • profile.by_sender().solicited
      • profile.by_sender().prevalence in ("new", "outlier")
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, profile.by_sender, regex.icontains, strings.ilike. Reference lists: $file_extensions_common_archives, $high_trust_sender_root_domains, $org_domains.

Indicators Matched (15)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
strings.ilikesubstring*password*
strings.ilikesubstring*incorrect*
strings.ilikesubstring*invalid*
strings.ilikesubstring*login*
regex.icontainsregexsign.in
strings.ilikesubstring*<script>*
regex.icontainsregex<title>.[^<]+(Payment|Invoice|Statement|Login|Microsoft|Email|Excel)
3 more
strings.ilikesubstring*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*
strings.ilikesubstring*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*
strings.ilikesubstring*&#83;&#105;&#103;&#110;&#32;&#105;&#110*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                // suspicious strings found in javascript\n                (\n                  length(filter(.scan.javascript.strings,\n                                strings.ilike(., \"*password*\", )\n                         )\n                  ) >= 2\n                  and 2 of (\n                    any(.scan.javascript.strings,\n                        strings.ilike(., \"*incorrect*\")\n                    ),\n                    any(.scan.javascript.strings, strings.ilike(., \"*invalid*\")),\n                    any(.scan.javascript.strings, strings.ilike(., \"*login*\")),\n                    any(.scan.javascript.strings, regex.icontains(., \"sign.in\")),\n                  )\n                )\n                or (\n                  // suspicious strings found outside of javascript, but binexplode'd file still of HTML type\n                  length(filter(.scan.strings.strings,\n                                strings.ilike(., \"*password*\", )\n                         )\n                  ) >= 2\n                  and 2 of (\n                    any(.scan.strings.strings, strings.ilike(., \"*incorrect*\")),\n                    any(.scan.strings.strings, strings.ilike(., \"*invalid*\")),\n                    any(.scan.strings.strings, strings.ilike(., \"*login*\")),\n                    any(.scan.strings.strings, strings.ilike(., \"*<script>*\")),\n                    any(.scan.strings.strings, regex.icontains(., \"sign.in\")),\n                    any(.scan.strings.strings,\n                        regex.icontains(.,\n                                        '<title>.[^<]+(Payment|Invoice|Statement|Login|Microsoft|Email|Excel)'\n                        )\n                    )\n                  )\n                )\n                or \n                // Known phishing obfuscation\n                2 of (\n                  // Enter password\n                  any(.scan.strings.strings,\n                      strings.ilike(.,\n                                    \"*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*\"\n                      )\n                  ),\n\n                  // Forgotten my password\n                  any(.scan.strings.strings,\n                      strings.ilike(.,\n                                    \"*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*\"\n                      )\n                  ),\n\n                  // Sign in\n                  any(.scan.strings.strings,\n                      strings.ilike(.,\n                                    \"*&#83;&#105;&#103;&#110;&#32;&#105;&#110*\"\n                      )\n                  )\n                )\n        )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender func_call "profile.by_sender().solicited"
      profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
  or
    and
      headers.auth_summary.spf.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in org_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in org_domains"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
headers.auth_summary.spf.passeq
  • true transforms: boolean corpus 32 (mql 32)
field:"headers.auth_summary.spf.pass" kind:eq value:"true"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: HTML file contains exclusively Javascript

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

Attached HTML file does not contain any HTML other than a <script> block.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.scan.strings.strings) == 1
                and any(.scan.strings.strings,
                        regex.imatch(., '\s{0,}<script.*')
                )
                and any(.scan.strings.strings,
                        strings.ends_with(., "</script>")
                )
        )
)

Detection Logic

Scope: inbound message.

Attached HTML file does not contain any HTML other than a <script> block.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), length(.scan.strings.strings) == 1 and any(.scan.strings.strings, regex.imatch(., '\s{0,}<script.*') ) and any(.scan.strings.strings, strings.ends_with(., "</script>") ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.imatch, strings.ends_with. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.imatchregex\s{0,}<script.*
strings.ends_withsuffix</script>

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                length(.scan.strings.strings) == 1\n                and any(.scan.strings.strings,\n                        regex.imatch(., '\\s{0,}<script.*')\n                )\n                and any(.scan.strings.strings,\n                        strings.ends_with(., \"</script>\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML file with excessive 'const' declarations and abnormally long timeouts

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

Detects messages with HTML attachments containing multiple 'const' declarations while excluding legitimate Gmail messages. This is evidence of potential code injection or obfuscation techniques.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesHTML smuggling, Scripting, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_type == "html"
        )
        and strings.count(file.parse_html(.).raw, 'const') >= 7
        and not regex.contains(file.parse_html(.).raw,
                               "<!-- saved from url=.{0,7}https://mail.google.com/mail/u/0/#inbox/"
        )
        and length(file.parse_html(.).raw) < 50000
        // long timeouts
        and regex.icontains(file.parse_html(.).raw,
                            'setTimeout\(\s*(?:function\s*)?\(.*?\)\s*(?:=>\s*)?\{[\s\S]*?\},\s*\d+\);',
                            // const delay = new Promise((resolve) => setTimeout(resolve, 100));
                            'setTimeout\(\s*\w+\,\s*\d{3,}\)+;'
        )
)

// negate highly trusted sender domains unless they fail DMARC authentication or DMARC is missing
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.

Detects messages with HTML attachments containing multiple 'const' declarations while excluding legitimate Gmail messages. This is evidence of potential code injection or obfuscation techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_type is 'html'
    • strings.count(file.parse_html(.).raw, 'const') >= 7
    • not:
      • regex.contains(file.parse_html(.).raw, "<!-- saved from url=.{0,7}https://mail.google.com/mail/u/0/#inbox/" )
    • length(file.parse_html(.).raw) < 50000
    • regex.icontains(file.parse_html(.).raw, 'setTimeout\(\s*(?:function\s*)?\(.*?\)\s*(?:=>\s*)?\{[\s\S]*?\},\s*\d+\);', // const delay = new Promise((resolve) => setTimeout(resolve, 100)); 'setTimeout\(\s*\w+\,\s*\d{3,}\)+;' )
  3. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.parse_html, regex.contains, regex.icontains, strings.count. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.icontainsregexsetTimeout\(\s*(?:function\s*)?\(.*?\)\s*(?:=>\s*)?\{[\s\S]*?\},\s*\d+\);
regex.icontainsregexsetTimeout\(\s*\w+\,\s*\d{3,}\)+;

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
      not
        regex.contains func_call "regex.contains(file.parse_html(.).raw,\n                               \"<!-- saved from url=.{0,7}https://mail.google.com/mail/u/0/#inbox/\"\n        )"
      length func_call "length(file.parse_html(.).raw) < 50000"
      regex.icontains func_call "regex.icontains(file.parse_html(.).raw,\n                            'setTimeout\\(\\s*(?:function\\s*)?\\(.*?\\)\\s*(?:=>\\s*)?\\{[\\s\\S]*?\\},\\s*\\d+\\);',\n                            // const delay = new Promise((resolve) => setTimeout(resolve, 100));\n                            'setTimeout\\(\\s*\\w+\\,\\s*\\d{3,}\\)+;'\n        )"
      strings.count func_call "strings.count(file.parse_html(.).raw, 'const') >= 7"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: HTML file with excessive padding and suspicious patterns

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

Attached HTML file contains excessive line breaks and suspicious Javascript patterns.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .content_type == "text/html"
          or .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_type == "html"
        )
        and any(file.explode(.),
                any(.scan.yara.matches, .name == "HTML_EXCESSIVE_PADDING")
        )
)

Detection Logic

Scope: inbound message.

Attached HTML file contains excessive line breaks and suspicious Javascript patterns.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .content_type is 'text/html'
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.yara.matches, .name == "HTML_EXCESSIVE_PADDING") )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (7)

FieldMatchValue
attachments[].content_typeequalstext/html
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].scan.yara.matches[].nameequalsHTML_EXCESSIVE_PADDING

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.yara.matches, .name == \"HTML_EXCESSIVE_PADDING\")\n        )"
  type.inbound eq "true"

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"

Attachment: HTML file with reference to recipient and suspicious patterns

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

Attached HTML file (or HTML file within an attached email) contains references to the recipients email address, indicative of credential phishing, and suspicious Javascript patterns.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesHTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .content_type == "text/html"
          or (.content_type == "message/rfc822" or .file_extension in ('eml'))
          or .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_type == "html"
        )
        and any(file.explode(.),
                .flavors.mime in~ ("text/html", "text/plain")
                and any(recipients.to,
                        any(..scan.strings.strings,
                            strings.icontains(., ..email.email)
                        )
                        and (
                          .email.domain.valid
                          or strings.icontains(.display_name, "undisclosed")
                        )
                )
        )
        and any(file.explode(.),
                (
                  any(.flavors.yara, . == "javascript_file")
                  // common indicator of HTML smuggling
                  and length(filter(.scan.javascript.identifiers,
                                    strings.ilike(., "_0x*")
                             )
                  ) > 50
                )
                or (
                  // javascript that doesn't get pulled out properly
                  .flavors.mime == "text/plain"
                  and strings.ilike(.file_name, "script*")
                  // common indicator of HTML smuggling
                  and length(filter(.scan.strings.strings,
                                    regex.imatch(., ".*_0x.*")
                             )
                  ) > 50
                )
        )
)

Detection Logic

Scope: inbound message.

Attached HTML file (or HTML file within an attached email) contains references to the recipients email address, indicative of credential phishing, and suspicious Javascript patterns.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .content_type is 'text/html'
      • any of:
        • .content_type is 'message/rfc822'
        • .file_extension in ('eml')
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_type is 'html'
    • any(file.explode(.), .flavors.mime in~ ("text/html", "text/plain") and any(recipients.to, any(..scan.strings.strings, strings.icontains(., ..email.email) ) and ( .email.domain.valid or strings.icontains(.display_name, "undisclosed") ) ) )
    • any(file.explode(.), ( any(.flavors.yara, . == "javascript_file") // common indicator of HTML smuggling and length(filter(.scan.javascript.identifiers, strings.ilike(., "_0x*") ) ) > 50 ) or ( // javascript that doesn't get pulled out properly .flavors.mime == "text/plain" and strings.ilike(.file_name, "script*") // common indicator of HTML smuggling and length(filter(.scan.strings.strings, regex.imatch(., ".*_0x.*") ) ) > 50 ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, recipients.to, recipients.to[].display_name, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: file.explode, regex.imatch, strings.icontains, strings.ilike.

Indicators Matched (16)

FieldMatchValue
attachments[].content_typeequalstext/html
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionmembereml
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].flavors.mimemembertext/html
file.explode(attachments[])[].flavors.mimemembertext/plain
strings.icontainssubstringundisclosed
file.explode(attachments[])[].flavors.yara[]equalsjavascript_file
4 more
strings.ilikesubstring_0x*
file.explode(attachments[])[].flavors.mimeequalstext/plain
strings.ilikesubstringscript*
regex.imatchregex.*_0x.*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "message/rfc822"
        attachments.content_type eq "text/html"
        attachments.file_extension eq "eml"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                (\n                  any(.flavors.yara, . == \"javascript_file\")\n                  // common indicator of HTML smuggling\n                  and length(filter(.scan.javascript.identifiers,\n                                    strings.ilike(., \"_0x*\")\n                             )\n                  ) > 50\n                )\n                or (\n                  // javascript that doesn't get pulled out properly\n                  .flavors.mime == \"text/plain\"\n                  and strings.ilike(.file_name, \"script*\")\n                  // common indicator of HTML smuggling\n                  and length(filter(.scan.strings.strings,\n                                    regex.imatch(., \".*_0x.*\")\n                             )\n                  ) > 50\n                )\n        )"
       macro "any(file.explode(.),\n                .flavors.mime in~ (\"text/html\", \"text/plain\")\n                and any(recipients.to,\n                        any(..scan.strings.strings,\n                            strings.icontains(., ..email.email)\n                        )\n                        and (\n                          .email.domain.valid\n                          or strings.icontains(.display_name, \"undisclosed\")\n                        )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling 'body onload' linking to suspicious destination

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

Potential HTML Smuggling. This rule inspects HTML attachments that contain a single link and leveraging an HTML body onload event. The linked domain must be in the URLhaus trusted repoters list, or have a suspicious TLD.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml", "xhtml")
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
          )
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
          or .content_type == "text/html"
        )
        and any(file.explode(.),
                not length(.scan.url.invalid_urls) > 0
                and length(.scan.url.urls) == 1
                and any(.scan.strings.strings,
                        strings.ilike(., "*body onload*")
                )
                and (
                  any(.scan.url.urls,
                      .domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters

                      // To-do uncomment below when list is created
                      // or .domain.root_domain in $suspicious_root_domains
                      or .domain.tld in $suspicious_tlds
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

Potential HTML Smuggling. This rule inspects HTML attachments that contain a single link and leveraging an HTML body onload event. The linked domain must be in the URLhaus trusted repoters list, or have a suspicious TLD.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml', 'xhtml')
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
      • .content_type is 'text/html'
    • any(file.explode(.), not length(.scan.url.invalid_urls) > 0 and length(.scan.url.urls) == 1 and any(.scan.strings.strings, strings.ilike(., "*body onload*") ) and ( any(.scan.url.urls, .domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters // To-do uncomment below when list is created // or .domain.root_domain in $suspicious_root_domains or .domain.tld in $suspicious_tlds ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $abuse_ch_urlhaus_domains_trusted_reporters, $file_extensions_common_archives, $suspicious_tlds.

Indicators Matched (10)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_extensionmemberxhtml
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
strings.ilikesubstring*body onload*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml", "xhtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                not length(.scan.url.invalid_urls) > 0\n                and length(.scan.url.urls) == 1\n                and any(.scan.strings.strings,\n                        strings.ilike(., \"*body onload*\")\n                )\n                and (\n                  any(.scan.url.urls,\n                      .domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters\n\n                      // To-do uncomment below when list is created\n                      // or .domain.root_domain in $suspicious_root_domains\n                      or .domain.tld in $suspicious_tlds\n                  )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling 'body onload' with high entropy and suspicious text

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

Potential HTML Smuggling. This rule inspects HTML attachments that contain "body unload", high entropy, and suspicious text.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml", "xhtml")
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
          )
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
          or .content_type == "text/html"
        )
        and any(file.explode(.),
                .scan.entropy.entropy >= 5
                and any(.scan.strings.strings,
                        strings.ilike(., "*body onload*")
                )
                and any(.scan.strings.strings,
                        regex.icontains(., 'data:image/.*;base64')
                )
                and any(.scan.strings.strings,
                        strings.ilike(., "*document pass*")
                )
        )
)

Detection Logic

Scope: inbound message.

Potential HTML Smuggling. This rule inspects HTML attachments that contain "body unload", high entropy, and suspicious text.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml', 'xhtml')
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
      • .content_type is 'text/html'
    • any(file.explode(.), .scan.entropy.entropy >= 5 and any(.scan.strings.strings, strings.ilike(., "*body onload*") ) and any(.scan.strings.strings, regex.icontains(., 'data:image/.*;base64') ) and any(.scan.strings.strings, strings.ilike(., "*document pass*") ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.icontains, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (12)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_extensionmemberxhtml
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
strings.ilikesubstring*body onload*
regex.icontainsregexdata:image/.*;base64
strings.ilikesubstring*document pass*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml", "xhtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                .scan.entropy.entropy >= 5\n                and any(.scan.strings.strings,\n                        strings.ilike(., \"*body onload*\")\n                )\n                and any(.scan.strings.strings,\n                        regex.icontains(., 'data:image/.*;base64')\n                )\n                and any(.scan.strings.strings,\n                        strings.ilike(., \"*document pass*\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling - QR Code with suspicious links

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

This rule detects messages with HTML attachments containing QR codes

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and 1 <= length(attachments) < 3

// inspects HTML attachments for QR codes
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml", "xhtml")
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
          )
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
          or .content_type == "text/html"
        )
        and any(file.explode(file.html_screenshot(.)),
                // any URL
                ml.link_analysis(.scan.qr.url).submitted
                // currently we won't pick it up as a URL if it's
                // not prefaced with a scheme. this is not very strong,
                // but it's unlikely to cause FPs for this rule
                or regex.contains(.scan.qr.data, '\.')
        )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

This rule detects messages with HTML attachments containing QR codes

  1. inbound message
  2. all of:
    • (1) <= (length(attachments))
    • (length(attachments)) < (3)
  3. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml', 'xhtml')
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
      • .content_type is 'text/html'
    • any(file.explode(file.html_screenshot(.)), // any URL ml.link_analysis(.scan.qr.url).submitted // currently we won't pick it up as a URL if it's // not prefaced with a scheme. this is not very strong, // but it's unlikely to cause FPs for this rule or regex.contains(.scan.qr.data, '\.') )
  4. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  5. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  6. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, file.html_screenshot, ml.link_analysis, profile.by_sender, regex.contains. Reference lists: $file_extensions_common_archives, $high_trust_sender_root_domains.

Indicators Matched (10)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_extensionmemberxhtml
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
regex.containsregex\.

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml", "xhtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(file.html_screenshot(.)),\n                // any URL\n                ml.link_analysis(.scan.qr.url).submitted\n                // currently we won't pick it up as a URL if it's\n                // not prefaced with a scheme. this is not very strong,\n                // but it's unlikely to cause FPs for this rule\n                or regex.contains(.scan.qr.data, '\\.')\n        )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  attachments length_compare "1"
  attachments length_compare "3"
  type.inbound eq "true"

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"

Attachment: HTML smuggling Microsoft sign in

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

Scans HTML files to detect HTML smuggling techniques impersonating a Microsoft login page.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree subdomain host, HTML smuggling, Impersonation: Brand, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • sender.email
  • type

Rule Body

type.inbound
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(.),
                .scan.entropy.entropy >= 5.7
                and .flavors.mime == "text/html"
                and length(.scan.javascript.identifiers) == 0
                and any(.scan.url.urls,
                        .domain.domain not in $tranco_1m
                        or .domain.root_domain in $free_subdomain_hosts
                )

                // seen in the wild: "sign in to your account", "sign in to your microsoft account"
                and strings.ilike(.scan.html.title, "*sign in*", "*microsoft*")
        )
)
// allow Microsoft domains just to be safe
and sender.email.domain.root_domain not in~ (
  'microsoft.com',
  'microsoftsupport.com',
  'office.com'
)

Detection Logic

Scope: inbound message.

Scans HTML files to detect HTML smuggling techniques impersonating a Microsoft login page.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), .scan.entropy.entropy >= 5.7 and .flavors.mime == "text/html" and length(.scan.javascript.identifiers) == 0 and any(.scan.url.urls, .domain.domain not in $tranco_1m or .domain.root_domain in $free_subdomain_hosts ) // seen in the wild: "sign in to your account", "sign in to your microsoft account" and strings.ilike(.scan.html.title, "*sign in*", "*microsoft*") )
  3. sender.email.domain.root_domain not in ('microsoft.com', 'microsoftsupport.com', 'office.com')

Inspects: attachments[].file_extension, attachments[].file_type, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives, $free_subdomain_hosts, $tranco_1m.

Indicators Matched (8)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].flavors.mimeequalstext/html
strings.ilikesubstring*sign in*
strings.ilikesubstring*microsoft*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                .scan.entropy.entropy >= 5.7\n                and .flavors.mime == \"text/html\"\n                and length(.scan.javascript.identifiers) == 0\n                and any(.scan.url.urls,\n                        .domain.domain not in $tranco_1m\n                        or .domain.root_domain in $free_subdomain_hosts\n                )\n\n                // seen in the wild: \"sign in to your account\", \"sign in to your microsoft account\"\n                and strings.ilike(.scan.html.title, \"*sign in*\", \"*microsoft*\")\n        )"
  not
    sender.email.domain.root_domain in ["microsoft.com", "microsoftsupport.com", "office.com"]
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

Attachment: HTML smuggling with atob and high entropy

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

Recursively scans files and archives to detect HTML smuggling techniques using Javascript atob functions.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesHTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml", "eml")
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
          or .content_type == "message/rfc822"
          or .file_extension in ('eml')
        )
        and any(file.explode(.),
                .scan.entropy.entropy >= 5
                and (
                  length(filter(.scan.javascript.identifiers,
                                strings.like(., "document", "write", "atob")
                         )
                  ) == 3
                  // usage: document['write'](atob)
                  or any(.scan.strings.strings,
                         regex.icontains(., "document.{0,10}write.{0,10}atob")
                  )
                  // usage: some_var = atob();
                  or any(.scan.strings.strings,
                         regex.icontains(., "=.?atob.*;")
                  )
                  // usage: atob(atob
                  or any(.scan.strings.strings, strings.ilike(., "*atob?atob*"))
                  // usage: {src: atob
                  or any(.scan.strings.strings,
                         strings.ilike(., "*{src: atob*")
                  )
                  // usage: eval(atob)
                  or any(.scan.strings.strings, strings.ilike(., "*eval?atob*"))
                  // usage: atob(_0x)
                  or any(.scan.strings.strings, strings.ilike(., "*atob(?0x*"))
                  // usage : 'at'+'ob'
                  or any(.scan.strings.strings, strings.ilike(., "*'at'+'ob'*"))
                  // 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*insertAdjacentHTML*atob*")
                  )
                )
        )
)
// negate bouncebacks and undeliverables
and not any(attachments,
            .content_type in (
              "message/global-delivery-status",
              "message/delivery-status"
            )
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques using Javascript atob functions.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml', 'eml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
      • .content_type is 'message/rfc822'
      • .file_extension in ('eml')
    • any(file.explode(.), .scan.entropy.entropy >= 5 and ( length(filter(.scan.javascript.identifiers, strings.like(., "document", "write", "atob") ) ) == 3 // usage: document['write'](atob) or any(.scan.strings.strings, regex.icontains(., "document.{0,10}write.{0,10}atob") ) // usage: some_var = atob(); or any(.scan.strings.strings, regex.icontains(., "=.?atob.*;") ) // usage: atob(atob or any(.scan.strings.strings, strings.ilike(., "*atob?atob*")) // usage: {src: atob or any(.scan.strings.strings, strings.ilike(., "*{src: atob*") ) // usage: eval(atob) or any(.scan.strings.strings, strings.ilike(., "*eval?atob*")) // usage: atob(_0x) or any(.scan.strings.strings, strings.ilike(., "*atob(?0x*")) // usage : 'at'+'ob' or any(.scan.strings.strings, strings.ilike(., "*'at'+'ob'*")) // 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*insertAdjacentHTML*atob*") ) ) )
  3. not:
    • any of attachments where:
      • .content_type in ('message/global-delivery-status', 'message/delivery-status')
  4. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, regex.icontains, strings.ilike, strings.like. Reference lists: $file_extensions_common_archives, $high_trust_sender_root_domains.

Indicators Matched (19)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_extensionmembereml
attachments[].file_typeequalshtml
attachments[].content_typeequalsmessage/rfc822
strings.likesubstringdocument
strings.likesubstringwrite
strings.likesubstringatob
regex.icontainsregexdocument.{0,10}write.{0,10}atob
regex.icontainsregex=.?atob.*;
7 more
strings.ilikesubstring*atob?atob*
strings.ilikesubstring*{src: atob*
strings.ilikesubstring*eval?atob*
strings.ilikesubstring*atob(?0x*
strings.ilikesubstring*'at'+'ob'*
strings.ilikesubstring*ato\u0062*
strings.ilikesubstring*document*insertAdjacentHTML*atob*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
        attachments.file_extension in ["dhtml", "eml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                .scan.entropy.entropy >= 5\n                and (\n                  length(filter(.scan.javascript.identifiers,\n                                strings.like(., \"document\", \"write\", \"atob\")\n                         )\n                  ) == 3\n                  // usage: document['write'](atob)\n                  or any(.scan.strings.strings,\n                         regex.icontains(., \"document.{0,10}write.{0,10}atob\")\n                  )\n                  // usage: some_var = atob();\n                  or any(.scan.strings.strings,\n                         regex.icontains(., \"=.?atob.*;\")\n                  )\n                  // usage: atob(atob\n                  or any(.scan.strings.strings, strings.ilike(., \"*atob?atob*\"))\n                  // usage: {src: atob\n                  or any(.scan.strings.strings,\n                         strings.ilike(., \"*{src: atob*\")\n                  )\n                  // usage: eval(atob)\n                  or any(.scan.strings.strings, strings.ilike(., \"*eval?atob*\"))\n                  // usage: atob(_0x)\n                  or any(.scan.strings.strings, strings.ilike(., \"*atob(?0x*\"))\n                  // usage : 'at'+'ob'\n                  or any(.scan.strings.strings, strings.ilike(., \"*'at'+'ob'*\"))\n                  // usage: obfuscating \"atob\"\n                  or any(.scan.javascript.identifiers,\n                         strings.ilike(., '*ato\\u0062*')\n                  )\n                  // usage: document.head.insertAdjacentHTML(\"beforeend\", atob(...\n                  or any(.scan.strings.strings,\n                         strings.ilike(., \"*document*insertAdjacentHTML*atob*\")\n                  )\n                )\n        )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    any(attachments)
      attachments.content_type in ["message/delivery-status", "message/global-delivery-status"]
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments

Attachment: HTML smuggling with atob and high entropy via calendar invite

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

Scans calendar invites (.ics files) to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, ICS Phishing, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (.file_extension =~ "ics" or .content_type == "text/calendar")
        and any(file.explode(.),
                .scan.entropy.entropy >= 5
                and (
                  length(filter(.scan.javascript.identifiers,
                                strings.like(., "document", "write", "atob")
                         )
                  ) == 3
                  // usage: document['write'](atob)
                  or any(.scan.strings.strings,
                         regex.icontains(., "document.{0,10}write.{0,10}atob")
                  )
                  // usage: some_var = atob();
                  or any(.scan.strings.strings,
                         regex.icontains(., "=.?atob.*;")
                  )
                  // usage: atob(atob
                  or any(.scan.strings.strings, strings.ilike(., "*atob?atob*"))
                  // usage: {src: atob
                  or any(.scan.strings.strings,
                         strings.ilike(., "*{src: atob*")
                  )
                  // usage: eval(atob)
                  or any(.scan.strings.strings, strings.ilike(., "*eval?atob*"))
                  // usage: atob(_0x)
                  or any(.scan.strings.strings, strings.ilike(., "*atob(?0x*"))
                  // usage : 'at'+'ob'
                  or any(.scan.strings.strings, strings.ilike(., "*'at'+'ob'*"))
                  // 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*insertAdjacentHTML*atob*")
                  )
                )
        )
)
// negate bouncebacks and undeliverables
and not any(attachments,
            .content_type in (
              "message/global-delivery-status",
              "message/delivery-status"
            )
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Scans calendar invites (.ics files) to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'ics'
      • .content_type is 'text/calendar'
    • any(file.explode(.), .scan.entropy.entropy >= 5 and ( length(filter(.scan.javascript.identifiers, strings.like(., "document", "write", "atob") ) ) == 3 // usage: document['write'](atob) or any(.scan.strings.strings, regex.icontains(., "document.{0,10}write.{0,10}atob") ) // usage: some_var = atob(); or any(.scan.strings.strings, regex.icontains(., "=.?atob.*;") ) // usage: atob(atob or any(.scan.strings.strings, strings.ilike(., "*atob?atob*")) // usage: {src: atob or any(.scan.strings.strings, strings.ilike(., "*{src: atob*") ) // usage: eval(atob) or any(.scan.strings.strings, strings.ilike(., "*eval?atob*")) // usage: atob(_0x) or any(.scan.strings.strings, strings.ilike(., "*atob(?0x*")) // usage : 'at'+'ob' or any(.scan.strings.strings, strings.ilike(., "*'at'+'ob'*")) // 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*insertAdjacentHTML*atob*") ) ) )
  3. not:
    • any of attachments where:
      • .content_type in ('message/global-delivery-status', 'message/delivery-status')
  4. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_type, attachments[].file_extension, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, regex.icontains, strings.ilike, strings.like. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (14)

FieldMatchValue
attachments[].file_extensionequalsics
attachments[].content_typeequalstext/calendar
strings.likesubstringdocument
strings.likesubstringwrite
strings.likesubstringatob
regex.icontainsregexdocument.{0,10}write.{0,10}atob
regex.icontainsregex=.?atob.*;
strings.ilikesubstring*atob?atob*
strings.ilikesubstring*{src: atob*
strings.ilikesubstring*eval?atob*
strings.ilikesubstring*atob(?0x*
strings.ilikesubstring*'at'+'ob'*
2 more
strings.ilikesubstring*ato\u0062*
strings.ilikesubstring*document*insertAdjacentHTML*atob*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "text/calendar"
        attachments.file_extension eq "ics"
       macro "any(file.explode(.),\n                .scan.entropy.entropy >= 5\n                and (\n                  length(filter(.scan.javascript.identifiers,\n                                strings.like(., \"document\", \"write\", \"atob\")\n                         )\n                  ) == 3\n                  // usage: document['write'](atob)\n                  or any(.scan.strings.strings,\n                         regex.icontains(., \"document.{0,10}write.{0,10}atob\")\n                  )\n                  // usage: some_var = atob();\n                  or any(.scan.strings.strings,\n                         regex.icontains(., \"=.?atob.*;\")\n                  )\n                  // usage: atob(atob\n                  or any(.scan.strings.strings, strings.ilike(., \"*atob?atob*\"))\n                  // usage: {src: atob\n                  or any(.scan.strings.strings,\n                         strings.ilike(., \"*{src: atob*\")\n                  )\n                  // usage: eval(atob)\n                  or any(.scan.strings.strings, strings.ilike(., \"*eval?atob*\"))\n                  // usage: atob(_0x)\n                  or any(.scan.strings.strings, strings.ilike(., \"*atob(?0x*\"))\n                  // usage : 'at'+'ob'\n                  or any(.scan.strings.strings, strings.ilike(., \"*'at'+'ob'*\"))\n                  // usage: obfuscating \"atob\"\n                  or any(.scan.javascript.identifiers,\n                         strings.ilike(., '*ato\\u0062*')\n                  )\n                  // usage: document.head.insertAdjacentHTML(\"beforeend\", atob(...\n                  or any(.scan.strings.strings,\n                         strings.ilike(., \"*document*insertAdjacentHTML*atob*\")\n                  )\n                )\n        )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    any(attachments)
      attachments.content_type in ["message/delivery-status", "message/global-delivery-status"]
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments

Attachment: HTML smuggling with auto-downloaded file

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

HTML attachments containing files that are automatically downloaded with Javascript.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesHTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.javascript.identifiers, strings.ilike(., 'click'))
                and any(.scan.javascript.identifiers,
                        strings.ilike(., 'addEventListener')
                )
                and (
                  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.

HTML attachments containing files that are automatically downloaded with Javascript.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.javascript.identifiers, strings.ilike(., 'click')) and any(.scan.javascript.identifiers, strings.ilike(., 'addEventListener') ) and ( 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*" ) ) ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.ilike, strings.like. Reference lists: $file_extensions_common_archives.

Indicators Matched (14)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
strings.ilikesubstringclick
strings.ilikesubstringaddEventListener
strings.likesubstringdocument
strings.likesubstringwrite
strings.likesubstringatob
strings.ilikesubstring*document*write*atob*
strings.ilikesubstring*=*atob*;
2 more
strings.ilikesubstring*ato\u0062*
strings.ilikesubstring*document*insertAdjacentHTML*atob*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.javascript.identifiers, strings.ilike(., 'click'))\n                and any(.scan.javascript.identifiers,\n                        strings.ilike(., 'addEventListener')\n                )\n                and (\n                  length(filter(.scan.javascript.identifiers,\n                                strings.like(., \"document\", \"write\", \"atob\")\n                         )\n                  ) == 3\n                  // usage: document['write'](atob)\n                  or any(.scan.strings.strings,\n                         strings.ilike(., \"*document*write*atob*\")\n                  )\n                  // usage: some_var = atob();\n                  or any(.scan.strings.strings, strings.ilike(., \"*=*atob*;\"))\n                  // usage: obfuscating \"atob\"\n                  or any(.scan.javascript.identifiers,\n                         strings.ilike(., '*ato\\u0062*')\n                  )\n                  // usage: document.head.insertAdjacentHTML(\"beforeend\", atob(...\n                  or any(.scan.strings.strings,\n                         strings.ilike(.,\n                                       \"*document*write*atob*\",\n                                       \"*document*insertAdjacentHTML*atob*\"\n                         )\n                  )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with base64 encoded JavaScript function

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

This rule identifies attachments that either have an HTML extension, lack any file extension, or possess an unrecognized file type and are employing Base64 encoding to conceal JavaScript functions within HTML script tags with little to no other content. Such obfuscation tactics have been frequently observed in credential phishing campaigns.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesHTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
        )
        and any(file.explode(.),
                any(.scan.strings.strings,
                    strings.contains(., "data:text/javascript;base64")
                )
                // strings array is small
                and length(.scan.strings.strings) < 10
        )
)

Detection Logic

Scope: inbound message.

This rule identifies attachments that either have an HTML extension, lack any file extension, or possess an unrecognized file type and are employing Base64 encoding to conceal JavaScript functions within HTML script tags with little to no other content. Such obfuscation tactics have been frequently observed in credential phishing campaigns.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, strings.contains(., "data:text/javascript;base64") ) // strings array is small and length(.scan.strings.strings) < 10 )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, strings.contains. Reference lists: $file_extensions_common_archives.

Indicators Matched (8)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
attachments[].file_typeequalshtml
strings.containssubstringdata:text/javascript;base64

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    strings.contains(., \"data:text/javascript;base64\")\n                )\n                // strings array is small\n                and length(.scan.strings.strings) < 10\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with base64 encoded ZIP file

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

Detects HTML attachments containing base64-encoded ZIP or Office files alongside JavaScript decoding functions such as atob, fromCharCode, or base64. This technique is commonly used to evade security controls by hiding malicious files within HTML content that are decoded and executed client-side.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_type == "html"
        )
        and (
          // javascript functions to decode the base64
          strings.icontains(file.parse_text(.).text, 'atob')
          or strings.icontains(file.parse_text(.).text, 'fromCharCode')
          or strings.icontains(file.parse_text(.).text, 'base64')
        )
        // Magic bytes for a ZIP/Office File that have been base64 encoded
        and regex.contains(file.parse_text(.).text,
                           '[\x2C\x3B\x3A\x22\x27\x28\x7B\x5B\s]UEsDB'
        )
        // negation of Micro Focus Voltage Secure Messaging
        and not strings.contains(file.parse_text(.).text,
                                 "<input type=\"hidden\" name=\"ZFRdata\" value=\"\n-----BEGIN VOLTAGE SECURE BLOCK V3-----\nUEsDBBQAAAAAAAAAAA"
        )
)

Detection Logic

Scope: inbound message.

Detects HTML attachments containing base64-encoded ZIP or Office files alongside JavaScript decoding functions such as atob, fromCharCode, or base64. This technique is commonly used to evade security controls by hiding malicious files within HTML content that are decoded and executed client-side.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_type is 'html'
    • any of:
      • strings.icontains(file.parse_text(.).text, 'atob')
      • strings.icontains(file.parse_text(.).text, 'fromCharCode')
      • strings.icontains(file.parse_text(.).text, 'base64')
    • regex.contains(file.parse_text(.).text, '[\x2C\x3B\x3A\x22\x27\x28\x7B\x5B\s]UEsDB' )
    • not:
      • strings.contains(file.parse_text(.).text, "<input type=\"hidden\" name=\"ZFRdata\" value=\"\n-----BEGIN VOLTAGE SECURE BLOCK V3-----\nUEsDBBQAAAAAAAAAAA" )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.parse_text, regex.contains, strings.contains, strings.icontains.

Indicators Matched (9)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
strings.icontainssubstringatob
strings.icontainssubstringfromCharCode
strings.icontainssubstringbase64
regex.containsregex[\x2C\x3B\x3A\x22\x27\x28\x7B\x5B\s]UEsDB

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
      not
        strings.contains func_call "strings.contains(file.parse_text(.).text,\n                                 \"<input type=\\\"hidden\\\" name=\\\"ZFRdata\\\" value=\\\"\\n-----BEGIN VOLTAGE SECURE BLOCK V3-----\\nUEsDBBQAAAAAAAAAAA\"\n        )"
      or
        strings.icontains func_call "strings.icontains(file.parse_text(.).text, 'atob')"
        strings.icontains func_call "strings.icontains(file.parse_text(.).text, 'base64')"
        strings.icontains func_call "strings.icontains(file.parse_text(.).text, 'fromCharCode')"
      regex.contains func_call "regex.contains(file.parse_text(.).text,\n                           '[\\x2C\\x3B\\x3A\\x22\\x27\\x28\\x7B\\x5B\\s]UEsDB'\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with concatenation obfuscation

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.strings.strings,
                    strings.ilike(.,
                                  "*CJzYyIuY29uY2F0KCJyaXB0Iik*",
                                  '*"sc".concat("ript")*'
                    )
                )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., "*CJzYyIuY29uY2F0KCJyaXB0Iik*", '*"sc".concat("ript")*' ) ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
strings.ilikesubstring*CJzYyIuY29uY2F0KCJyaXB0Iik*
strings.ilikesubstring*"sc".concat("ript")*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    strings.ilike(.,\n                                  \"*CJzYyIuY29uY2F0KCJyaXB0Iik*\",\n                                  '*\"sc\".concat(\"ript\")*'\n                    )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with decimal encoding

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

Potential HTML smuggling attack based on large blocks of decimal encoding. Attackers often use decimal encoding as an obfuscation technique to bypass traditional email security measures.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml", "xhtml")
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
          )
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
          or .content_type == "text/html"
        )
        and any(file.explode(.),
                // suspicious identifiers
                any(.scan.strings.strings, regex.contains(., '(\d{2,3},){60,}'))
        )
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Potential HTML smuggling attack based on large blocks of decimal encoding. Attackers often use decimal encoding as an obfuscation technique to bypass traditional email security measures.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml', 'xhtml')
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
      • .content_type is 'text/html'
    • any(file.explode(.), // suspicious identifiers any(.scan.strings.strings, regex.contains(., '(\d{2,3},){60,}')) )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  4. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  5. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, profile.by_sender, regex.contains. Reference lists: $file_extensions_common_archives, $high_trust_sender_root_domains.

Indicators Matched (10)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_extensionmemberxhtml
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
regex.containsregex(\d{2,3},){60,}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml", "xhtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                // suspicious identifiers\n                any(.scan.strings.strings, regex.contains(., '(\\d{2,3},){60,}'))\n        )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with embedded base64 streamed file download

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

HTML attachments containing base64-encoded files that are downloaded via embedded hyperlinks. This TTP is used by attackers to bypass email and web filters since the file is not downloaded from an external source. Recently observed delivering Qakbot.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesHTML smuggling, Scripting, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.strings.strings,
                    regex.icontains(.,
                                    '<a href="data:application/octet-stream;base64,[a-z0-9/+]+={0,2}" download=".+\.[a-z]{2,3}'
                    )
                )
        )
)

Detection Logic

Scope: inbound message.

HTML attachments containing base64-encoded files that are downloaded via embedded hyperlinks. This TTP is used by attackers to bypass email and web filters since the file is not downloaded from an external source. Recently observed delivering Qakbot.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, regex.icontains(., '<a href="data:application/octet-stream;base64,[a-z0-9/+]+={0,2}" download=".+\.[a-z]{2,3}' ) ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.icontains. Reference lists: $file_extensions_common_archives.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.icontainsregex<a href="data:application/octet-stream;base64,[a-z0-9/+]+={0,2}" download=".+\.[a-z]{2,3}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    regex.icontains(.,\n                                    '<a href=\"data:application/octet-stream;base64,[a-z0-9/+]+={0,2}\" download=\".+\\.[a-z]{2,3}'\n                    )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with embedded base64-encoded executable

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

HTML attachmemt contains a base-64 encoded executable.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                (
                  .file_extension in~ ("html", "htm", "shtml", "dhtml")
                  or .flavors.mime == "text/plain"
                )
                and any(.flavors.yara, . == 'base64_pe')
        )
)

Detection Logic

Scope: inbound message.

HTML attachmemt contains a base-64 encoded executable.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), ( .file_extension in~ ("html", "htm", "shtml", "dhtml") or .flavors.mime == "text/plain" ) and any(.flavors.yara, . == 'base64_pe') )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (11)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].file_extensionmemberhtml
file.explode(attachments[])[].file_extensionmemberhtm
file.explode(attachments[])[].file_extensionmembershtml
file.explode(attachments[])[].file_extensionmemberdhtml
file.explode(attachments[])[].flavors.mimeequalstext/plain
file.explode(attachments[])[].flavors.yara[]equalsbase64_pe

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                (\n                  .file_extension in~ (\"html\", \"htm\", \"shtml\", \"dhtml\")\n                  or .flavors.mime == \"text/plain\"\n                )\n                and any(.flavors.yara, . == 'base64_pe')\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with embedded base64-encoded ISO

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

HTML attachment contains a base-64 encoded ISO. This is a known TTP for multiple threat actors.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, ISO

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm")
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
        )
        and any(file.explode(.),
                any(.scan.strings.strings,
                    strings.ilike(.,
                                  // Base64 encoded ISOs
                                  "*SVNPIDk2NjAvSEZT*",
                                  "*MTk5MyBFLllPVU5HREFMRQ*",
                                  // Reversed base64 encoded ISOs
                                  "*TZESvAjN2kDIPNVS*",
                                  "*QRMFERH5UVPllLFByM5kTM*"
                    )
                )
        )
)

Detection Logic

Scope: inbound message.

HTML attachment contains a base-64 encoded ISO. This is a known TTP for multiple threat actors.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., // Base64 encoded ISOs "*SVNPIDk2NjAvSEZT*", "*MTk5MyBFLllPVU5HREFMRQ*", // Reversed base64 encoded ISOs "*TZESvAjN2kDIPNVS*", "*QRMFERH5UVPllLFByM5kTM*" ) ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_typeequalshtml
strings.ilikesubstring*SVNPIDk2NjAvSEZT*
strings.ilikesubstring*MTk5MyBFLllPVU5HREFMRQ*
strings.ilikesubstring*TZESvAjN2kDIPNVS*
strings.ilikesubstring*QRMFERH5UVPllLFByM5kTM*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["htm", "html"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    strings.ilike(.,\n                                  // Base64 encoded ISOs\n                                  \"*SVNPIDk2NjAvSEZT*\",\n                                  \"*MTk5MyBFLllPVU5HREFMRQ*\",\n                                  // Reversed base64 encoded ISOs\n                                  \"*TZESvAjN2kDIPNVS*\",\n                                  \"*QRMFERH5UVPllLFByM5kTM*\"\n                    )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with eval and atob

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                // usage: onerror="eval(atob('
                any(.scan.strings.strings,
                    regex.imatch(., ".*eval.{1,4}atob.*")
                )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), // usage: onerror="eval(atob(' any(.scan.strings.strings, regex.imatch(., ".*eval.{1,4}atob.*") ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.imatch. Reference lists: $file_extensions_common_archives.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.imatchregex.*eval.{1,4}atob.*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                // usage: onerror=\"eval(atob('\n                any(.scan.strings.strings,\n                    regex.imatch(., \".*eval.{1,4}atob.*\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with eval and atob via calendar invite

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

Scans calendar invites (.ics files) to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, ICS Phishing, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (.file_extension =~ "ics" or .content_type == "text/calendar")
        // usage: onerror="eval(atob('
        and regex.imatch(file.parse_text(.).text, ".*eval.{1,4}atob.*")
)

Detection Logic

Scope: inbound message.

Scans calendar invites (.ics files) to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'ics'
      • .content_type is 'text/calendar'
    • regex.imatch(file.parse_text(.).text, ".*eval.{1,4}atob.*")

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: file.parse_text, regex.imatch.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionequalsics
attachments[].content_typeequalstext/calendar
regex.imatchregex.*eval.{1,4}atob.*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "text/calendar"
        attachments.file_extension eq "ics"
      regex.imatch func_call "regex.imatch(file.parse_text(.).text, \".*eval.{1,4}atob.*\")"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with excessive line break obfuscation

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

Credential Phishing attacks have been observed using excessive line breaks to obfuscate javascript functions within html files.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEncryption, Evasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.strings.strings,
                    // return new line padded obfuscation 
                    regex.contains(., '(\\r\\n\S{2}){50,}')
                    and strings.contains(., 'decodeURIComponent')
                )
        )
)

Detection Logic

Scope: inbound message.

Credential Phishing attacks have been observed using excessive line breaks to obfuscate javascript functions within html files.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, // return new line padded obfuscation regex.contains(., '(\\r\\n\S{2}){50,}') and strings.contains(., 'decodeURIComponent') ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.contains, strings.contains. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.containsregex(\\r\\n\S{2}){50,}
strings.containssubstringdecodeURIComponent

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    // return new line padded obfuscation \n                    regex.contains(., '(\\\\r\\\\n\\S{2}){50,}')\n                    and strings.contains(., 'decodeURIComponent')\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with excessive string concatenation and suspicious patterns

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

Attached HTML file contains excessive string concatenation, a recipient's email address, and an indicator of HTML smuggling. This pattern has been seen in the wild in an attempt to obfuscate the file's contents.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, HTML smuggling, Scripting, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule Body

type.inbound
and any(attachments,
        // HTML file, or something like it
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
          or .file_type == "html"
        )

        // small HTML file
        and .size < 5000

        // lots of concatenation (obfuscation technique)
        and strings.count(file.parse_html(.).raw, "+") > 20

        // contains a recipient's email address
        and any(recipients.to,
                strings.icontains(file.parse_html(..).raw, .email.email)
                and .email.domain.valid
        )

        // HTML smuggling
        and 1 of (
          strings.ilike(file.parse_html(.).raw, "*window.location.href*"),
          strings.ilike(file.parse_html(.).raw, "*createObjectURL*")
        )
)

Detection Logic

Scope: inbound message.

Attached HTML file contains excessive string concatenation, a recipient's email address, and an indicator of HTML smuggling. This pattern has been seen in the wild in an attempt to obfuscate the file's contents.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
      • .file_type is 'html'
    • .size < 5000
    • strings.count(file.parse_html(.).raw, "+") > 20
    • any of recipients.to where all hold:
      • strings.icontains(file.parse_html(..).raw, .email.email)
      • .email.domain.valid
    • at least 1 of:
      • strings.ilike(file.parse_html(.).raw, "*window.location.href*")
      • strings.ilike(file.parse_html(.).raw, "*createObjectURL*")

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: file.parse_html, strings.count, strings.icontains, strings.ilike.

Indicators Matched (9)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
attachments[].file_typeequalshtml
strings.ilikesubstring*window.location.href*
strings.ilikesubstring*createObjectURL*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
      any(recipients.to)
        and
          recipients.to.email.domain.valid eq "true"
          strings.icontains func_call "strings.icontains(file.parse_html(..).raw, .email.email)"
      or
        strings.ilike func_call "strings.ilike(file.parse_html(.).raw, \"*createObjectURL*\")"
        strings.ilike func_call "strings.ilike(file.parse_html(.).raw, \"*window.location.href*\")"
      attachments.size lt "5000"
      strings.count func_call "strings.count(file.parse_html(.).raw, \"+\") > 20"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with fromCharCode and other signals

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.scan.javascript.identifiers) < 100
                and "location" in .scan.javascript.identifiers
                and "charCodeAt" in .scan.javascript.identifiers
                and "fromCharCode" in .scan.javascript.identifiers
                and "indexOf" in .scan.javascript.identifiers
                and "try" in .scan.javascript.keywords
                and "catch" in .scan.javascript.keywords
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), length(.scan.javascript.identifiers) < 100 and "location" in .scan.javascript.identifiers and "charCodeAt" in .scan.javascript.identifiers and "fromCharCode" in .scan.javascript.identifiers and "indexOf" in .scan.javascript.identifiers and "try" in .scan.javascript.keywords and "catch" in .scan.javascript.keywords )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (11)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].scan.javascript.identifierscontainslocation
file.explode(attachments[])[].scan.javascript.identifierscontainscharCodeAt
file.explode(attachments[])[].scan.javascript.identifierscontainsfromCharCode
file.explode(attachments[])[].scan.javascript.identifierscontainsindexOf
file.explode(attachments[])[].scan.javascript.keywordscontainstry
file.explode(attachments[])[].scan.javascript.keywordscontainscatch

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                length(.scan.javascript.identifiers) < 100\n                and \"location\" in .scan.javascript.identifiers\n                and \"charCodeAt\" in .scan.javascript.identifiers\n                and \"fromCharCode\" in .scan.javascript.identifiers\n                and \"indexOf\" in .scan.javascript.identifiers\n                and \"try\" in .scan.javascript.keywords\n                and \"catch\" in .scan.javascript.keywords\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with hex strings

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

Recursively scans files and archives to detect HTML smuggling using hex-encoded string content.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.strings.strings,
                    // ["\x00\x00\x00\xAA..."]
                    regex.icontains(., '(\\x([a-zA-Z0-9]{2})){100}')
                )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling using hex-encoded string content.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, // ["\x00\x00\x00\xAA..."] regex.icontains(., '(\\x([a-zA-Z0-9]{2})){100}') ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.icontains. Reference lists: $file_extensions_common_archives.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.icontainsregex(\\x([a-zA-Z0-9]{2})){100}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    // [\"\\x00\\x00\\x00\\xAA...\"]\n                    regex.icontains(., '(\\\\x([a-zA-Z0-9]{2})){100}')\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with high entropy and other signals

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                .scan.entropy.entropy >= 5
                and any(.scan.strings.strings,
                        regex.icontains(., "fromCharCode")
                        and regex.icontains(., "parseInt")
                        and regex.icontains(., "charCodeAt")
                        and regex.icontains(., '(\\x0.*?){50}')
                )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), .scan.entropy.entropy >= 5 and any(.scan.strings.strings, regex.icontains(., "fromCharCode") and regex.icontains(., "parseInt") and regex.icontains(., "charCodeAt") and regex.icontains(., '(\\x0.*?){50}') ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.icontains. Reference lists: $file_extensions_common_archives.

Indicators Matched (9)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.icontainsregexfromCharCode
regex.icontainsregexparseInt
regex.icontainsregexcharCodeAt
regex.icontainsregex(\\x0.*?){50}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                .scan.entropy.entropy >= 5\n                and any(.scan.strings.strings,\n                        regex.icontains(., \"fromCharCode\")\n                        and regex.icontains(., \"parseInt\")\n                        and regex.icontains(., \"charCodeAt\")\n                        and regex.icontains(., '(\\\\x0.*?){50}')\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with raw array buffer

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, Free subdomain host, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.strings.strings,
                    // arrayBuffer, eg repetition:
                    // [0xa0,0x8e,0xd0,0x60,...]
                    regex.icontains(., '(\W?0x[a-zA-Z0-9]{2}\W?,\s*){100}')
                )
                and any(.scan.strings.strings, strings.contains(., ".map"))
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, // arrayBuffer, eg repetition: // [0xa0,0x8e,0xd0,0x60,...] regex.icontains(., '(\W?0x[a-zA-Z0-9]{2}\W?,\s*){100}') ) and any(.scan.strings.strings, strings.contains(., ".map")) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.icontains, strings.contains. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
regex.icontainsregex(\W?0x[a-zA-Z0-9]{2}\W?,\s*){100}
strings.containssubstring.map

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    // arrayBuffer, eg repetition:\n                    // [0xa0,0x8e,0xd0,0x60,...]\n                    regex.icontains(., '(\\W?0x[a-zA-Z0-9]{2}\\W?,\\s*){100}')\n                )\n                and any(.scan.strings.strings, strings.contains(., \".map\"))\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with RC4 decryption

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

Potential HTML smuggling. The RC4 algorithm is used within inline JavaScript to decrypt the payload on-the-fly.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEncryption, Evasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.strings.strings,
                    strings.ilike(., "*?[(?[?]+?[?])%256]*")
                )
        )
)

Detection Logic

Scope: inbound message.

Potential HTML smuggling. The RC4 algorithm is used within inline JavaScript to decrypt the payload on-the-fly.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., "*?[(?[?]+?[?])%256]*") ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
strings.ilikesubstring*?[(?[?]+?[?])%256]*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    strings.ilike(., \"*?[(?[?]+?[?])%256]*\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with ROT13

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

Potential HTML obfuscation attack based on suspicious JavaScript identifiers. Some attackers may use obfuscation techniques such as ROT13 to bypass email security filters. This rule may be expanded to inspect HTML attachments for other suspicious identifiers.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEncryption, Evasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_extension in~ $file_extensions_common_archives
          or .file_type in~ ("html", "svg")
        )
        and any(file.explode(.),
                1 of (
                  any(.scan.javascript.identifiers,
                      . in~ ("rot13", "decodeROT13")
                  ),
                  any(.scan.strings.strings,
                      // ROT13 encoded value for https & http
                      strings.icontains(., "\"uggcf://")
                      or strings.icontains(., "\"uggc://")
                  )
                )
                and length(.scan.javascript.identifiers) < 100
        )
)

Detection Logic

Scope: inbound message.

Potential HTML obfuscation attack based on suspicious JavaScript identifiers. Some attackers may use obfuscation techniques such as ROT13 to bypass email security filters. This rule may be expanded to inspect HTML attachments for other suspicious identifiers.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type in ('html', 'svg')
    • any(file.explode(.), 1 of ( any(.scan.javascript.identifiers, . in~ ("rot13", "decodeROT13") ), any(.scan.strings.strings, // ROT13 encoded value for https & http strings.icontains(., "\"uggcf://") or strings.icontains(., "\"uggc://") ) ) and length(.scan.javascript.identifiers) < 100 )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.icontains. Reference lists: $file_extensions_common_archives.

Indicators Matched (10)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typememberhtml
attachments[].file_typemembersvg
file.explode(attachments[])[].scan.javascript.identifiers[]memberrot13
file.explode(attachments[])[].scan.javascript.identifiers[]memberdecodeROT13
strings.icontainssubstring\"uggcf://
strings.icontainssubstring\"uggc://

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type in ["html", "svg"]
       macro "any(file.explode(.),\n                1 of (\n                  any(.scan.javascript.identifiers,\n                      . in~ (\"rot13\", \"decodeROT13\")\n                  ),\n                  any(.scan.strings.strings,\n                      // ROT13 encoded value for https & http\n                      strings.icontains(., \"\\\"uggcf://\")\n                      or strings.icontains(., \"\\\"uggc://\")\n                  )\n                )\n                and length(.scan.javascript.identifiers) < 100\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with setTimeout

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .size <= 400
        and (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
        )
        and any(file.explode(.),
                "setTimeout" in .scan.javascript.identifiers
                and any(.scan.strings.strings,
                        strings.ilike(., "*location.href*")
                )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • .size ≤ 400
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), "setTimeout" in .scan.javascript.identifiers and any(.scan.strings.strings, strings.ilike(., "*location.href*") ) )

Inspects: attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].scan.javascript.identifierscontainssetTimeout
strings.ilikesubstring*location.href*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
      attachments.size le "400"
       macro "any(file.explode(.),\n                \"setTimeout\" in .scan.javascript.identifiers\n                and any(.scan.strings.strings,\n                        strings.ilike(., \"*location.href*\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML smuggling with unescape

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

Recursively scans files and archives to detect HTML smuggling techniques.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
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(.),
                any(.scan.javascript.identifiers, . == "unescape")
                or any(.scan.strings.strings,
                       regex.contains(., "document.write.{0,10}unescape")
                )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect HTML smuggling techniques.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
    • any(file.explode(.), any(.scan.javascript.identifiers, . == "unescape") or any(.scan.strings.strings, regex.contains(., "document.write.{0,10}unescape") ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, regex.contains. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
file.explode(attachments[])[].scan.javascript.identifiers[]equalsunescape
regex.containsregexdocument.write.{0,10}unescape

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
       macro "any(file.explode(.),\n                any(.scan.javascript.identifiers, . == \"unescape\")\n                or any(.scan.strings.strings,\n                       regex.contains(., \"document.write.{0,10}unescape\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: HTML with emoji-to-character map

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

Detects inbound messages containing HTML attachments with an unusually high number of emojis in a list, sent from untrusted or suspicious senders who lack an established sending history or have previous malicious behavior.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, HTML smuggling, Impersonation: Brand, Scripting, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml")
          or .file_type == "html"
          or .content_type in ("application/octet-stream", "text/html")
        )
        and regex.icount(file.parse_html(.).raw,
                         '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}].{0,10},'
        ) > 10
)
and (
  (
    profile.by_sender().prevalence in ("new", "outlier")
    and not profile.by_sender().solicited
  )
  or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing HTML attachments with an unusually high number of emojis in a list, sent from untrusted or suspicious senders who lack an established sending history or have previous malicious behavior.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
      • .file_type is 'html'
      • .content_type in ('application/octet-stream', 'text/html')
    • regex.icount(file.parse_html(.).raw, '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}].{0,10},' ) > 10
  3. any of:
    • all of:
      • profile.by_sender().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender().solicited
    • profile.by_sender().any_messages_malicious_or_spam
  4. not:
    • profile.by_sender().any_messages_benign
  5. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.parse_html, profile.by_sender, regex.icount. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (8)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_typeequalshtml
attachments[].content_typememberapplication/octet-stream
attachments[].content_typemembertext/html
regex.icountregex[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}].{0,10},

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/octet-stream", "text/html"]
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
      regex.icount func_call "regex.icount(file.parse_html(.).raw,\n                         '[\\x{1F300}-\\x{1F5FF}\\x{1F600}-\\x{1F64F}\\x{1F680}-\\x{1F6FF}\\x{1F700}-\\x{1F77F}\\x{1F780}-\\x{1F7FF}\\x{1F900}-\\x{1F9FF}\\x{2600}-\\x{26FF}\\x{2700}-\\x{27BF}\\x{2300}-\\x{23FF}].{0,10},'\n        ) > 10"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().solicited"
      profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
    profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: HTML with hidden body

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

This rule identifies HTML attachments which begin directly with a hidden body element. This has been observed in phishing campaigns to hide the content of an otherwise benign HTML attachment that then has remote content injected into the body.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and not profile.by_sender().solicited
// not high trust sender domains
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and any(attachments,
        .file_extension == "html"
        // starts with the hidden body element
        and regex.icontains(file.parse_html(.).raw,
                            '^<body style\s*=\s*"\s*display\s*:\s*none\s*;\s*">'
        )
)

Detection Logic

Scope: inbound message.

This rule identifies HTML attachments which begin directly with a hidden body element. This has been observed in phishing campaigns to hide the content of an otherwise benign HTML attachment that then has remote content injected into the body.

  1. inbound message
  2. not:
    • profile.by_sender().solicited
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  4. any of attachments where all hold:
    • .file_extension is 'html'
    • regex.icontains(file.parse_html(.).raw, '^<body style\s*=\s*"\s*display\s*:\s*none\s*;\s*">' )

Inspects: attachments[].file_extension, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.parse_html, profile.by_sender, regex.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalshtml
regex.icontainsregex^<body style\s*=\s*"\s*display\s*:\s*none\s*;\s*">

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  any(attachments)
    and
      attachments.file_extension eq "html"
      regex.icontains func_call "regex.icontains(file.parse_html(.).raw,\n                            '^<body style\\s*=\\s*\"\\s*display\\s*:\\s*none\\s*;\\s*\">'\n        )"
  not
    profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

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"

Attachment: HTML with JavaScript functions for HTTP requests

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

This rule identifies HTML attachments which contain multiple references to JavaScript functions that support making HTTP requests. This has been observed in phishing campaigns to load remote payloads into otherwise benign HTML attachments.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and not profile.by_sender().solicited
// not high trust sender domains
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and any(attachments,
        .file_extension in~ ("html", "htm", "shtml", "dhtml")
        and 3 of (
          strings.icontains(file.parse_html(.).raw, '.replace'),
          strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest'),
          strings.icontains(file.parse_html(.).raw, 'onreadystate'),
          strings.icontains(file.parse_html(.).raw, 'GET'),
          strings.icontains(file.parse_html(.).raw, 'send()'),
          strings.icontains(file.parse_html(.).raw, 'responseText'),
        )
)

Detection Logic

Scope: inbound message.

This rule identifies HTML attachments which contain multiple references to JavaScript functions that support making HTTP requests. This has been observed in phishing campaigns to load remote payloads into otherwise benign HTML attachments.

  1. inbound message
  2. not:
    • profile.by_sender().solicited
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  4. any of attachments where all hold:
    • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
    • at least 3 of:
      • strings.icontains(file.parse_html(.).raw, '.replace')
      • strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')
      • strings.icontains(file.parse_html(.).raw, 'onreadystate')
      • strings.icontains(file.parse_html(.).raw, 'GET')
      • strings.icontains(file.parse_html(.).raw, 'send()')
      • strings.icontains(file.parse_html(.).raw, 'responseText')

Inspects: attachments[].file_extension, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.parse_html, profile.by_sender, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (10)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
strings.icontainssubstring.replace
strings.icontainssubstringXMLHttpRequest
strings.icontainssubstringonreadystate
strings.icontainssubstringGET
strings.icontainssubstringsend()
strings.icontainssubstringresponseText

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, '.replace')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'GET')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'XMLHttpRequest')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
        and
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'onreadystate')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'responseText')"
          strings.icontains func_call "strings.icontains(file.parse_html(.).raw, 'send()')"
      attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    profile.by_sender func_call "profile.by_sender().solicited"
  type.inbound eq "true"

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"

Attachment: HTML with obfuscation and recipient's email in JavaScript strings

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

Attached HTML file contains JavaScript code with suspicious identifiers like 'atob' or 'decrypt', as well as the recipient's email address embedded within the JavaScript

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesHTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("html", "htm", "shtml", "dhtml", "xhtml")
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
          )
          or .file_extension in~ $file_extensions_common_archives
          or .file_type == "html"
          or .content_type == "text/html"
        )
        and .size < 1000000
        and any(file.explode(.),
                // suspicious identifiers
                any([.scan.strings.strings, .scan.javascript.identifiers],
                    any(., strings.like(., "*atob*", "*decrypt*"))
                )
        )
        // Recipients address found in javascript
        and any(file.explode(.),
                (
                  any(recipients.to,
                      (
                        any(..scan.javascript.strings,
                            strings.icontains(., ..email.email)
                        )
                        or any(..scan.strings.strings,
                               strings.icontains(., ..email.email)
                        )
                      )
                      and (
                        .email.domain.valid
                        or strings.icontains(.display_name, "undisclosed")
                      )
                  )
                )
        )
        // Negating Cisco Secure Email Encryption
        and not any(file.explode(.),
                    any(.scan.javascript.strings,
                        strings.contains(., "Cisco Registered Envelope Service")
                        or strings.contains(., "https://res.cisco.com:443")
                    )
        )
        // Negating SolarWinds Kiwi Syslog server email reports
        and not any(file.explode(.),
                    length(.scan.url.urls) > 0
                    and all(.scan.url.urls,
                            strings.contains(.domain.root_domain,
                                             "kiwisyslog.com"
                            )
                    )
        )
)

Detection Logic

Scope: inbound message.

Attached HTML file contains JavaScript code with suspicious identifiers like 'atob' or 'decrypt', as well as the recipient's email address embedded within the JavaScript

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('html', 'htm', 'shtml', 'dhtml', 'xhtml')
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'html'
      • .content_type is 'text/html'
    • .size < 1000000
    • any(file.explode(.), // suspicious identifiers any([.scan.strings.strings, .scan.javascript.identifiers], any(., strings.like(., "*atob*", "*decrypt*")) ) )
    • any(file.explode(.), ( any(recipients.to, ( any(..scan.javascript.strings, strings.icontains(., ..email.email) ) or any(..scan.strings.strings, strings.icontains(., ..email.email) ) ) and ( .email.domain.valid or strings.icontains(.display_name, "undisclosed") ) ) ) )
    • not:
      • any(file.explode(.), any(.scan.javascript.strings, strings.contains(., "Cisco Registered Envelope Service") or strings.contains(., "https://res.cisco.com:443") ) )
    • not:
      • any(file.explode(.), length(.scan.url.urls) > 0 and all(.scan.url.urls, strings.contains(.domain.root_domain, "kiwisyslog.com" ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, recipients.to, recipients.to[].display_name, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: file.explode, strings.contains, strings.icontains, strings.like. Reference lists: $file_extensions_common_archives.

Indicators Matched (12)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].file_extensionmemberxhtml
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
strings.likesubstring*atob*
strings.likesubstring*decrypt*
strings.icontainssubstringundisclosed

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml", "xhtml"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "html"
      not
         macro "any(file.explode(.),\n                    any(.scan.javascript.strings,\n                        strings.contains(., \"Cisco Registered Envelope Service\")\n                        or strings.contains(., \"https://res.cisco.com:443\")\n                    )\n        )"
      not
         macro "any(file.explode(.),\n                    length(.scan.url.urls) > 0\n                    and all(.scan.url.urls,\n                            strings.contains(.domain.root_domain,\n                                             \"kiwisyslog.com\"\n                            )\n                    )\n        )"
      attachments.size lt "1000000"
       macro "any(file.explode(.),\n                (\n                  any(recipients.to,\n                      (\n                        any(..scan.javascript.strings,\n                            strings.icontains(., ..email.email)\n                        )\n                        or any(..scan.strings.strings,\n                               strings.icontains(., ..email.email)\n                        )\n                      )\n                      and (\n                        .email.domain.valid\n                        or strings.icontains(.display_name, \"undisclosed\")\n                      )\n                  )\n                )\n        )"
       macro "any(file.explode(.),\n                // suspicious identifiers\n                any([.scan.strings.strings, .scan.javascript.identifiers],\n                    any(., strings.like(., \"*atob*\", \"*decrypt*\"))\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: ICS calendar file with base64 encoded recipient address in URL parameters

#

Attachment: ICS calendar file with QR code containing recipient email address

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

Detects calendar attachments (.ics files) containing QR codes that include the recipient's email address in the URL, URL fragment, or base64-encoded data. This technique is commonly used to personalize credential theft attacks by embedding the target's email address within calendar invitations.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to[0]
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or (
            .file_extension == "ics"
            or .content_type in ("application/ics", "text/calendar")
          )
        )
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and any(beta.file.parse_ics(.).events,
                //
                // This rule makes use of a beta feature and is subject to change without notice
                // using the beta feature in custom rules is not suggested until it has been formally released
                //
                any(beta.scan_qr(file.html_screenshot(.description_html)).items,
                    strings.icontains(.url.url, recipients.to[0].email.email)
                    or any(strings.scan_base64(.url.url, format="url"),
                           strings.icontains(., recipients.to[0].email.email)
                    )
                    or any(strings.scan_base64(.url.fragment),
                           strings.icontains(., recipients.to[0].email.email)
                    )
                )
        )
)

Detection Logic

Scope: inbound message.

Detects calendar attachments (.ics files) containing QR codes that include the recipient's email address in the URL, URL fragment, or base64-encoded data. This technique is commonly used to personalize credential theft attacks by embedding the target's email address within calendar invitations.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'ics'
      • any of:
        • .file_extension is 'ics'
        • .content_type in ('application/ics', 'text/calendar')
    • any(beta.file.parse_ics(.).events, // // This rule makes use of a beta feature and is subject to change without notice // using the beta feature in custom rules is not suggested until it has been formally released // any(beta.scan_qr(file.html_screenshot(.description_html)).items, strings.icontains(.url.url, recipients.to[0].email.email) or any(strings.scan_base64(.url.url, format="url"), strings.icontains(., recipients.to[0].email.email) ) or any(strings.scan_base64(.url.fragment), strings.icontains(., recipients.to[0].email.email) ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, recipients.to[0].email.email, type.inbound. Sensors: beta.file.parse_ics, beta.scan_qr, file.html_screenshot, strings.icontains, strings.scan_base64.

Indicators Matched (4)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
       macro "any(beta.file.parse_ics(.).events,\n                //\n                // This rule makes use of a beta feature and is subject to change without notice\n                // using the beta feature in custom rules is not suggested until it has been formally released\n                //\n                any(beta.scan_qr(file.html_screenshot(.description_html)).items,\n                    strings.icontains(.url.url, recipients.to[0].email.email)\n                    or any(strings.scan_base64(.url.url, format=\"url\"),\n                           strings.icontains(., recipients.to[0].email.email)\n                    )\n                    or any(strings.scan_base64(.url.fragment),\n                           strings.icontains(., recipients.to[0].email.email)\n                    )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: ICS calendar file with recipient address in UID field

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

Detects inbound messages containing ICS calendar attachments where the UID property matches the recipient's email address, indicating potential calendar-based social engineering.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesSocial engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to[0]
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or (
            .file_extension == "ics"
            or .content_type in ("application/ics", "text/calendar")
          )
        )
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and any(beta.file.parse_ics(.).events,
                any(.raw_properties,
                    .key == "UID" and .value == recipients.to[0].email.email
                )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing ICS calendar attachments where the UID property matches the recipient's email address, indicating potential calendar-based social engineering.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'ics'
      • any of:
        • .file_extension is 'ics'
        • .content_type in ('application/ics', 'text/calendar')
    • any(beta.file.parse_ics(.).events, any(.raw_properties, .key == "UID" and .value == recipients.to[0].email.email ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, recipients.to[0].email.email, type.inbound. Sensors: beta.file.parse_ics.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
beta.file.parse_ics(attachments[]).events[].raw_properties[].keyequalsUID

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
       macro "any(beta.file.parse_ics(.).events,\n                any(.raw_properties,\n                    .key == \"UID\" and .value == recipients.to[0].email.email\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: ICS calendar file with suspicious product identifier

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

Detects inbound messages containing ICS calendar attachments that have product identifiers matching patterns commonly associated with malicious calendar invitations. The rule identifies ICS files through multiple detection methods and analyzes the product_id field for suspicious formatting that may indicate automated generation or spoofing attempts.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Social engineering, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and (
          regex.icontains(beta.file.parse_ics(.).product_id,
                          '-//[a-z0-9]*[0-9][a-z0-9]*//EN'
          )
          or strings.icontains(beta.file.parse_ics(.).product_id,
                               "-//MyApp//example.com//",
                               "-//My App//NS9 Calendar//EN",
                               "-//SharePoint//NONSGML v1.0//EN",
                               "-//YourCassavaLtd//EateriesDept//EN",
                               "-//Your App//EN",
                               "-//Organization//EN",
                               "-//Calendar Auto//EN",
                               "-Meeting Schedule",
                               "-//JANSANI//Email Engine v12.7//EN",
                               "-Event Mandate",
                               "-//CalendarInviteBuilder//EN",
                               "-//CustomMailer//EN",
                               "Trafft",
                               "-//caldav.icloud.com//CALDAVJ 2620B879//EN",
                               "-//Calendar Event//EN",
                               "-//dilmar//EN",
                               "-//First Dips//Portal//EN",
                               "-//X7fG3//Y2kL9//M9nP4 16.0 MIMEDIR//EN",
                               "-//HRNotify//CompChange 1.0//EN",
                               "-//Prof Morales Sender//EN",
                               "//NONSGML Event//EN"
          )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing ICS calendar attachments that have product identifiers matching patterns commonly associated with malicious calendar invitations. The rule identifies ICS files through multiple detection methods and analyzes the product_id field for suspicious formatting that may indicate automated generation or spoofing attempts.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'ics'
      • .file_extension is 'ics'
      • .content_type in ('application/ics', 'text/calendar')
    • any of:
      • regex.icontains(beta.file.parse_ics(.).product_id, '-//[a-z0-9]*[0-9][a-z0-9]*//EN' )
      • strings.icontains(beta.file.parse_ics(.).product_id, "-//MyApp//example.com//", "-//My App//NS9 Calendar//EN", "-//SharePoint//NONSGML v1.0//EN", "-//YourCassavaLtd//EateriesDept//EN", "-//Your App//EN", "-//Organization//EN", "-//Calendar Auto//EN", "-Meeting Schedule", "-//JANSANI//Email Engine v12.7//EN", "-Event Mandate", "-//CalendarInviteBuilder//EN", "-//CustomMailer//EN", "Trafft", "-//caldav.icloud.com//CALDAVJ 2620B879//EN", "-//Calendar Event//EN", "-//dilmar//EN", "-//First Dips//Portal//EN", "-//X7fG3//Y2kL9//M9nP4 16.0 MIMEDIR//EN", "-//HRNotify//CompChange 1.0//EN", "-//Prof Morales Sender//EN", "//NONSGML Event//EN" )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: beta.file.parse_ics, regex.icontains, strings.icontains.

Indicators Matched (26)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
regex.icontainsregex-//[a-z0-9]*[0-9][a-z0-9]*//EN
strings.icontainssubstring-//MyApp//example.com//
strings.icontainssubstring-//My App//NS9 Calendar//EN
strings.icontainssubstring-//SharePoint//NONSGML v1.0//EN
strings.icontainssubstring-//YourCassavaLtd//EateriesDept//EN
strings.icontainssubstring-//Your App//EN
strings.icontainssubstring-//Organization//EN
strings.icontainssubstring-//Calendar Auto//EN
14 more
strings.icontainssubstring-Meeting Schedule
strings.icontainssubstring-//JANSANI//Email Engine v12.7//EN
strings.icontainssubstring-Event Mandate
strings.icontainssubstring-//CalendarInviteBuilder//EN
strings.icontainssubstring-//CustomMailer//EN
strings.icontainssubstringTrafft
strings.icontainssubstring-//caldav.icloud.com//CALDAVJ 2620B879//EN
strings.icontainssubstring-//Calendar Event//EN
strings.icontainssubstring-//dilmar//EN
strings.icontainssubstring-//First Dips//Portal//EN
strings.icontainssubstring-//X7fG3//Y2kL9//M9nP4 16.0 MIMEDIR//EN
strings.icontainssubstring-//HRNotify//CompChange 1.0//EN
strings.icontainssubstring-//Prof Morales Sender//EN
strings.icontainssubstring//NONSGML Event//EN

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
      or
        regex.icontains func_call "regex.icontains(beta.file.parse_ics(.).product_id,\n                          '-//[a-z0-9]*[0-9][a-z0-9]*//EN'\n          )"
        strings.icontains func_call "strings.icontains(beta.file.parse_ics(.).product_id,\n                               \"-//MyApp//example.com//\",\n                               \"-//My App//NS9 Calendar//EN\",\n                               \"-//SharePoint//NONSGML v1.0//EN\",\n                               \"-//YourCassavaLtd//EateriesDept//EN\",\n                               \"-//Your App//EN\",\n                               \"-//Organization//EN\",\n                               \"-//Calendar Auto//EN\",\n                               \"-Meeting Schedule\",\n                               \"-//JANSANI//Email Engine v12.7//EN\",\n                               \"-Event Mandate\",\n                               \"-//CalendarInviteBuilder//EN\",\n                               \"-//CustomMailer//EN\",\n                               \"Trafft\",\n                               \"-//caldav.icloud.com//CALDAVJ 2620B879//EN\",\n                               \"-//Calendar Event//EN\",\n                               \"-//dilmar//EN\",\n                               \"-//First Dips//Portal//EN\",\n                               \"-//X7fG3//Y2kL9//M9nP4 16.0 MIMEDIR//EN\",\n                               \"-//HRNotify//CompChange 1.0//EN\",\n                               \"-//Prof Morales Sender//EN\",\n                               \"//NONSGML Event//EN\"\n          )"
  type.inbound eq "true"

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"

Attachment: ICS calendar file with suspicious UID domain

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

Detects inbound messages containing ICS calendar attachments where the event UID property ends with a specific domain (@example.com). Malicious actors may use calendar invites to socially engineer recipients into accepting fraudulent meetings or following malicious instructions embedded in calendar events.

Threat Classification

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

CategoryValues
Attack typesICS Phishing, Credential Phishing, BEC/Fraud
Tactics and techniquesSocial engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and any(beta.file.parse_ics(.).events,
                any(.raw_properties,
                    .key == "UID" and strings.iends_with(.value, "@example.com")
                )
        )
)    

Detection Logic

Scope: inbound message.

Detects inbound messages containing ICS calendar attachments where the event UID property ends with a specific domain (@example.com). Malicious actors may use calendar invites to socially engineer recipients into accepting fraudulent meetings or following malicious instructions embedded in calendar events.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'ics'
      • .file_extension is 'ics'
      • .content_type in ('application/ics', 'text/calendar')
    • any(beta.file.parse_ics(.).events, any(.raw_properties, .key == "UID" and strings.iends_with(.value, "@example.com") ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: beta.file.parse_ics, strings.iends_with.

Indicators Matched (6)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
beta.file.parse_ics(attachments[]).events[].raw_properties[].keyequalsUID
strings.iends_withsuffix@example.com

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
       macro "any(beta.file.parse_ics(.).events,\n                any(.raw_properties,\n                    .key == \"UID\" and strings.iends_with(.value, \"@example.com\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: ICS calendar invite with bid/RFP lure and suspicious link

#

Attachment: ICS calendar invite with financial lure and suspicious link

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

Detects inbound emails containing ICS calendar attachments whose event descriptions reference credit notes, billing adjustments, or invoice reconciliation language, combined with body links pointing to URL shorteners, suspicious TLDs, newly registered domains, free file hosts, or self-service platforms that do not match the sender's domain. Excludes messages from high-trust sender domains that pass DMARC authentication.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, BEC/Fraud
Tactics and techniquesSocial engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.links
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and any(beta.file.parse_ics(.).events,
                regex.icontains(.description,
                                'credit\s+note.{0,30}CN-[0-9]{8}',
                                '(?:review|issued?).{0,30}credit\s+note',
                                'credit.{0,20}(?:has\s+been\s+)?issued.{0,30}(?:invoice|billing|pricing\s+adjustment)',
                                '(?:billing|accounting)\s+(?:review|adjustment|reconciliation).{0,30}credit',
                                'investment\s+drawdown',
                                'reimbursement\s+statement',
                                'e-?document\s+reports?'
                )
        )
)
and any(body.links,
        .href_url.domain.root_domain != sender.email.domain.root_domain
        and (
          .href_url.domain.domain in $url_shorteners
          or .href_url.domain.root_domain in $url_shorteners
          or .href_url.domain.tld in $suspicious_tlds
          or network.whois(.href_url.domain).days_old < 90
          or .href_url.domain.root_domain in $free_file_hosts
          or .href_url.domain.domain in $free_file_hosts
          or .href_url.domain.root_domain in $self_service_creation_platform_domains
          or .href_url.domain.domain in $self_service_creation_platform_domains
        )
)
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.

Detects inbound emails containing ICS calendar attachments whose event descriptions reference credit notes, billing adjustments, or invoice reconciliation language, combined with body links pointing to URL shorteners, suspicious TLDs, newly registered domains, free file hosts, or self-service platforms that do not match the sender's domain. Excludes messages from high-trust sender domains that pass DMARC authentication.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'ics'
      • .file_extension is 'ics'
      • .content_type in ('application/ics', 'text/calendar')
    • any(beta.file.parse_ics(.).events, regex.icontains(.description, 'credit\s+note.{0,30}CN-[0-9]{8}', '(?:review|issued?).{0,30}credit\s+note', 'credit.{0,20}(?:has\s+been\s+)?issued.{0,30}(?:invoice|billing|pricing\s+adjustment)', '(?:billing|accounting)\s+(?:review|adjustment|reconciliation).{0,30}credit', 'investment\s+drawdown', 'reimbursement\s+statement', 'e-?document\s+reports?' ) )
  3. any of body.links where all hold:
    • .href_url.domain.root_domain is not sender.email.domain.root_domain
    • any of:
      • .href_url.domain.domain in $url_shorteners
      • .href_url.domain.root_domain in $url_shorteners
      • .href_url.domain.tld in $suspicious_tlds
      • network.whois(.href_url.domain).days_old < 90
      • .href_url.domain.root_domain in $free_file_hosts
      • .href_url.domain.domain in $free_file_hosts
      • .href_url.domain.root_domain in $self_service_creation_platform_domains
      • .href_url.domain.domain in $self_service_creation_platform_domains
  4. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, body.links, body.links[].href_url.domain, body.links[].href_url.domain.domain, body.links[].href_url.domain.root_domain, body.links[].href_url.domain.tld, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.file.parse_ics, network.whois, regex.icontains. Reference lists: $free_file_hosts, $high_trust_sender_root_domains, $self_service_creation_platform_domains, $suspicious_tlds, $url_shorteners.

Indicators Matched (11)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
regex.icontainsregexcredit\s+note.{0,30}CN-[0-9]{8}
regex.icontainsregex(?:review|issued?).{0,30}credit\s+note
regex.icontainsregexcredit.{0,20}(?:has\s+been\s+)?issued.{0,30}(?:invoice|billing|pricing\s+adjustment)
regex.icontainsregex(?:billing|accounting)\s+(?:review|adjustment|reconciliation).{0,30}credit
regex.icontainsregexinvestment\s+drawdown
regex.icontainsregexreimbursement\s+statement
regex.icontainsregexe-?document\s+reports?

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
       macro "any(beta.file.parse_ics(.).events,\n                regex.icontains(.description,\n                                'credit\\s+note.{0,30}CN-[0-9]{8}',\n                                '(?:review|issued?).{0,30}credit\\s+note',\n                                'credit.{0,20}(?:has\\s+been\\s+)?issued.{0,30}(?:invoice|billing|pricing\\s+adjustment)',\n                                '(?:billing|accounting)\\s+(?:review|adjustment|reconciliation).{0,30}credit',\n                                'investment\\s+drawdown',\n                                'reimbursement\\s+statement',\n                                'e-?document\\s+reports?'\n                )\n        )"
  any(body.links)
    and
      or
        body.links.href_url.domain.domain macro "body.links[].href_url.domain.domain in free_file_hosts"
        body.links.href_url.domain.domain macro "body.links[].href_url.domain.domain in self_service_creation_platform_domains"
        body.links.href_url.domain.domain macro "body.links[].href_url.domain.domain in url_shorteners"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain in free_file_hosts"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain in self_service_creation_platform_domains"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain in url_shorteners"
        body.links.href_url.domain.tld macro "body.links[].href_url.domain.tld in suspicious_tlds"
        network.whois func_call "network.whois(.href_url.domain).days_old < 90"
      body.links.href_url.domain.root_domain cross_field_compare "sender.email.domain.root_domain"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: ICS calendar with embedded file from internal sender with SPF failure

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

Detects calendar invitations (ICS files) from internal domains that fail SPF authentication and contain embedded attachments, with single attendee and organizer both from organizational domains.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesSpoofing, Evasion, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and sender.email.domain.domain in $org_domains
and not coalesce(headers.auth_summary.dmarc.pass, false)
// has an ICS file
and any(attachments,
        .file_extension == "ics" or .content_type == "text/calendar"
)
// and a single other attachment that isn't an ICS but is embedded in the ICS
and length(filter(attachments,
                  not (
                    .file_extension == "ics"
                    or .content_type == "text/calendar"
                    or .file_type in $file_types_images
                  )
                  and any(filter(attachments,
                                 .file_extension == "ics"
                                 or .content_type == "text/calendar"
                          ),
                          strings.contains(file.parse_text(.).text,
                                           ..content_id
                          )
                  )
           )
) == 1
// exlode the ics file and look at the VEVENT file
and any(filter(attachments,
               .file_extension == "ics" or .content_type == "text/calendar"
        ),
        any(file.explode(.),
            // attendees and org are both within org_domains
            any(.scan.ics.calendars,
                any(.components,
                    .type == "VEVENT"
                    and length(.attendees) == 1
                    and all(.attendees,
                            .mailbox.email.domain.domain in $org_domains
                    )
                    and any(.organizers,
                            .mailbox.email.domain.domain in $org_domains
                    )
                    and length(.attachments) > 0
                    and all(.attachments,
                            .type == "uri" and strings.starts_with(.uri, "CID:")
                    )
                )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects calendar invitations (ICS files) from internal domains that fail SPF authentication and contain embedded attachments, with single attendee and organizer both from organizational domains.

  1. inbound message
  2. sender.email.domain.domain in $org_domains
  3. not:
    • coalesce(headers.auth_summary.dmarc.pass, false)
  4. any of attachments where any holds:
    • .file_extension is 'ics'
    • .content_type is 'text/calendar'
  5. length(filter(attachments, not ( .file_extension == "ics" or .content_type == "text/calendar" or .file_type in $file_types_images ) and any(filter(attachments, .file_extension == "ics" or .content_type == "text/calendar" ), strings.contains(file.parse_text(.).text, ..content_id ) ) ) ) == 1
  6. any(filter(attachments, .file_extension == "ics" or .content_type == "text/calendar" ), any(file.explode(.), // attendees and org are both within org_domains any(.scan.ics.calendars, any(.components, .type == "VEVENT" and length(.attendees) == 1 and all(.attendees, .mailbox.email.domain.domain in $org_domains ) and any(.organizers, .mailbox.email.domain.domain in $org_domains ) and length(.attachments) > 0 and all(.attachments, .type == "uri" and strings.starts_with(.uri, "CID:") ) ) ) ) )

Inspects: attachments[].content_id, attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.domain, type.inbound. Sensors: file.explode, file.parse_text, strings.contains, strings.starts_with. Reference lists: $file_types_images, $org_domains.

Indicators Matched (5)

FieldMatchValue
attachments[].file_extensionequalsics
attachments[].content_typeequalstext/calendar
file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].typeequalsVEVENT
file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].attachments[].typeequalsuri
strings.starts_withprefixCID:

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      attachments.content_type eq "text/calendar"
      attachments.file_extension eq "ics"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
  length func_call "length(filter(attachments,\n                  not (\n                    .file_extension == \"ics\"\n                    or .content_type == \"text/calendar\"\n                    or .file_type in $file_types_images\n                  )\n                  and any(filter(attachments,\n                                 .file_extension == \"ics\"\n                                 or .content_type == \"text/calendar\"\n                          ),\n                          strings.contains(file.parse_text(.).text,\n                                           ..content_id\n                          )\n                  )\n           )\n) == 1"
  sender.email.domain.domain macro "sender.email.domain.domain in org_domains"
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .file_extension == \"ics\" or .content_type == \"text/calendar\"\n        ),\n        any(file.explode(.),\n            // attendees and org are both within org_domains\n            any(.scan.ics.calendars,\n                any(.components,\n                    .type == \"VEVENT\"\n                    and length(.attendees) == 1\n                    and all(.attendees,\n                            .mailbox.email.domain.domain in $org_domains\n                    )\n                    and any(.organizers,\n                            .mailbox.email.domain.domain in $org_domains\n                    )\n                    and length(.attachments) > 0\n                    and all(.attachments,\n                            .type == \"uri\" and strings.starts_with(.uri, \"CID:\")\n                    )\n                )\n            )\n        )\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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: ICS file with AWS Lambda URL

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

Detects ICS calendar files that contain references to AWS Lambda URLs, which may be used to deliver malicious content or redirect users to suspicious resources.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, Free file host, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ('ics')
          or .content_type in ("application/ics", "text/calendar")
        )
        and (
          regex.icontains(file.parse_text(.).text, 'lambda-url')
          //
          // This rule makes use of a beta feature and is subject to change without notice
          // using the beta feature in custom rules is not suggested until it has been formally released
          //
          or any(beta.file.parse_ics(.).events,
                 any(.links,
                     strings.icontains(.href_url.domain.domain, "lambda-url")
                 )
          )
        )
)

Detection Logic

Scope: inbound message.

Detects ICS calendar files that contain references to AWS Lambda URLs, which may be used to deliver malicious content or redirect users to suspicious resources.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('ics')
      • .content_type in ('application/ics', 'text/calendar')
    • any of:
      • regex.icontains(file.parse_text(.).text, 'lambda-url')
      • any(beta.file.parse_ics(.).events, any(.links, strings.icontains(.href_url.domain.domain, "lambda-url") ) )

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: beta.file.parse_ics, file.parse_text, regex.icontains, strings.icontains.

Indicators Matched (5)

FieldMatchValue
attachments[].file_extensionmemberics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
regex.icontainsregexlambda-url
strings.icontainssubstringlambda-url

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
      or
        regex.icontains func_call "regex.icontains(file.parse_text(.).text, 'lambda-url')"
         macro "any(beta.file.parse_ics(.).events,\n                 any(.links,\n                     strings.icontains(.href_url.domain.domain, \"lambda-url\")\n                 )\n          )"
  type.inbound eq "true"

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"

Attachment: ICS file with credential theft indicators

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

Detects inbound emails containing calendar invite (.ics) attachments where the parsed event description is classified by NLU as having high-confidence credential theft intent and financial communication topics, and where embedded links point to domains that differ from the sender's domain and match known free file hosts, free subdomain hosts, self-service creation platforms, URL shorteners, suspicious TLDs, or newly registered domains (less than 90 days old).

Threat Classification

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

CategoryValues
Attack typesICS Phishing, Credential Phishing
Tactics and techniquesFree file host, Free subdomain host, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        and any(beta.file.parse_ics(.).events,
                any(ml.nlu_classifier(.description).intents,
                    .name == "cred_theft" and .confidence == "high"
                )
                and any(ml.nlu_classifier(.description).topics,
                        .name == "Financial Communications"
                        and .confidence == "high"
                )
                and any(.links,
                        .href_url.domain.root_domain != sender.email.domain.root_domain
                        and (
                          .href_url.domain.root_domain in $self_service_creation_platform_domains
                          or .href_url.domain.domain in $self_service_creation_platform_domains
                          or .href_url.domain.root_domain in $free_file_hosts
                          or .href_url.domain.domain in $free_file_hosts
                          or .href_url.domain.root_domain in $free_subdomain_hosts
                          or .href_url.domain.domain in $free_subdomain_hosts
                          or .href_url.domain.tld in $suspicious_tlds
                          or .href_url.domain.domain in $url_shorteners
                          or .href_url.domain.root_domain in $url_shorteners
                          or network.whois(.href_url.domain).days_old < 90
                        )
                )
        )
)
and not (
  strings.istarts_with(subject.base,
                       "accepted:",
                       "declined:",
                       "_accepted:",
                       "_declined:"
  )
)
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.

Detects inbound emails containing calendar invite (.ics) attachments where the parsed event description is classified by NLU as having high-confidence credential theft intent and financial communication topics, and where embedded links point to domains that differ from the sender's domain and match known free file hosts, free subdomain hosts, self-service creation platforms, URL shorteners, suspicious TLDs, or newly registered domains (less than 90 days old).

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'ics'
      • .file_extension is 'ics'
      • .content_type in ('application/ics', 'text/calendar')
    • any(beta.file.parse_ics(.).events, any(ml.nlu_classifier(.description).intents, .name == "cred_theft" and .confidence == "high" ) and any(ml.nlu_classifier(.description).topics, .name == "Financial Communications" and .confidence == "high" ) and any(.links, .href_url.domain.root_domain != sender.email.domain.root_domain and ( .href_url.domain.root_domain in $self_service_creation_platform_domains or .href_url.domain.domain in $self_service_creation_platform_domains or .href_url.domain.root_domain in $free_file_hosts or .href_url.domain.domain in $free_file_hosts or .href_url.domain.root_domain in $free_subdomain_hosts or .href_url.domain.domain in $free_subdomain_hosts or .href_url.domain.tld in $suspicious_tlds or .href_url.domain.domain in $url_shorteners or .href_url.domain.root_domain in $url_shorteners or network.whois(.href_url.domain).days_old < 90 ) ) )
  3. not:
    • subject.base starts with any of 4 patterns
      • accepted:
      • declined:
      • _accepted:
      • _declined:
  4. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, subject.base, type.inbound. Sensors: beta.file.parse_ics, ml.nlu_classifier, network.whois, strings.istarts_with. Reference lists: $free_file_hosts, $free_subdomain_hosts, $high_trust_sender_root_domains, $self_service_creation_platform_domains, $suspicious_tlds, $url_shorteners.

Indicators Matched (8)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
ml.nlu_classifier(beta.file.parse_ics(attachments[]).events[].description).intents[].nameequalscred_theft
ml.nlu_classifier(beta.file.parse_ics(attachments[]).events[].description).intents[].confidenceequalshigh
ml.nlu_classifier(beta.file.parse_ics(attachments[]).events[].description).topics[].nameequalsFinancial Communications
ml.nlu_classifier(beta.file.parse_ics(attachments[]).events[].description).topics[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
       macro "any(beta.file.parse_ics(.).events,\n                any(ml.nlu_classifier(.description).intents,\n                    .name == \"cred_theft\" and .confidence == \"high\"\n                )\n                and any(ml.nlu_classifier(.description).topics,\n                        .name == \"Financial Communications\"\n                        and .confidence == \"high\"\n                )\n                and any(.links,\n                        .href_url.domain.root_domain != sender.email.domain.root_domain\n                        and (\n                          .href_url.domain.root_domain in $self_service_creation_platform_domains\n                          or .href_url.domain.domain in $self_service_creation_platform_domains\n                          or .href_url.domain.root_domain in $free_file_hosts\n                          or .href_url.domain.domain in $free_file_hosts\n                          or .href_url.domain.root_domain in $free_subdomain_hosts\n                          or .href_url.domain.domain in $free_subdomain_hosts\n                          or .href_url.domain.tld in $suspicious_tlds\n                          or .href_url.domain.domain in $url_shorteners\n                          or .href_url.domain.root_domain in $url_shorteners\n                          or network.whois(.href_url.domain).days_old < 90\n                        )\n                )\n        )"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  not
    or
      subject.base starts_with "_accepted:"
      subject.base starts_with "_declined:"
      subject.base starts_with "accepted:"
      subject.base starts_with "declined:"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass
subject.basestarts_with_accepted:excludes:subject.base field:"subject.base" value:"_accepted:"
subject.basestarts_with_declined:excludes:subject.base field:"subject.base" value:"_declined:"
subject.basestarts_withaccepted:excludes:subject.base field:"subject.base" value:"accepted:"
subject.basestarts_withdeclined:excludes:subject.base field:"subject.base" value:"declined:"

Attachment: ICS file with excessive custom properties

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

ICS calendar attachment contains an unusually high number of custom X- properties, which may indicate attempts to hide malicious content or exploit calendar parsing vulnerabilities.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments,
               .file_type in~ ('ics')
               or .content_type in ("text/calendar", "application/ics")
        ),
        regex.icount(file.parse_text(.).text,
                     '[\r\n]X-[^\r\n]+\x3b\s?[^\r\n]+:\s*[a-f0-9]{32,}'
        ) > 10
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta feature in custom rules is not suggested until it has been formally released
        //
        or any(beta.file.parse_ics(.).events,
               length(filter(.raw_properties,
                             strings.istarts_with(.key, 'X-')
                             and regex.icontains(.value, '^[a-f0-9]{32,}$')
                      )
               ) > 10
        )
)

Detection Logic

Scope: inbound message.

ICS calendar attachment contains an unusually high number of custom X- properties, which may indicate attempts to hide malicious content or exploit calendar parsing vulnerabilities.

  1. inbound message
  2. any(filter(attachments, .file_type in~ ('ics') or .content_type in ("text/calendar", "application/ics") ), regex.icount(file.parse_text(.).text, '[\r\n]X-[^\r\n]+\x3b\s?[^\r\n]+:\s*[a-f0-9]{32,}' ) > 10 // // This rule makes use of a beta feature and is subject to change without notice // using the beta feature in custom rules is not suggested until it has been formally released // or any(beta.file.parse_ics(.).events, length(filter(.raw_properties, strings.istarts_with(.key, 'X-') and regex.icontains(.value, '^[a-f0-9]{32,}$') ) ) > 10 ) )

Inspects: attachments[].content_type, attachments[].file_type, type.inbound. Sensors: beta.file.parse_ics, file.parse_text, regex.icontains, regex.icount, strings.istarts_with.

Indicators Matched (6)

FieldMatchValue
attachments[].file_typememberics
attachments[].content_typemembertext/calendar
attachments[].content_typememberapplication/ics
regex.icountregex[\r\n]X-[^\r\n]+\x3b\s?[^\r\n]+:\s*[a-f0-9]{32,}
strings.istarts_withprefixX-
regex.icontainsregex^[a-f0-9]{32,}$

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .file_type in~ ('ics')\n               or .content_type in (\"text/calendar\", \"application/ics\")\n        ),\n        regex.icount(file.parse_text(.).text,\n                     '[\\r\\n]X-[^\\r\\n]+\\x3b\\s?[^\\r\\n]+:\\s*[a-f0-9]{32,}'\n        ) > 10\n        //\n        // This rule makes use of a beta feature and is subject to change without notice\n        // using the beta feature in custom rules is not suggested until it has been formally released\n        //\n        or any(beta.file.parse_ics(.).events,\n               length(filter(.raw_properties,\n                             strings.istarts_with(.key, 'X-')\n                             and regex.icontains(.value, '^[a-f0-9]{32,}$')\n                      )\n               ) > 10\n        )\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"

Attachment: ICS file with links to newly registered domains

#

Attachment: ICS file with meeting prefix

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

Detects incoming messages with a single ICS calendar file attachment that has a filename starting with 'meeting_'.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesICS Phishing, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(attachments) == 1
and any(filter(attachments,
               .file_extension in~ ('ics')
               or .content_type in ("application/ics", "text/calendar")
        ),
        regex.icontains(.file_name, 'meeting_[a-zA-Z0-9]{5}\.')
)

Detection Logic

Scope: inbound message.

Detects incoming messages with a single ICS calendar file attachment that has a filename starting with 'meeting_'.

  1. inbound message
  2. length(attachments) == 1
  3. any(filter(attachments, .file_extension in~ ('ics') or .content_type in ("application/ics", "text/calendar") ), regex.icontains(.file_name, 'meeting_[a-zA-Z0-9]{5}\.') )

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: regex.icontains.

Indicators Matched (4)

FieldMatchValue
attachments[].file_extensionmemberics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
regex.icontainsregexmeeting_[a-zA-Z0-9]{5}\.

Stages and Predicates

Stage 1: mql_rule

and
  attachments length_compare "1"
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .file_extension in~ ('ics')\n               or .content_type in (\"application/ics\", \"text/calendar\")\n        ),\n        regex.icontains(.file_name, 'meeting_[a-zA-Z0-9]{5}\\.')\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"

Attachment: ICS file with non-Gregorian calendar scale

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

Detects ICS calendar attachments that use a non-standard calendar scale other than GREGORIAN, which may indicate malicious calendar files attempting to exploit calendar parsing vulnerabilities or bypass security filters.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ('ics')
          or .content_type in ("application/ics", "text/calendar")
        )
        and not strings.icontains(beta.file.parse_ics(.).scale, 'GREGORIAN')
)

Detection Logic

Scope: inbound message.

Detects ICS calendar attachments that use a non-standard calendar scale other than GREGORIAN, which may indicate malicious calendar files attempting to exploit calendar parsing vulnerabilities or bypass security filters.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('ics')
      • .content_type in ('application/ics', 'text/calendar')
    • not:
      • strings.icontains(beta.file.parse_ics(.).scale, 'GREGORIAN')

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: beta.file.parse_ics, strings.icontains.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionmemberics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
      not
        strings.icontains func_call "strings.icontains(beta.file.parse_ics(.).scale, 'GREGORIAN')"
  type.inbound eq "true"

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"

Attachment: ICS invite meeting lure

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

Detects inbound messages carrying an .ics calendar attachment that impersonate meeting invites, referencing dial-in details such as PIN resets, local numbers, or conference IDs. These messages include a tracked link redirecting through the sender's own domain (e.g. /ls/click) and use generic, template-style subject lines like 'Management Progress Meeting' or 'Project Closeout Report', often appended with a machine-generated timestamp. The sending domains are typically unrelated or compromised businesses rather than legitimate meeting platforms, and the pattern is consistent with a phishing kit automating fake meeting invitations to harvest clicks or credentials.

Threat Classification

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

CategoryValues
Attack typesICS Phishing, Credential Phishing
Tactics and techniquesSocial engineering, Impersonation: Brand, Spoofing, Open redirect

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
)
and 2 of (
  strings.icontains(body.current_thread.text, 'join the meeting now'),
  strings.icontains(body.current_thread.text, 'reset dial-in pin'),
  strings.icontains(body.current_thread.text, 'find a local number'),
  strings.icontains(body.current_thread.text, 'phone conference id')
)
and any(body.current_thread.links,
        .href_url.domain.root_domain == sender.email.domain.root_domain
        and strings.istarts_with(.href_url.path, "/ls/click")
)
and 2 of (
  strings.icontains(subject.subject, 'project implementing agreement kick-off'),
  strings.icontains(subject.subject, 'management progress meeting'),
  strings.icontains(subject.subject, 'finance committee meeting'),
  strings.icontains(subject.subject, 'project closeout report'),
  strings.icontains(subject.subject, '(and new time)'),
  // kit personalizes with the target org name: "Discussion w/ <Company>:"
  (
    regex.icontains(subject.subject, 'discussion w/ .{1,40}:')
    or 
    // machine-appended timestamp
    regex.icontains(subject.subject,
                    '(?:\d{1,2}:\d{2}:\d{2}|\d{1,2}:\d{2}\s*(?:am|pm))\s*$'
    )
  )
)

Detection Logic

Scope: inbound message.

Detects inbound messages carrying an .ics calendar attachment that impersonate meeting invites, referencing dial-in details such as PIN resets, local numbers, or conference IDs. These messages include a tracked link redirecting through the sender's own domain (e.g. /ls/click) and use generic, template-style subject lines like 'Management Progress Meeting' or 'Project Closeout Report', often appended with a machine-generated timestamp. The sending domains are typically unrelated or compromised businesses rather than legitimate meeting platforms, and the pattern is consistent with a phishing kit automating fake meeting invitations to harvest clicks or credentials.

  1. inbound message
  2. any of attachments where any holds:
    • .file_type is 'ics'
    • .file_extension is 'ics'
    • .content_type in ('application/ics', 'text/calendar')
  3. at least 2 of 4: body.current_thread.text contains any of 4 patterns
    • join the meeting now
    • reset dial-in pin
    • find a local number
    • phone conference id
  4. any of body.current_thread.links where all hold:
    • .href_url.domain.root_domain is sender.email.domain.root_domain
    • .href_url.path starts with '/ls/click'
  5. at least 2 of:
    • subject.subject contains 'project implementing agreement kick-off'
    • subject.subject contains 'management progress meeting'
    • subject.subject contains 'finance committee meeting'
    • subject.subject contains 'project closeout report'
    • subject.subject contains '(and new time)'
    • any of:
      • subject.subject matches 'discussion w/ .{1,40}:'
      • subject.subject matches '(?:\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}\\s*(?:am|pm))\\s*$'

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, body.current_thread.links, body.current_thread.links[].href_url.domain.root_domain, body.current_thread.links[].href_url.path, body.current_thread.text, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: regex.icontains, strings.icontains, strings.istarts_with.

Indicators Matched (16)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
strings.icontainssubstringjoin the meeting now
strings.icontainssubstringreset dial-in pin
strings.icontainssubstringfind a local number
strings.icontainssubstringphone conference id
strings.istarts_withprefix/ls/click
strings.icontainssubstringproject implementing agreement kick-off
strings.icontainssubstringmanagement progress meeting
strings.icontainssubstringfinance committee meeting
4 more
strings.icontainssubstringproject closeout report
strings.icontainssubstring(and new time)
regex.icontainsregexdiscussion w/ .{1,40}:
regex.icontainsregex(?:\d{1,2}:\d{2}:\d{2}|\d{1,2}:\d{2}\s*(?:am|pm))\s*$

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      or
        subject.subject regex_match "(?:\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}\\s*(?:am|pm))\\s*$"
        subject.subject regex_match "discussion w/ .{1,40}:"
      subject.subject contains "(and new time)"
    and
      or
        subject.subject regex_match "(?:\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}\\s*(?:am|pm))\\s*$"
        subject.subject regex_match "discussion w/ .{1,40}:"
      subject.subject contains "finance committee meeting"
    and
      or
        subject.subject regex_match "(?:\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}\\s*(?:am|pm))\\s*$"
        subject.subject regex_match "discussion w/ .{1,40}:"
      subject.subject contains "management progress meeting"
    and
      or
        subject.subject regex_match "(?:\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}\\s*(?:am|pm))\\s*$"
        subject.subject regex_match "discussion w/ .{1,40}:"
      subject.subject contains "project closeout report"
    and
      or
        subject.subject regex_match "(?:\\d{1,2}:\\d{2}:\\d{2}|\\d{1,2}:\\d{2}\\s*(?:am|pm))\\s*$"
        subject.subject regex_match "discussion w/ .{1,40}:"
      subject.subject contains "project implementing agreement kick-off"
    and
      subject.subject contains "(and new time)"
      subject.subject contains "finance committee meeting"
    and
      subject.subject contains "(and new time)"
      subject.subject contains "management progress meeting"
    and
      subject.subject contains "(and new time)"
      subject.subject contains "project closeout report"
    and
      subject.subject contains "(and new time)"
      subject.subject contains "project implementing agreement kick-off"
    and
      subject.subject contains "finance committee meeting"
      subject.subject contains "management progress meeting"
    and
      subject.subject contains "finance committee meeting"
      subject.subject contains "project closeout report"
    and
      subject.subject contains "finance committee meeting"
      subject.subject contains "project implementing agreement kick-off"
    and
      subject.subject contains "management progress meeting"
      subject.subject contains "project closeout report"
    and
      subject.subject contains "management progress meeting"
      subject.subject contains "project implementing agreement kick-off"
    and
      subject.subject contains "project closeout report"
      subject.subject contains "project implementing agreement kick-off"
  any(attachments)
    or
      attachments.content_type in ["application/ics", "text/calendar"]
      attachments.file_extension eq "ics"
      attachments.file_type eq "ics"
  any(body.current_thread.links)
    and
      body.current_thread.links.href_url.domain.root_domain cross_field_compare "sender.email.domain.root_domain"
      body.current_thread.links.href_url.path starts_with "/ls/click"
  or
    and
      body.current_thread.text contains "find a local number"
      body.current_thread.text contains "join the meeting now"
    and
      body.current_thread.text contains "find a local number"
      body.current_thread.text contains "phone conference id"
    and
      body.current_thread.text contains "find a local number"
      body.current_thread.text contains "reset dial-in pin"
    and
      body.current_thread.text contains "join the meeting now"
      body.current_thread.text contains "phone conference id"
    and
      body.current_thread.text contains "join the meeting now"
      body.current_thread.text contains "reset dial-in pin"
    and
      body.current_thread.text contains "phone conference id"
      body.current_thread.text contains "reset dial-in pin"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • find a local number
  • join the meeting now
  • phone conference id
  • reset dial-in pin
field:"body.current_thread.text" kind:contains
subject.subjectcontains
  • (and new time)
  • finance committee meeting
  • management progress meeting
  • project closeout report
  • project implementing agreement kick-off
field:"subject.subject" kind:contains
subject.subjectregex_match
  • (?:\d{1,2}:\d{2}:\d{2}|\d{1,2}:\d{2}\s*(?:am|pm))\s*$
  • discussion w/ .{1,40}:
field:"subject.subject" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: ICS voicemail lure with suspicious link

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

Detects inbound emails containing an ICS calendar attachment whose event description mimics a voicemail notification (e.g., 'new voicemail', 'listen to your voicemail') and includes a link pointing to a free file hosting service, self-service creation platform, URL shortener, suspicious TLD, or a domain registered within the last 90 days. Excludes messages from high-trust sender domains that pass DMARC authentication.

Threat Classification

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

CategoryValues
Attack typesICS Phishing, Credential Phishing
Tactics and techniquesSocial engineering, Free file host, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type == "ics"
          or .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
        and any(beta.file.parse_ics(.).events,
                // voicemail key words
                regex.icontains(.description,
                                'new voice\s?mail|voice\s?mail.{0,20}(?:notification|received|awaits|ready|logged)|listen\s+to\s+(?:your\s+)?voice\s?mail|you\s+(?:have|received)\s+a\s+new\s+voice|voice\s+message.{0,20}(?:notification|from your inbox|in your)'
                )
                // sus link
                and any(.links,
                        .href_url.domain.root_domain in $free_file_hosts
                        or .href_url.domain.domain in $free_file_hosts
                        or .href_url.domain.root_domain in $self_service_creation_platform_domains
                        or .href_url.domain.domain in $self_service_creation_platform_domains
                        or .href_url.domain.tld in $suspicious_tlds
                        or .href_url.domain.domain in $url_shorteners
                        or .href_url.domain.root_domain in $url_shorteners
                        or network.whois(.href_url.domain).days_old < 90
                        or strings.icontains(.display_url.url, "voicemail")
                        or strings.icontains(.display_text, "voicemail")                          
                        // minimal js landing page
                        or (
                          length(ml.link_analysis(.).unique_urls_accessed) == 3
                          and all(ml.link_analysis(.).unique_urls_accessed,
                                  .url == ..href_url.url
                                  or (
                                    strings.starts_with(.url, ..href_url.url)
                                    and strings.ends_with(.url, '.js')
                                  )
                                  or .url == strings.concat(..href_url.url,
                                                            'favicon.png'
                                  )
                          )
                        )
                )
        )
)
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.

Detects inbound emails containing an ICS calendar attachment whose event description mimics a voicemail notification (e.g., 'new voicemail', 'listen to your voicemail') and includes a link pointing to a free file hosting service, self-service creation platform, URL shortener, suspicious TLD, or a domain registered within the last 90 days. Excludes messages from high-trust sender domains that pass DMARC authentication.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'ics'
      • .file_extension is 'ics'
      • .content_type in ('application/ics', 'text/calendar')
    • any(beta.file.parse_ics(.).events, // voicemail key words regex.icontains(.description, 'new voice\s?mail|voice\s?mail.{0,20}(?:notification|received|awaits|ready|logged)|listen\s+to\s+(?:your\s+)?voice\s?mail|you\s+(?:have|received)\s+a\s+new\s+voice|voice\s+message.{0,20}(?:notification|from your inbox|in your)' ) // sus link and any(.links, .href_url.domain.root_domain in $free_file_hosts or .href_url.domain.domain in $free_file_hosts or .href_url.domain.root_domain in $self_service_creation_platform_domains or .href_url.domain.domain in $self_service_creation_platform_domains or .href_url.domain.tld in $suspicious_tlds or .href_url.domain.domain in $url_shorteners or .href_url.domain.root_domain in $url_shorteners or network.whois(.href_url.domain).days_old < 90 or strings.icontains(.display_url.url, "voicemail") or strings.icontains(.display_text, "voicemail") // minimal js landing page or ( length(ml.link_analysis(.).unique_urls_accessed) == 3 and all(ml.link_analysis(.).unique_urls_accessed, .url == ..href_url.url or ( strings.starts_with(.url, ..href_url.url) and strings.ends_with(.url, '.js') ) or .url == strings.concat(..href_url.url, 'favicon.png' ) ) ) ) )
  3. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.file.parse_ics, ml.link_analysis, network.whois, regex.icontains, strings.concat, strings.ends_with, strings.icontains, strings.starts_with. Reference lists: $free_file_hosts, $high_trust_sender_root_domains, $self_service_creation_platform_domains, $suspicious_tlds, $url_shorteners.

Indicators Matched (7)

FieldMatchValue
attachments[].file_typeequalsics
attachments[].file_extensionequalsics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
regex.icontainsregexnew voice\s?mail|voice\s?mail.{0,20}(?:notification|received|awaits|ready|logged)|listen\s+to\s+(?:your\s+)?voice\s?mail|you\s+(?:have|received)\s+a\s+new\s+voice|voice\s+message.{0,20}(?:notification|from your inbox|in your)
strings.icontainssubstringvoicemail
strings.ends_withsuffix.js

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
       macro "any(beta.file.parse_ics(.).events,\n                // voicemail key words\n                regex.icontains(.description,\n                                'new voice\\s?mail|voice\\s?mail.{0,20}(?:notification|received|awaits|ready|logged)|listen\\s+to\\s+(?:your\\s+)?voice\\s?mail|you\\s+(?:have|received)\\s+a\\s+new\\s+voice|voice\\s+message.{0,20}(?:notification|from your inbox|in your)'\n                )\n                // sus link\n                and any(.links,\n                        .href_url.domain.root_domain in $free_file_hosts\n                        or .href_url.domain.domain in $free_file_hosts\n                        or .href_url.domain.root_domain in $self_service_creation_platform_domains\n                        or .href_url.domain.domain in $self_service_creation_platform_domains\n                        or .href_url.domain.tld in $suspicious_tlds\n                        or .href_url.domain.domain in $url_shorteners\n                        or .href_url.domain.root_domain in $url_shorteners\n                        or network.whois(.href_url.domain).days_old < 90\n                        or strings.icontains(.display_url.url, \"voicemail\")\n                        or strings.icontains(.display_text, \"voicemail\")                          \n                        // minimal js landing page\n                        or (\n                          length(ml.link_analysis(.).unique_urls_accessed) == 3\n                          and all(ml.link_analysis(.).unique_urls_accessed,\n                                  .url == ..href_url.url\n                                  or (\n                                    strings.starts_with(.url, ..href_url.url)\n                                    and strings.ends_with(.url, '.js')\n                                  )\n                                  or .url == strings.concat(..href_url.url,\n                                                            'favicon.png'\n                                  )\n                          )\n                        )\n                )\n        )"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: ICS with embedded document

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

ICS invite contains an embedded document.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension == "ics"
        and strings.ilike(file.parse_text(.).text,
                          '*ATTACH;ENCODING=*;VALUE=BINARY*'
        )
        and (
          strings.ilike(file.parse_text(.).text, '*FILENAME=*.doc*')
          or strings.ilike(file.parse_text(.).text, '*FILENAME=*.dot*')
          or strings.ilike(file.parse_text(.).text, '*FILENAME=*.pp*')
          or strings.ilike(file.parse_text(.).text, '*FILENAME=*.wbk*')
          or strings.ilike(file.parse_text(.).text, '*FILENAME=*.xl*')
          or strings.ilike(file.parse_text(.).text, '*FILENAME=*.html*')
        )
)

Detection Logic

Scope: inbound message.

ICS invite contains an embedded document.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension is 'ics'
    • strings.ilike(file.parse_text(.).text, '*ATTACH;ENCODING=*;VALUE=BINARY*' )
    • any of:
      • strings.ilike(file.parse_text(.).text, '*FILENAME=*.doc*')
      • strings.ilike(file.parse_text(.).text, '*FILENAME=*.dot*')
      • strings.ilike(file.parse_text(.).text, '*FILENAME=*.pp*')
      • strings.ilike(file.parse_text(.).text, '*FILENAME=*.wbk*')
      • strings.ilike(file.parse_text(.).text, '*FILENAME=*.xl*')
      • strings.ilike(file.parse_text(.).text, '*FILENAME=*.html*')

Inspects: attachments[].file_extension, type.inbound. Sensors: file.parse_text, strings.ilike.

Indicators Matched (8)

FieldMatchValue
attachments[].file_extensionequalsics
strings.ilikesubstring*ATTACH;ENCODING=*;VALUE=BINARY*
strings.ilikesubstring*FILENAME=*.doc*
strings.ilikesubstring*FILENAME=*.dot*
strings.ilikesubstring*FILENAME=*.pp*
strings.ilikesubstring*FILENAME=*.wbk*
strings.ilikesubstring*FILENAME=*.xl*
strings.ilikesubstring*FILENAME=*.html*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        strings.ilike func_call "strings.ilike(file.parse_text(.).text, '*FILENAME=*.doc*')"
        strings.ilike func_call "strings.ilike(file.parse_text(.).text, '*FILENAME=*.dot*')"
        strings.ilike func_call "strings.ilike(file.parse_text(.).text, '*FILENAME=*.html*')"
        strings.ilike func_call "strings.ilike(file.parse_text(.).text, '*FILENAME=*.pp*')"
        strings.ilike func_call "strings.ilike(file.parse_text(.).text, '*FILENAME=*.wbk*')"
        strings.ilike func_call "strings.ilike(file.parse_text(.).text, '*FILENAME=*.xl*')"
      attachments.file_extension eq "ics"
      strings.ilike func_call "strings.ilike(file.parse_text(.).text,\n                          '*ATTACH;ENCODING=*;VALUE=BINARY*'\n        )"
  type.inbound eq "true"

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"

Attachment: ICS with embedded Javascript in SVG file

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

Detects incoming messages containing ICS attachments with embedded SVG files that contain malicious JavaScript code, including base64-encoded content and potentially harmful event handlers. The rule specifically watches for onload events, location redirects, error handlers, and iframe elements with base64 data URIs.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesScripting, Evasion, ICS Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ('ics')
          or .content_type in ("application/ics", "text/calendar")
        )
        and any(file.explode(.),
                (
                  .file_extension in~ ("svg", "svgz")
                  or .flavors.mime == "image/svg+xml"
                )
                and any(.scan.strings.strings,
                        strings.ilike(.,
                                      "*onload*",
                                      "*window.location.href*",
                                      "*onerror*",
                                      "*CDATA*",
                                      "*<script*",
                                      "*</script*",
                                      "*atob*",
                                      "*location.assign*",
                                      "*decodeURIComponent*"
                        )
                )
        )
)

Detection Logic

Scope: inbound message.

Detects incoming messages containing ICS attachments with embedded SVG files that contain malicious JavaScript code, including base64-encoded content and potentially harmful event handlers. The rule specifically watches for onload events, location redirects, error handlers, and iframe elements with base64 data URIs.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('ics')
      • .content_type in ('application/ics', 'text/calendar')
    • any(file.explode(.), ( .file_extension in~ ("svg", "svgz") or .flavors.mime == "image/svg+xml" ) and any(.scan.strings.strings, strings.ilike(., "*onload*", "*window.location.href*", "*onerror*", "*CDATA*", "*<script*", "*</script*", "*atob*", "*location.assign*", "*decodeURIComponent*" ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: file.explode, strings.ilike.

Indicators Matched (15)

FieldMatchValue
attachments[].file_extensionmemberics
attachments[].content_typememberapplication/ics
attachments[].content_typemembertext/calendar
file.explode(attachments[])[].file_extensionmembersvg
file.explode(attachments[])[].file_extensionmembersvgz
file.explode(attachments[])[].flavors.mimeequalsimage/svg+xml
strings.ilikesubstring*onload*
strings.ilikesubstring*window.location.href*
strings.ilikesubstring*onerror*
strings.ilikesubstring*CDATA*
strings.ilikesubstring*<script*
strings.ilikesubstring*</script*
3 more
strings.ilikesubstring*atob*
strings.ilikesubstring*location.assign*
strings.ilikesubstring*decodeURIComponent*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
       macro "any(file.explode(.),\n                (\n                  .file_extension in~ (\"svg\", \"svgz\")\n                  or .flavors.mime == \"image/svg+xml\"\n                )\n                and any(.scan.strings.strings,\n                        strings.ilike(.,\n                                      \"*onload*\",\n                                      \"*window.location.href*\",\n                                      \"*onerror*\",\n                                      \"*CDATA*\",\n                                      \"*<script*\",\n                                      \"*</script*\",\n                                      \"*atob*\",\n                                      \"*location.assign*\",\n                                      \"*decodeURIComponent*\"\n                        )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: ICS with employee policy review lure

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

Detects ICS calendar attachments containing references to 'policy review' and 'secure access' terminology, which may be used in social engineering attacks to prompt users to take action under the guise of compliance or security requirements.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, BEC/Fraud
Tactics and techniquesEvasion, ICS Phishing, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments,
               .file_type in~ ('ics')
               or .content_type in ("text/calendar", "application/ics")
        ),
        any(file.explode(.),
            .depth == 0
            and any(.scan.strings.strings,
                    strings.icontains(., 'policy review')
            )
            and any(.scan.strings.strings,
                    strings.icontains(., 'secure access')
            )
        )
)

Detection Logic

Scope: inbound message.

Detects ICS calendar attachments containing references to 'policy review' and 'secure access' terminology, which may be used in social engineering attacks to prompt users to take action under the guise of compliance or security requirements.

  1. inbound message
  2. any(filter(attachments, .file_type in~ ('ics') or .content_type in ("text/calendar", "application/ics") ), any(file.explode(.), .depth == 0 and any(.scan.strings.strings, strings.icontains(., 'policy review') ) and any(.scan.strings.strings, strings.icontains(., 'secure access') ) ) )

Inspects: attachments[].content_type, attachments[].file_type, type.inbound. Sensors: file.explode, strings.icontains.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typememberics
attachments[].content_typemembertext/calendar
attachments[].content_typememberapplication/ics
strings.icontainssubstringpolicy review
strings.icontainssubstringsecure access

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .file_type in~ ('ics')\n               or .content_type in (\"text/calendar\", \"application/ics\")\n        ),\n        any(file.explode(.),\n            .depth == 0\n            and any(.scan.strings.strings,\n                    strings.icontains(., 'policy review')\n            )\n            and any(.scan.strings.strings,\n                    strings.icontains(., 'secure access')\n            )\n        )\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"

Attachment: Identity Confirmation With Document Unlock Code

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

Detects short inbound messages referencing an attached document that requires the recipient to confirm their identity and enter a code to unlock it, sent within an active thread context.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesSocial engineering, Encryption, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • body.current_thread
  • type

Rule Body

type.inbound
// confirm to unlock language
and strings.icontains(body.current_thread.text, "confirm your identity")
and strings.icontains(body.current_thread.text, "code to unlock document")
// and attached document
and strings.icontains(body.current_thread.text, "attached document")
// short message length
and length(body.current_thread.text) < 500
// plus previous threads
and length(body.previous_threads) > 1

Detection Logic

Scope: inbound message.

Detects short inbound messages referencing an attached document that requires the recipient to confirm their identity and enter a code to unlock it, sent within an active thread context.

  1. inbound message
  2. body.current_thread.text contains 'confirm your identity'
  3. body.current_thread.text contains 'code to unlock document'
  4. body.current_thread.text contains 'attached document'
  5. length(body.current_thread.text) < 500
  6. length(body.previous_threads) > 1

Inspects: body.current_thread.text, body.previous_threads, type.inbound. Sensors: strings.icontains.

Indicators Matched (3)

FieldMatchValue
strings.icontainssubstringconfirm your identity
strings.icontainssubstringcode to unlock document
strings.icontainssubstringattached document

Stages and Predicates

Stage 1: mql_rule

and
  body.current_thread.text contains "attached document"
  body.current_thread.text contains "code to unlock document"
  body.current_thread.text contains "confirm your identity"
  body.current_thread.text length_compare "500"
  body.previous_threads length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • attached document
  • code to unlock document
  • confirm your identity
field:"body.current_thread.text" kind:contains
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: Image-only docx/pptx callback phishing

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

Detects inbound emails with docx or pptx attachments that contain no text but exactly one embedded image, a common tactic to evade text-based scanning by presenting content as a picture. The rule then inspects any extracted text from the image for a combination of callback phishing lures—such as references to subscriptions, invoices, refunds, or antivirus renewals alongside phone numbers or dollar amounts—paired with impersonation of well-known brands like PayPal, McAfee, Norton, or Best Buy, indicating a fraudulent phone-based scam attempt.

Threat Classification

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

CategoryValues
Attack typesCallback Phishing
Tactics and techniquesImage as content, Impersonation: Brand, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • sender.email
  • type

Rule Body

type.inbound
and sender.email.domain.root_domain in $free_email_providers
and any(attachments,
        .file_type in ("docx", "pptx")
        and any(file.explode(.),
                (.scan.docx.word_count == 0 and .scan.docx.image_count == 1)
                or (.scan.pptx.word_count == 0 and .scan.pptx.image_count == 1)
        )
        and any(file.explode(.),
                (.depth == 0 or .flavors.mime == "text/plain")
                // 4 of the following strings are found
                and 4 of (
                  // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
                  strings.icontains(.scan.strings.raw, "purchase"),
                  strings.icontains(.scan.strings.raw, "payment"),
                  strings.icontains(.scan.strings.raw, "transaction"),
                  strings.icontains(.scan.strings.raw, "subscription"),
                  strings.icontains(.scan.strings.raw, "antivirus"),
                  strings.icontains(.scan.strings.raw, "order"),
                  strings.icontains(.scan.strings.raw, "support"),
                  strings.icontains(.scan.strings.raw, "help line"),
                  strings.icontains(.scan.strings.raw, "receipt"),
                  strings.icontains(.scan.strings.raw, "invoice"),
                  strings.icontains(.scan.strings.raw, "call"),
                  strings.icontains(.scan.strings.raw, "helpdesk"),
                  strings.icontains(.scan.strings.raw, "cancel"),
                  strings.icontains(.scan.strings.raw, "renew"),
                  strings.icontains(.scan.strings.raw, "refund"),
                  regex.icontains(.scan.strings.raw, "(?:reach|contact) us at"),
                  strings.icontains(.scan.strings.raw, "+1"),
                  strings.icontains(.scan.strings.raw, "amount"),
                  strings.icontains(.scan.strings.raw, "charged"),
                  strings.icontains(.scan.strings.raw, "crypto"),
                  strings.icontains(.scan.strings.raw, "wallet address"),
                  regex.icontains(.scan.strings.raw, '\$\d{3}\.\d{2}\b'),
                  regex.icontains(.scan.strings.raw,
                                  '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
                                  '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
                  ),
                )
                and regex.icontains(.scan.strings.raw,
                                    '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks|amazon)'
                )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound emails with docx or pptx attachments that contain no text but exactly one embedded image, a common tactic to evade text-based scanning by presenting content as a picture. The rule then inspects any extracted text from the image for a combination of callback phishing lures—such as references to subscriptions, invoices, refunds, or antivirus renewals alongside phone numbers or dollar amounts—paired with impersonation of well-known brands like PayPal, McAfee, Norton, or Best Buy, indicating a fraudulent phone-based scam attempt.

  1. inbound message
  2. sender.email.domain.root_domain in $free_email_providers
  3. any of attachments where all hold:
    • .file_type in ('docx', 'pptx')
    • any(file.explode(.), (.scan.docx.word_count == 0 and .scan.docx.image_count == 1) or (.scan.pptx.word_count == 0 and .scan.pptx.image_count == 1) )
    • any(file.explode(.), (.depth == 0 or .flavors.mime == "text/plain") // 4 of the following strings are found and 4 of ( // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml strings.icontains(.scan.strings.raw, "purchase"), strings.icontains(.scan.strings.raw, "payment"), strings.icontains(.scan.strings.raw, "transaction"), strings.icontains(.scan.strings.raw, "subscription"), strings.icontains(.scan.strings.raw, "antivirus"), strings.icontains(.scan.strings.raw, "order"), strings.icontains(.scan.strings.raw, "support"), strings.icontains(.scan.strings.raw, "help line"), strings.icontains(.scan.strings.raw, "receipt"), strings.icontains(.scan.strings.raw, "invoice"), strings.icontains(.scan.strings.raw, "call"), strings.icontains(.scan.strings.raw, "helpdesk"), strings.icontains(.scan.strings.raw, "cancel"), strings.icontains(.scan.strings.raw, "renew"), strings.icontains(.scan.strings.raw, "refund"), regex.icontains(.scan.strings.raw, "(?:reach|contact) us at"), strings.icontains(.scan.strings.raw, "+1"), strings.icontains(.scan.strings.raw, "amount"), strings.icontains(.scan.strings.raw, "charged"), strings.icontains(.scan.strings.raw, "crypto"), strings.icontains(.scan.strings.raw, "wallet address"), regex.icontains(.scan.strings.raw, '\$\d{3}\.\d{2}\b'), regex.icontains(.scan.strings.raw, '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}', '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}' ), ) and regex.icontains(.scan.strings.raw, '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks|amazon)' ) )

Inspects: attachments[].file_type, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, regex.icontains, strings.icontains. Reference lists: $free_email_providers.

Indicators Matched (28)

FieldMatchValue
attachments[].file_typememberdocx
attachments[].file_typememberpptx
file.explode(attachments[])[].flavors.mimeequalstext/plain
strings.icontainssubstringpurchase
strings.icontainssubstringpayment
strings.icontainssubstringtransaction
strings.icontainssubstringsubscription
strings.icontainssubstringantivirus
strings.icontainssubstringorder
strings.icontainssubstringsupport
strings.icontainssubstringhelp line
strings.icontainssubstringreceipt
16 more
strings.icontainssubstringinvoice
strings.icontainssubstringcall
strings.icontainssubstringhelpdesk
strings.icontainssubstringcancel
strings.icontainssubstringrenew
strings.icontainssubstringrefund
regex.icontainsregex(?:reach|contact) us at
strings.icontainssubstring+1
strings.icontainssubstringamount
strings.icontainssubstringcharged
strings.icontainssubstringcrypto
strings.icontainssubstringwallet address
regex.icontainsregex\$\d{3}\.\d{2}\b
regex.icontainsregex\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}
regex.icontainsregex\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}
regex.icontainsregex(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks|amazon)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type in ["docx", "pptx"]
       macro "any(file.explode(.),\n                (.depth == 0 or .flavors.mime == \"text/plain\")\n                // 4 of the following strings are found\n                and 4 of (\n                  // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml\n                  strings.icontains(.scan.strings.raw, \"purchase\"),\n                  strings.icontains(.scan.strings.raw, \"payment\"),\n                  strings.icontains(.scan.strings.raw, \"transaction\"),\n                  strings.icontains(.scan.strings.raw, \"subscription\"),\n                  strings.icontains(.scan.strings.raw, \"antivirus\"),\n                  strings.icontains(.scan.strings.raw, \"order\"),\n                  strings.icontains(.scan.strings.raw, \"support\"),\n                  strings.icontains(.scan.strings.raw, \"help line\"),\n                  strings.icontains(.scan.strings.raw, \"receipt\"),\n                  strings.icontains(.scan.strings.raw, \"invoice\"),\n                  strings.icontains(.scan.strings.raw, \"call\"),\n                  strings.icontains(.scan.strings.raw, \"helpdesk\"),\n                  strings.icontains(.scan.strings.raw, \"cancel\"),\n                  strings.icontains(.scan.strings.raw, \"renew\"),\n                  strings.icontains(.scan.strings.raw, \"refund\"),\n                  regex.icontains(.scan.strings.raw, \"(?:reach|contact) us at\"),\n                  strings.icontains(.scan.strings.raw, \"+1\"),\n                  strings.icontains(.scan.strings.raw, \"amount\"),\n                  strings.icontains(.scan.strings.raw, \"charged\"),\n                  strings.icontains(.scan.strings.raw, \"crypto\"),\n                  strings.icontains(.scan.strings.raw, \"wallet address\"),\n                  regex.icontains(.scan.strings.raw, '\\$\\d{3}\\.\\d{2}\\b'),\n                  regex.icontains(.scan.strings.raw,\n                                  '\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}',\n                                  '\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}'\n                  ),\n                )\n                and regex.icontains(.scan.strings.raw,\n                                    '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t|quickbooks|amazon)'\n                )\n        )"
       macro "any(file.explode(.),\n                (.scan.docx.word_count == 0 and .scan.docx.image_count == 1)\n                or (.scan.pptx.word_count == 0 and .scan.pptx.image_count == 1)\n        )"
  sender.email.domain.root_domain macro "sender.email.domain.root_domain in free_email_providers"
  type.inbound eq "true"

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"

Attachment: Invoice and W-9 PDFs with suspicious creators

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

Detects messages containing two PDF attachments where one has invoice-related naming patterns and another contains W-9 tax form indicators, commonly used in business email compromise attacks targeting financial processes.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesPDF, Social engineering, Impersonation: Brand

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • headers.reply_to
  • sender.email
  • type

Rule Body

type.inbound
and length(distinct(attachments, .sha1)) == 2
and length(filter(attachments, .file_type == "pdf")) == 2
// either of them are chrome/wkhtmltopdf
and any(filter(attachments, .file_type == "pdf"),
        beta.parse_exif(.).creator == "Chromium"
        or strings.icontains(beta.parse_exif(.).creator, "wkhtmltopdf")
        or strings.icontains(beta.parse_exif(.).creator, "HeadlessChrome")
        or (
          any(beta.parse_exif(.).fields, .key == "Creator" and .value == "")
          and any(beta.parse_exif(.).fields,
                  .key == "Producer" and .value == ""
          )
        )
        or any(beta.parse_exif(.).fields,
               .key in ("Producer", "CreatorTool")
               and regex.icontains(.value, '(?:pdfium|mpdf)')
        )
)
and any(attachments,
        strings.istarts_with(.file_name, 'lnv')
        or strings.istarts_with(.file_name, 'inv-')
        or strings.istarts_with(.file_name, "invoice_")
        or regex.contains(.file_name, '^Invoice\s\d{8,9}')
        or regex.contains(.file_name, '^INV[0-9]{7}')
        or regex.contains(.file_name, '^INV#[0-9]{12}')
        or strings.icontains(beta.ocr(.).text, "Executive Business Coaching")
        or strings.icontains(beta.ocr(.).text, "Executive Coaching")
        or strings.icontains(beta.ocr(.).text, "Professional Services")
        or strings.icontains(beta.ocr(.).text, "Business Systems Integration")
        or strings.icontains(beta.ocr(.).text, "Consulting & Advisory")
        or strings.icontains(beta.ocr(.).text, "Zoomlnfo")
        or (
          (
            regex.contains(beta.ocr(.).text, 'INVOICE\s*\n')
            or regex.icontains(.file_name, '_inv_')
          )
          and length(headers.reply_to) > 0
          and all(headers.reply_to,
                  .email.domain.root_domain != sender.email.domain.root_domain
          )
        )
)
and any(attachments,
        .file_name == ".pdf"
        or regex.contains(beta.ocr(.).text, 'W[=-]9')
        or regex.icontains(.file_name, 'w[-_]?9')
)
and not (
  sender.email.domain.root_domain in ('intuit.com')
  and coalesce(headers.auth_summary.dmarc.pass, false)
)

Detection Logic

Scope: inbound message.

Detects messages containing two PDF attachments where one has invoice-related naming patterns and another contains W-9 tax form indicators, commonly used in business email compromise attacks targeting financial processes.

  1. inbound message
  2. length(distinct(attachments, .sha1)) == 2
  3. length(filter(attachments, .file_type == "pdf")) == 2
  4. any(filter(attachments, .file_type == "pdf"), beta.parse_exif(.).creator == "Chromium" or strings.icontains(beta.parse_exif(.).creator, "wkhtmltopdf") or strings.icontains(beta.parse_exif(.).creator, "HeadlessChrome") or ( any(beta.parse_exif(.).fields, .key == "Creator" and .value == "") and any(beta.parse_exif(.).fields, .key == "Producer" and .value == "" ) ) or any(beta.parse_exif(.).fields, .key in ("Producer", "CreatorTool") and regex.icontains(.value, '(?:pdfium|mpdf)') ) )
  5. any of attachments where any holds:
    • .file_name starts with 'lnv'
    • .file_name starts with 'inv-'
    • .file_name starts with 'invoice_'
    • .file_name matches '^Invoice\\s\\d{8,9}'
    • .file_name matches '^INV[0-9]{7}'
    • .file_name matches '^INV#[0-9]{12}'
    • strings.icontains(beta.ocr(.).text, "Executive Business Coaching")
    • strings.icontains(beta.ocr(.).text, "Executive Coaching")
    • strings.icontains(beta.ocr(.).text, "Professional Services")
    • strings.icontains(beta.ocr(.).text, "Business Systems Integration")
    • strings.icontains(beta.ocr(.).text, "Consulting & Advisory")
    • strings.icontains(beta.ocr(.).text, "Zoomlnfo")
    • all of:
      • any of:
        • regex.contains(beta.ocr(.).text, 'INVOICE\s*\n')
        • .file_name matches '_inv_'
      • length(headers.reply_to) > 0
      • all of headers.reply_to where:
        • .email.domain.root_domain is not sender.email.domain.root_domain
  6. any of attachments where any holds:
    • .file_name is '.pdf'
    • regex.contains(beta.ocr(.).text, 'W[=-]9')
    • .file_name matches 'w[-_]?9'
  7. not:
    • all of:
      • sender.email.domain.root_domain in ('intuit.com')
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_name, attachments[].file_type, attachments[].sha1, headers.auth_summary.dmarc.pass, headers.reply_to, headers.reply_to[].email.domain.root_domain, sender.email.domain.root_domain, type.inbound. Sensors: beta.ocr, beta.parse_exif, regex.contains, regex.icontains, strings.icontains, strings.istarts_with.

Indicators Matched (26)

FieldMatchValue
attachments[].file_typeequalspdf
strings.icontainssubstringwkhtmltopdf
strings.icontainssubstringHeadlessChrome
beta.parse_exif(filter(attachments)[]).fields[].keyequalsCreator
beta.parse_exif(filter(attachments)[]).fields[].valueequals
beta.parse_exif(filter(attachments)[]).fields[].keyequalsProducer
beta.parse_exif(filter(attachments)[]).fields[].keymemberProducer
beta.parse_exif(filter(attachments)[]).fields[].keymemberCreatorTool
regex.icontainsregex(?:pdfium|mpdf)
strings.istarts_withprefixlnv
strings.istarts_withprefixinv-
strings.istarts_withprefixinvoice_
14 more
regex.containsregex^Invoice\s\d{8,9}
regex.containsregex^INV[0-9]{7}
regex.containsregex^INV#[0-9]{12}
strings.icontainssubstringExecutive Business Coaching
strings.icontainssubstringExecutive Coaching
strings.icontainssubstringProfessional Services
strings.icontainssubstringBusiness Systems Integration
strings.icontainssubstringConsulting & Advisory
strings.icontainssubstringZoomlnfo
regex.containsregexINVOICE\s*\n
regex.icontainsregex_inv_
attachments[].file_nameequals.pdf
regex.containsregexW[=-]9
regex.icontainsregexw[-_]?9

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        or
          attachments.file_name regex_match "_inv_"
          regex.contains func_call "regex.contains(beta.ocr(.).text, 'INVOICE\\s*\\n')"
        headers.reply_to length_compare "0"
         macro "all(headers.reply_to,\n                  .email.domain.root_domain != sender.email.domain.root_domain\n          )"
      attachments.file_name regex_match "^INV#[0-9]{12}"
      attachments.file_name regex_match "^INV[0-9]{7}"
      attachments.file_name regex_match "^Invoice\\s\\d{8,9}"
      attachments.file_name starts_with "inv-"
      attachments.file_name starts_with "invoice_"
      attachments.file_name starts_with "lnv"
      strings.icontains func_call "strings.icontains(beta.ocr(.).text, \"Business Systems Integration\")"
      strings.icontains func_call "strings.icontains(beta.ocr(.).text, \"Consulting & Advisory\")"
      strings.icontains func_call "strings.icontains(beta.ocr(.).text, \"Executive Business Coaching\")"
      strings.icontains func_call "strings.icontains(beta.ocr(.).text, \"Executive Coaching\")"
      strings.icontains func_call "strings.icontains(beta.ocr(.).text, \"Professional Services\")"
      strings.icontains func_call "strings.icontains(beta.ocr(.).text, \"Zoomlnfo\")"
  any(attachments)
    or
      attachments.file_name eq ".pdf"
      attachments.file_name regex_match "w[-_]?9"
      regex.contains func_call "regex.contains(beta.ocr(.).text, 'W[=-]9')"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain eq "intuit.com"
  length func_call "length(distinct(attachments, .sha1)) == 2"
  length func_call "length(filter(attachments, .file_type == \"pdf\")) == 2"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        beta.parse_exif(.).creator == \"Chromium\"\n        or strings.icontains(beta.parse_exif(.).creator, \"wkhtmltopdf\")\n        or strings.icontains(beta.parse_exif(.).creator, \"HeadlessChrome\")\n        or (\n          any(beta.parse_exif(.).fields, .key == \"Creator\" and .value == \"\")\n          and any(beta.parse_exif(.).fields,\n                  .key == \"Producer\" and .value == \"\"\n          )\n        )\n        or any(beta.parse_exif(.).fields,\n               .key in (\"Producer\", \"CreatorTool\")\n               and regex.icontains(.value, '(?:pdfium|mpdf)')\n        )\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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass
sender.email.domain.root_domaineqintuit.comexcludes:sender.email.domain.root_domain field:"sender.email.domain.root_domain" value:"intuit.com"

Attachment: JavaScript file with suspicious base64-encoded executable

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

JavaScript attachment or compressed JavaScript file containing a base64 encoded executable.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_common_archives
          or .file_extension in ("js", "jar")
        )
        and any(file.explode(.),
                (
                  (
                    .file_extension in ("js", "jar")
                    or any(.flavors.yara, . == "javascript_file")
                  )
                  and any(.flavors.yara, . == 'base64_pe')
                )
        )
)

Detection Logic

Scope: inbound message.

JavaScript attachment or compressed JavaScript file containing a base64 encoded executable.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_common_archives
      • .file_extension in ('js', 'jar')
    • any(file.explode(.), ( ( .file_extension in ("js", "jar") or any(.flavors.yara, . == "javascript_file") ) and any(.flavors.yara, . == 'base64_pe') ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmemberjs
attachments[].file_extensionmemberjar
file.explode(attachments[])[].file_extensionmemberjs
file.explode(attachments[])[].file_extensionmemberjar
file.explode(attachments[])[].flavors.yara[]equalsjavascript_file
file.explode(attachments[])[].flavors.yara[]equalsbase64_pe

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["jar", "js"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.),\n                (\n                  (\n                    .file_extension in (\"js\", \"jar\")\n                    or any(.flavors.yara, . == \"javascript_file\")\n                  )\n                  and any(.flavors.yara, . == 'base64_pe')\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: JPEG with gd-jpeg creator and suspicious file name

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

Detects inbound messages containing a single JPEG attachment with specific filename patterns and EXIF metadata indicating creation by gd-jpeg v1.0. This has been observed being used to produce company logos used within phishing messages.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(filter(attachments, .file_type == "jpg")) == 1
and any(attachments,
        .file_type == "jpg"
        and .file_extension == "jpeg"
        and strings.icontains(.file_name, 'images')
        and (
          strings.count(.file_name, '/') == 1
          or strings.count(.file_name, 'image') == 2
        )
        and any(beta.parse_exif(.).fields,
                .key =~ "Comment"
                and strings.istarts_with(.value, 'CREATOR: gd-jpeg v1.0')
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing a single JPEG attachment with specific filename patterns and EXIF metadata indicating creation by gd-jpeg v1.0. This has been observed being used to produce company logos used within phishing messages.

  1. inbound message
  2. length(filter(attachments, .file_type == "jpg")) == 1
  3. any of attachments where all hold:
    • .file_type is 'jpg'
    • .file_extension is 'jpeg'
    • .file_name contains 'images'
    • any of:
      • strings.count(.file_name, '/') == 1
      • strings.count(.file_name, 'image') == 2
    • any(beta.parse_exif(.).fields, .key =~ "Comment" and strings.istarts_with(.value, 'CREATOR: gd-jpeg v1.0') )

Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, type.inbound. Sensors: beta.parse_exif, strings.count, strings.icontains, strings.istarts_with.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalsjpg
attachments[].file_extensionequalsjpeg
strings.icontainssubstringimages
beta.parse_exif(attachments[]).fields[].keyequalsComment
strings.istarts_withprefixCREATOR: gd-jpeg v1.0

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        strings.count func_call "strings.count(.file_name, '/') == 1"
        strings.count func_call "strings.count(.file_name, 'image') == 2"
      attachments.file_extension eq "jpeg"
      attachments.file_name contains "images"
      attachments.file_type eq "jpg"
       macro "any(beta.parse_exif(.).fields,\n                .key =~ \"Comment\"\n                and strings.istarts_with(.value, 'CREATOR: gd-jpeg v1.0')\n        )"
  length func_call "length(filter(attachments, .file_type == \"jpg\")) == 1"
  type.inbound eq "true"

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"

Attachment: Legal themed message or PDF with suspicious indicators

#

Attachment: Link file with UNC path

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

Attached link file contains a UNC path. This can be used to relay NTLM password hashes; Windows will attempt to authenticate against the path even without the file being opened.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, LNK

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in ("lnk", "url")
        and any(file.explode(.),
                any(.scan.strings.strings,
                    regex.icontains(.,
                                    '\\\\([a-zA-Z0-9_:%.$-]+)\\([a-zA-Z0-9_:%.$-]+)'
                    )
                ) // normal UNC paths
                or any(.scan.strings.strings,
                       regex.icontains(.,
                                       '%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)'
                       )
                ) // percent-encoded UNC paths
        )
)

Detection Logic

Scope: inbound message.

Attached link file contains a UNC path. This can be used to relay NTLM password hashes; Windows will attempt to authenticate against the path even without the file being opened.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in ('lnk', 'url')
    • any(file.explode(.), any(.scan.strings.strings, regex.icontains(., '\\\\([a-zA-Z0-9_:%.$-]+)\\([a-zA-Z0-9_:%.$-]+)' ) ) // normal UNC paths or any(.scan.strings.strings, regex.icontains(., '%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)' ) ) // percent-encoded UNC paths )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, regex.icontains.

Indicators Matched (4)

FieldMatchValue
attachments[].file_extensionmemberlnk
attachments[].file_extensionmemberurl
regex.icontainsregex\\\\([a-zA-Z0-9_:%.$-]+)\\([a-zA-Z0-9_:%.$-]+)
regex.icontainsregex%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension in ["lnk", "url"]
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    regex.icontains(.,\n                                    '\\\\\\\\([a-zA-Z0-9_:%.$-]+)\\\\([a-zA-Z0-9_:%.$-]+)'\n                    )\n                ) // normal UNC paths\n                or any(.scan.strings.strings,\n                       regex.icontains(.,\n                                       '%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)'\n                       )\n                ) // percent-encoded UNC paths\n        )"
  type.inbound eq "true"

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"

Attachment: Link to Doubleclick.net open redirect

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

Doubleclick.net link in a document leveraging an open redirect.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesEvasion, Open redirect, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • type

Rule Body

type.inbound
and length(body.links) == 0
and any(attachments,
        (.file_type in ("pdf", "doc", "docx"))
        and any(file.explode(.),
                any(.scan.url.urls,
                    .domain.root_domain == "doubleclick.net"
                    and (
                      strings.icontains(.path, "/aclk")
                      or strings.icontains(.path, "/pcs/click")
                      or strings.icontains(.path, "/searchads/link/click")
                    )
                    and regex.icontains(.query_params,
                                        '&(?:adurl|ds_dest_url)=(?:[a-z]+(?:\:|%3a))?(?:\/|%2f)(?:\/|%2f)'
                    )
                )
        )
)

Detection Logic

Scope: inbound message.

Doubleclick.net link in a document leveraging an open redirect.

  1. inbound message
  2. length(body.links) == 0
  3. any of attachments where all hold:
    • .file_type in ('pdf', 'doc', 'docx')
    • any(file.explode(.), any(.scan.url.urls, .domain.root_domain == "doubleclick.net" and ( strings.icontains(.path, "/aclk") or strings.icontains(.path, "/pcs/click") or strings.icontains(.path, "/searchads/link/click") ) and regex.icontains(.query_params, '&(?:adurl|ds_dest_url)=(?:[a-z]+(?:\:|%3a))?(?:\/|%2f)(?:\/|%2f)' ) ) )

Inspects: attachments[].file_type, body.links, type.inbound. Sensors: file.explode, regex.icontains, strings.icontains.

Indicators Matched (8)

FieldMatchValue
attachments[].file_typememberpdf
attachments[].file_typememberdoc
attachments[].file_typememberdocx
file.explode(attachments[])[].scan.url.urls[].domain.root_domainequalsdoubleclick.net
strings.icontainssubstring/aclk
strings.icontainssubstring/pcs/click
strings.icontainssubstring/searchads/link/click
regex.icontainsregex&(?:adurl|ds_dest_url)=(?:[a-z]+(?:\:|%3a))?(?:\/|%2f)(?:\/|%2f)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type in ["doc", "docx", "pdf"]
       macro "any(file.explode(.),\n                any(.scan.url.urls,\n                    .domain.root_domain == \"doubleclick.net\"\n                    and (\n                      strings.icontains(.path, \"/aclk\")\n                      or strings.icontains(.path, \"/pcs/click\")\n                      or strings.icontains(.path, \"/searchads/link/click\")\n                    )\n                    and regex.icontains(.query_params,\n                                        '&(?:adurl|ds_dest_url)=(?:[a-z]+(?:\\:|%3a))?(?:\\/|%2f)(?:\\/|%2f)'\n                    )\n                )\n        )"
  body.links length_compare "0"
  type.inbound eq "true"

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"

Attachment: LNK file

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

Recursively scans files and archives to detect LNK connection files. LNK files can be weaponised to execute arbitrary commands including unpacking and running executable content embedded within the file itself.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesLNK

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension =~ "lnk"
        or (
          .file_extension in~ $file_extensions_common_archives
          and any(file.explode(.), .file_extension =~ "lnk")
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect LNK connection files. LNK files can be weaponised to execute arbitrary commands including unpacking and running executable content embedded within the file itself.

  1. inbound message
  2. any of attachments where any holds:
    • .file_extension is 'lnk'
    • all of:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), .file_extension =~ "lnk")

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalslnk
file.explode(attachments[])[].file_extensionequalslnk

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.), .file_extension =~ \"lnk\")"
      attachments.file_extension eq "lnk"
  type.inbound eq "true"

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"

Attachment: LNK with embedded content

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

Emotet has been observed to embed executable content within an LNK file to deliver and execute VBScript when launched. Similar research has demonstrated how this concept may be applied to deliver and launch an embedded executable via PowerShell.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesExploit, LNK, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and (
  any(attachments,
      .file_extension == "lnk"
      and any(file.explode(.),
              .file_extension =~ "lnk"
              and any(.scan.exiftool.fields,
                      (.key == "TargetFileSize" and .value == "0")
              )
              and any(.scan.exiftool.fields,
                      (
                        .key == "CommandLineArguments"
                        and strings.ilike(.value,
                                          "*findstr*",
                                          "*sc $path*",
                                          "*Set-Content*"
                        )
                      )
              )
      )
  )
)

Detection Logic

Scope: inbound message.

Emotet has been observed to embed executable content within an LNK file to deliver and execute VBScript when launched. Similar research has demonstrated how this concept may be applied to deliver and launch an embedded executable via PowerShell.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension is 'lnk'
    • any(file.explode(.), .file_extension =~ "lnk" and any(.scan.exiftool.fields, (.key == "TargetFileSize" and .value == "0") ) and any(.scan.exiftool.fields, ( .key == "CommandLineArguments" and strings.ilike(.value, "*findstr*", "*sc $path*", "*Set-Content*" ) ) ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, strings.ilike.

Indicators Matched (8)

FieldMatchValue
attachments[].file_extensionequalslnk
file.explode(attachments[])[].file_extensionequalslnk
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsTargetFileSize
file.explode(attachments[])[].scan.exiftool.fields[].valueequals0
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsCommandLineArguments
strings.ilikesubstring*findstr*
strings.ilikesubstring*sc $path*
strings.ilikesubstring*Set-Content*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension eq "lnk"
       macro "any(file.explode(.),\n              .file_extension =~ \"lnk\"\n              and any(.scan.exiftool.fields,\n                      (.key == \"TargetFileSize\" and .value == \"0\")\n              )\n              and any(.scan.exiftool.fields,\n                      (\n                        .key == \"CommandLineArguments\"\n                        and strings.ilike(.value,\n                                          \"*findstr*\",\n                                          \"*sc $path*\",\n                                          \"*Set-Content*\"\n                        )\n                      )\n              )\n      )"
  type.inbound eq "true"

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"

Attachment: Macro files containing MHT content

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

Detects macro-enabled files that contain embedded MHT (MIME HTML) content, which is commonly used to hide malicious code through file format manipulation.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesEvasion, Macros, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in $file_extensions_macros
        and any(file.explode(.),
                .file_extension == "mht"
                and not .flavors.mime == "message/rfc822"
        )
)

Detection Logic

Scope: inbound message.

Detects macro-enabled files that contain embedded MHT (MIME HTML) content, which is commonly used to hide malicious code through file format manipulation.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_macros
    • any(file.explode(.), .file_extension == "mht" and not .flavors.mime == "message/rfc822" )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_macros.

Indicators Matched (1)

FieldMatchValue
file.explode(attachments[])[].file_extensionequalsmht

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                .file_extension == \"mht\"\n                and not .flavors.mime == \"message/rfc822\"\n        )"
  type.inbound eq "true"

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"

Attachment: Macro with suspected use of COM ShellBrowserWindow object for process creation

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

Macro references the ShellBrowserWindow COM object which can be used to spawn new processes from Explorer.exe rather than as a child process of the Office application. This can be useful for a threat actor attempting to evade security controls.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesMacros, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.),
                any(.scan.strings.strings,
                    strings.ilike(.,
                                  "*new:C08AFD90-F2A1-11D1-8455-00A0C91F3880*"
                    )
                )
        )
)

Detection Logic

Scope: inbound message.

Macro references the ShellBrowserWindow COM object which can be used to spawn new processes from Explorer.exe rather than as a child process of the Office application. This can be useful for a threat actor attempting to evade security controls.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., "*new:C08AFD90-F2A1-11D1-8455-00A0C91F3880*" ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_macros.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
strings.ilikesubstring*new:C08AFD90-F2A1-11D1-8455-00A0C91F3880*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    strings.ilike(.,\n                                  \"*new:C08AFD90-F2A1-11D1-8455-00A0C91F3880*\"\n                    )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: Malformed OLE file

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

Attached OLE file (typically a Microsoft Office document) is malformed, possibly to evade traditional scanners and filters.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in $file_extensions_macros
        and any(file.explode(.),
                any(.scan.yara.matches, .name == "MALFORMED_OLE_HEADER")
        )
)

Detection Logic

Scope: inbound message.

Attached OLE file (typically a Microsoft Office document) is malformed, possibly to evade traditional scanners and filters.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_macros
    • any(file.explode(.), any(.scan.yara.matches, .name == "MALFORMED_OLE_HEADER") )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_macros.

Indicators Matched (1)

FieldMatchValue
file.explode(attachments[])[].scan.yara.matches[].nameequalsMALFORMED_OLE_HEADER

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                any(.scan.yara.matches, .name == \"MALFORMED_OLE_HEADER\")\n        )"
  type.inbound eq "true"

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"

Attachment: Malicious OneNote commands

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

Scans for OneNote attachments that contain suspicious commands that may indicate malicious activity.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesOneNote, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ ("one")
          or .file_extension in~ $file_extensions_common_archives
        )
        and any(file.explode(.),
                "onenote_file" in .flavors.yara
                and any(.scan.strings.strings,
                        strings.ilike(.,
                                      "*WshShell*",
                                      "*ExecuteCmdAsync*",
                                      "*CreateObject*",
                                      "*Wscript.Shell*",
                                      "*schtasks*",
                                      "*CreateProcess*",
                                      "*winmgmts*",
                                      "*SetEnvironmentVariable*",
                                      "*powershell*",
                                      "*echo off*"
                        )
                )
        )
)

Detection Logic

Scope: inbound message.

Scans for OneNote attachments that contain suspicious commands that may indicate malicious activity.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('one')
      • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), "onenote_file" in .flavors.yara and any(.scan.strings.strings, strings.ilike(., "*WshShell*", "*ExecuteCmdAsync*", "*CreateObject*", "*Wscript.Shell*", "*schtasks*", "*CreateProcess*", "*winmgmts*", "*SetEnvironmentVariable*", "*powershell*", "*echo off*" ) ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_common_archives.

Indicators Matched (12)

FieldMatchValue
attachments[].file_extensionmemberone
file.explode(attachments[])[].flavors.yaracontainsonenote_file
strings.ilikesubstring*WshShell*
strings.ilikesubstring*ExecuteCmdAsync*
strings.ilikesubstring*CreateObject*
strings.ilikesubstring*Wscript.Shell*
strings.ilikesubstring*schtasks*
strings.ilikesubstring*CreateProcess*
strings.ilikesubstring*winmgmts*
strings.ilikesubstring*SetEnvironmentVariable*
strings.ilikesubstring*powershell*
strings.ilikesubstring*echo off*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension eq "one"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.),\n                \"onenote_file\" in .flavors.yara\n                and any(.scan.strings.strings,\n                        strings.ilike(.,\n                                      \"*WshShell*\",\n                                      \"*ExecuteCmdAsync*\",\n                                      \"*CreateObject*\",\n                                      \"*Wscript.Shell*\",\n                                      \"*schtasks*\",\n                                      \"*CreateProcess*\",\n                                      \"*winmgmts*\",\n                                      \"*SetEnvironmentVariable*\",\n                                      \"*powershell*\",\n                                      \"*echo off*\"\n                        )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: Malicious zip file matching zipline campaign

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

Detects inbound ZIP attachments containing content that matches observed artifacts from a ZipLine campaign reported on by Telekom Security.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesLNK

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "zip"),
        any(file.explode(.),
            any(.scan.yara.matches, .name in ("zipline_delivery_telekom"))
        )
)

Detection Logic

Scope: inbound message.

Detects inbound ZIP attachments containing content that matches observed artifacts from a ZipLine campaign reported on by Telekom Security.

  1. inbound message
  2. any(filter(attachments, .file_type == "zip"), any(file.explode(.), any(.scan.yara.matches, .name in ("zipline_delivery_telekom")) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalszip
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberzipline_delivery_telekom

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"zip\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name in (\"zipline_delivery_telekom\"))\n        )\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"

Attachment: Microsoft 365 credential phishing

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

Looks for messages with an image attachment that contains words related to Microsoft, Office365, and passwords.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.links
  • headers
  • headers.auth_summary
  • headers.hops
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and length(filter(attachments, .file_type not in $file_types_images)) == 0
and (
  any(attachments,
      .file_type in $file_types_images
      and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft"))
  )
  or any(attachments,
         .file_type in $file_types_images
         and any(file.explode(.),
                 strings.ilike(.scan.ocr.raw, "*microsoft*", "*office")
                 and length(.scan.ocr.raw) < 1500
         )
  )
)
and any(attachments,
        .file_type in $file_types_images
        and any(file.explode(.),
                length(filter([
                                "password",
                                "unread messages",
                                "Shared Documents",
                                "expiration",
                                "expire",
                                "expiring",
                                "kindly",
                                "renew",
                                "review",
                                "emails failed",
                                "kicked out",
                                "prevented",
                                "storage",
                                "required now",
                                "cache",
                                "qr code",
                                "security update",
                                "invoice",
                                "retrieve",
                                "blocked"
                              ],
                              strings.icontains(..scan.ocr.raw, .)
                       )
                ) >= 2
                or (
                  any(ml.nlu_classifier(.scan.ocr.raw).intents,
                      .name == "cred_theft" and .confidence == "high"
                  )
                  and length(ml.nlu_classifier(.scan.ocr.raw).entities) > 1
                )
        )
)
and (
  not sender.email.domain.domain in ("microsoft.com", "sharepointonline.com")
  or not any(headers.hops,
             .authentication_results.compauth.verdict is not null
             and .authentication_results.compauth.verdict == "pass"
  )
)

// negate angelbeat urls and microsoft disclaimer links
and (
  length(body.links) > 0
  and not all(body.links,
              .href_url.domain.root_domain in (
                "abeatinfo.com",
                "abeatinvite.com",
                "aka.ms",
                "angelbeat.com"
              )
  )
)

// negate replies
and (
  (
    (length(headers.references) > 0 or headers.in_reply_to is null)
    and not (
      (
        strings.istarts_with(subject.subject, "RE:")
        or strings.istarts_with(subject.subject, "R:")
        or strings.istarts_with(subject.subject, "ODG:")
        or strings.istarts_with(subject.subject, "答复:")
        or strings.istarts_with(subject.subject, "AW:")
        or strings.istarts_with(subject.subject, "TR:")
        or strings.istarts_with(subject.subject, "FWD:")
        or regex.icontains(subject.subject,
                           '^(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:'
        )
      )
    )
  )
  or length(headers.references) == 0
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Looks for messages with an image attachment that contains words related to Microsoft, Office365, and passwords.

  1. inbound message
  2. length(filter(attachments, .file_type not in $file_types_images)) == 0
  3. any of:
    • any of attachments where all hold:
      • .file_type in $file_types_images
      • any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft"))
    • any of attachments where all hold:
      • .file_type in $file_types_images
      • any(file.explode(.), strings.ilike(.scan.ocr.raw, "*microsoft*", "*office") and length(.scan.ocr.raw) < 1500 )
  4. any of attachments where all hold:
    • .file_type in $file_types_images
    • any(file.explode(.), length(filter([ "password", "unread messages", "Shared Documents", "expiration", "expire", "expiring", "kindly", "renew", "review", "emails failed", "kicked out", "prevented", "storage", "required now", "cache", "qr code", "security update", "invoice", "retrieve", "blocked" ], strings.icontains(..scan.ocr.raw, .) ) ) >= 2 or ( any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence == "high" ) and length(ml.nlu_classifier(.scan.ocr.raw).entities) > 1 ) )
  5. any of:
    • not:
      • sender.email.domain.domain in ('microsoft.com', 'sharepointonline.com')
    • not:
      • any of headers.hops where all hold:
        • .authentication_results.compauth.verdict is set
        • .authentication_results.compauth.verdict is 'pass'
  6. all of:
    • length(body.links) > 0
    • not:
      • all of body.links where:
        • .href_url.domain.root_domain in ('abeatinfo.com', 'abeatinvite.com', 'aka.ms', 'angelbeat.com')
  7. any of:
    • all of:
      • any of:
        • length(headers.references) > 0
        • headers.in_reply_to is missing
      • none of:
        • subject.subject starts with 'RE:'
        • subject.subject starts with 'R:'
        • subject.subject starts with 'ODG:'
        • subject.subject starts with '答复:'
        • subject.subject starts with 'AW:'
        • subject.subject starts with 'TR:'
        • subject.subject starts with 'FWD:'
        • subject.subject matches '^(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?)\\s?:'
    • length(headers.references) == 0
  8. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  9. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  10. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].file_type, body.links, body.links[].href_url.domain.root_domain, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].authentication_results.compauth.verdict, headers.in_reply_to, headers.references, sender.email.domain.domain, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, ml.logo_detect, ml.nlu_classifier, profile.by_sender, regex.icontains, strings.icontains, strings.ilike, strings.istarts_with, strings.starts_with. Reference lists: $file_types_images, $high_trust_sender_root_domains.

Indicators Matched (5)

FieldMatchValue
strings.starts_withprefixMicrosoft
strings.ilikesubstring*microsoft*
strings.ilikesubstring*office
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  or
    not
      any(headers.hops)
        and
          headers.hops.authentication_results.compauth.verdict eq "pass"
          headers.hops.authentication_results.compauth.verdict is_not_null
    not
      sender.email.domain.domain in ["microsoft.com", "sharepointonline.com"]
  or
    and
      not
        or
          subject.subject regex_match "^(\\[[^\\]]+\\]\\s?){0,3}(re|fwd?)\\s?:"
          subject.subject starts_with "AW:"
          subject.subject starts_with "FWD:"
          subject.subject starts_with "ODG:"
          subject.subject starts_with "R:"
          subject.subject starts_with "RE:"
          subject.subject starts_with "TR:"
          subject.subject starts_with "答复:"
      or
        headers.in_reply_to is_null
        headers.references length_compare "0"
    headers.references length_compare "0"
  or
    any(attachments)
      and
        attachments.file_type macro "attachments[].file_type in file_types_images"
         macro "any(file.explode(.),\n                 strings.ilike(.scan.ocr.raw, \"*microsoft*\", \"*office\")\n                 and length(.scan.ocr.raw) < 1500\n         )"
    any(attachments)
      and
        attachments.file_type macro "attachments[].file_type in file_types_images"
         macro "any(ml.logo_detect(.).brands, strings.starts_with(.name, \"Microsoft\"))"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  any(attachments)
    and
      attachments.file_type macro "attachments[].file_type in file_types_images"
       macro "any(file.explode(.),\n                length(filter([\n                                \"password\",\n                                \"unread messages\",\n                                \"Shared Documents\",\n                                \"expiration\",\n                                \"expire\",\n                                \"expiring\",\n                                \"kindly\",\n                                \"renew\",\n                                \"review\",\n                                \"emails failed\",\n                                \"kicked out\",\n                                \"prevented\",\n                                \"storage\",\n                                \"required now\",\n                                \"cache\",\n                                \"qr code\",\n                                \"security update\",\n                                \"invoice\",\n                                \"retrieve\",\n                                \"blocked\"\n                              ],\n                              strings.icontains(..scan.ocr.raw, .)\n                       )\n                ) >= 2\n                or (\n                  any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                      .name == \"cred_theft\" and .confidence == \"high\"\n                  )\n                  and length(ml.nlu_classifier(.scan.ocr.raw).entities) > 1\n                )\n        )"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  not
     macro "all(body.links,\n              .href_url.domain.root_domain in (\n                \"abeatinfo.com\",\n                \"abeatinvite.com\",\n                \"aka.ms\",\n                \"angelbeat.com\"\n              )\n  )"
  body.links length_compare "0"
  length func_call "length(filter(attachments, .file_type not in $file_types_images)) == 0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
headers.in_reply_tois_null
  • (no value, null check)
field:"headers.in_reply_to" kind:is_null
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: Microsoft impersonation via PDF with link and suspicious language

#

Attachment: Microsoft OAuth credential harvesting via EML with embedded malicious links

#

Attachment: Microsoft SharePoint Impersonation via images in macro-enabled attachment

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

Detects macro-enabled Office documents (docx and similar extensions) that contain images with text mimicking Microsoft SharePoint file-sharing notifications. The embedded images reference SharePoint collaboration language such as invitations to edit or references to Microsoft 365 access controls, designed to deceive recipients into trusting the attachment.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, Macros, Image as content, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
// office docx
and any(filter(attachments, .file_extension in $file_extensions_macros),
        any(file.explode(.),
            // that contain sharepoint file share email wording in images
            strings.icontains(.scan.ocr.raw,
                              ' invited you to edit',
                              'This invite will only work for you and people with existing access',
                              ' use of Microsoft 365 and may contain content that is controlled by'
            )
        )
)

Detection Logic

Scope: inbound message.

Detects macro-enabled Office documents (docx and similar extensions) that contain images with text mimicking Microsoft SharePoint file-sharing notifications. The embedded images reference SharePoint collaboration language such as invitations to edit or references to Microsoft 365 access controls, designed to deceive recipients into trusting the attachment.

  1. inbound message
  2. any(filter(attachments, .file_extension in $file_extensions_macros), any(file.explode(.), // that contain sharepoint file share email wording in images strings.icontains(.scan.ocr.raw, ' invited you to edit', 'This invite will only work for you and people with existing access', ' use of Microsoft 365 and may contain content that is controlled by' ) ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, strings.icontains. Reference lists: $file_extensions_macros.

Indicators Matched (3)

FieldMatchValue
strings.icontainssubstring invited you to edit
strings.icontainssubstringThis invite will only work for you and people with existing access
strings.icontainssubstring use of Microsoft 365 and may contain content that is controlled by

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_extension in $file_extensions_macros),\n        any(file.explode(.),\n            // that contain sharepoint file share email wording in images\n            strings.icontains(.scan.ocr.raw,\n                              ' invited you to edit',\n                              'This invite will only work for you and people with existing access',\n                              ' use of Microsoft 365 and may contain content that is controlled by'\n            )\n        )\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"

Attachment: MS Office or RTF file with Shell.Explorer.1 com object with embedded LNK

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

Detects embedded Shell.Explorer.1 COM objects containing LNK files within various file types.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (.file_type == "rtf" or .file_extension in $file_extensions_macros)
        and any(file.explode(.),
                any(.scan.yara.matches,
                    strings.starts_with(.name, "ShellExplorer1_LNK_")
                )
        )
)

Detection Logic

Scope: inbound message.

Detects embedded Shell.Explorer.1 COM objects containing LNK files within various file types.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type is 'rtf'
      • .file_extension in $file_extensions_macros
    • any(file.explode(.), any(.scan.yara.matches, strings.starts_with(.name, "ShellExplorer1_LNK_") ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.starts_with. Reference lists: $file_extensions_macros.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalsrtf
strings.starts_withprefixShellExplorer1_LNK_

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
        attachments.file_type eq "rtf"
       macro "any(file.explode(.),\n                any(.scan.yara.matches,\n                    strings.starts_with(.name, \"ShellExplorer1_LNK_\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: MS OOXML file created by Administrator with zero edit time

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

Detects inbound PowerPoint (.pptx) and other MS OOXML attachments where the file creator is listed as 'Administrator' and the total edit time is zero minutes, while missing the 'TitlesOfParts' metadata field. This pattern may indicate programmatically generated or suspicious presentation files.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type in ("pptx", "docx")),
        beta.parse_exif(.).creator == "Administrator"
        and any(beta.parse_exif(.).fields,
                .key == "TotalEditTime" and .value == "0"
        )
        and not 'TitlesOfParts' in map(beta.parse_exif(.).fields, .key)
)

Detection Logic

Scope: inbound message.

Detects inbound PowerPoint (.pptx) and other MS OOXML attachments where the file creator is listed as 'Administrator' and the total edit time is zero minutes, while missing the 'TitlesOfParts' metadata field. This pattern may indicate programmatically generated or suspicious presentation files.

  1. inbound message
  2. any(filter(attachments, .file_type in ("pptx", "docx")), beta.parse_exif(.).creator == "Administrator" and any(beta.parse_exif(.).fields, .key == "TotalEditTime" and .value == "0" ) and not 'TitlesOfParts' in map(beta.parse_exif(.).fields, .key) )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif.

Indicators Matched (4)

FieldMatchValue
attachments[].file_typememberpptx
attachments[].file_typememberdocx
beta.parse_exif(filter(attachments)[]).fields[].keyequalsTotalEditTime
beta.parse_exif(filter(attachments)[]).fields[].valueequals0

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type in (\"pptx\", \"docx\")),\n        beta.parse_exif(.).creator == \"Administrator\"\n        and any(beta.parse_exif(.).fields,\n                .key == \"TotalEditTime\" and .value == \"0\"\n        )\n        and not 'TitlesOfParts' in map(beta.parse_exif(.).fields, .key)\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"

Attachment: MSI installer file

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

Recursively scans files and archives to detect MSI installer files. Coercing a target user to run an MSI can be used as part of an 'IT Support' or 'software update' social engineering attack. Execution of the delivered MSI could enable the attacker to execute malicious code on the target user's host.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and (
  any(attachments, .file_extension =~ "msi")
  or (
    any(attachments,
        .file_extension in~ $file_extensions_common_archives
        and any(file.explode(.), .file_extension =~ "msi")
    )
  )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect MSI installer files. Coercing a target user to run an MSI can be used as part of an 'IT Support' or 'software update' social engineering attack. Execution of the delivered MSI could enable the attacker to execute malicious code on the target user's host.

  1. inbound message
  2. any of:
    • any of attachments where:
      • .file_extension is 'msi'
    • any of attachments where all hold:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), .file_extension =~ "msi")

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalsmsi
file.explode(attachments[])[].file_extensionequalsmsi

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.), .file_extension =~ \"msi\")"
    any(attachments)
      attachments.file_extension eq "msi"
  type.inbound eq "true"

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"

Attachment: Office document loads remote document template

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

Recursively scans archives and Office documents to detect remote document template injection.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          (
            // office files
            .file_extension in~ $file_extensions_macros
            or .file_extension in~ $file_extensions_common_archives
            or (
              .file_extension is null
              and .file_type == "unknown"
              and .content_type == "application/octet-stream"
              and .size < 100000000
            )
          )
          and any(file.explode(.),
                  .flavors.mime == "text/xml"
                  and any(.scan.strings.strings,
                          regex.icontains(., "Target.{0,20}http.{0,200}dotm")
                  )
          )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans archives and Office documents to detect remote document template injection.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), .flavors.mime == "text/xml" and any(.scan.strings.strings, regex.icontains(., "Target.{0,20}http.{0,200}dotm") ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, regex.icontains. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (4)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
file.explode(attachments[])[].flavors.mimeequalstext/xml
regex.icontainsregexTarget.{0,20}http.{0,200}dotm

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                  .flavors.mime == \"text/xml\"\n                  and any(.scan.strings.strings,\n                          regex.icontains(., \"Target.{0,20}http.{0,200}dotm\")\n                  )\n          )"
  type.inbound eq "true"

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"

Attachment: Office document with VSTO add-in

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

Recursively scans files and archives to detect Office documents with VSTO Add-ins.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesScripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.reply_to
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or .file_extension in~ $file_extensions_common_archives
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.),
                .file_extension in~ (
                  "doc",
                  "docm",
                  "docx",
                  "dot",
                  "dotm",
                  "xls",
                  "xlsx",
                  "xlsm",
                  "xlm",
                  "xlsb",
                  "xlt",
                  "xltm",
                  "ppt",
                  "pptx",
                  "pptm",
                  "ppsm"
                )
                and any(.scan.exiftool.fields,
                        .key == "Tag_AssemblyLocation"
                        and strings.ilike(.value, "*.vsto*")
                        and not strings.ilike(.value, 'C:\Program Files*')
                        and not any($org_domains, strings.contains(..value, .))
                )
        )
)
// the message is unsolicited and no false positives
and (
  not profile.by_sender().solicited
  or (
    length(headers.reply_to) > 0
    and all(headers.reply_to, .email.email not in $recipient_emails)
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect Office documents with VSTO Add-ins.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), .file_extension in~ ( "doc", "docm", "docx", "dot", "dotm", "xls", "xlsx", "xlsm", "xlm", "xlsb", "xlt", "xltm", "ppt", "pptx", "pptm", "ppsm" ) and any(.scan.exiftool.fields, .key == "Tag_AssemblyLocation" and strings.ilike(.value, "*.vsto*") and not strings.ilike(.value, 'C:\Program Files*') and not any($org_domains, strings.contains(..value, .)) ) )
  3. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • length(headers.reply_to) > 0
      • all of headers.reply_to where:
        • .email.email not in $recipient_emails
  4. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, headers.reply_to, headers.reply_to[].email.email, type.inbound. Sensors: file.explode, profile.by_sender, strings.contains, strings.ilike. Reference lists: $file_extensions_common_archives, $file_extensions_macros, $org_domains, $recipient_emails.

Indicators Matched (20)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
file.explode(attachments[])[].file_extensionmemberdoc
file.explode(attachments[])[].file_extensionmemberdocm
file.explode(attachments[])[].file_extensionmemberdocx
file.explode(attachments[])[].file_extensionmemberdot
file.explode(attachments[])[].file_extensionmemberdotm
file.explode(attachments[])[].file_extensionmemberxls
file.explode(attachments[])[].file_extensionmemberxlsx
file.explode(attachments[])[].file_extensionmemberxlsm
file.explode(attachments[])[].file_extensionmemberxlm
file.explode(attachments[])[].file_extensionmemberxlsb
8 more
file.explode(attachments[])[].file_extensionmemberxlt
file.explode(attachments[])[].file_extensionmemberxltm
file.explode(attachments[])[].file_extensionmemberppt
file.explode(attachments[])[].file_extensionmemberpptx
file.explode(attachments[])[].file_extensionmemberpptm
file.explode(attachments[])[].file_extensionmemberppsm
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsTag_AssemblyLocation
strings.ilikesubstring*.vsto*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                .file_extension in~ (\n                  \"doc\",\n                  \"docm\",\n                  \"docx\",\n                  \"dot\",\n                  \"dotm\",\n                  \"xls\",\n                  \"xlsx\",\n                  \"xlsm\",\n                  \"xlm\",\n                  \"xlsb\",\n                  \"xlt\",\n                  \"xltm\",\n                  \"ppt\",\n                  \"pptx\",\n                  \"pptm\",\n                  \"ppsm\"\n                )\n                and any(.scan.exiftool.fields,\n                        .key == \"Tag_AssemblyLocation\"\n                        and strings.ilike(.value, \"*.vsto*\")\n                        and not strings.ilike(.value, 'C:\\Program Files*')\n                        and not any($org_domains, strings.contains(..value, .))\n                )\n        )"
  or
    and
      headers.reply_to length_compare "0"
       macro "all(headers.reply_to, .email.email not in $recipient_emails)"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: Office file contains OLE relationship to credential phishing page

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

Office file OLE relationship link is a credential page, or contains credential phishing language.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and length(file.oletools(.).relationships) < 500
        and any(file.oletools(.).relationships,
                (
                  any(ml.nlu_classifier(ml.link_analysis(.target_url).final_dom.display_text
                      ).intents,
                      .name == "cred_theft"
                      and .confidence in ("medium", "high")
                  )
                  and .target_url.domain.root_domain not in (
                    "google.com",
                    "goo.gl"
                  )
                  and ml.link_analysis(.target_url).effective_url.domain.domain != "login.microsoftonline.com"
                )
                or ml.link_analysis(.target_url).credphish.disposition == "phishing"
        )
)
and (
  (
    profile.by_sender().prevalence in ("new", "outlier")
    and not profile.by_sender().solicited
  )
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Office file OLE relationship link is a credential page, or contains credential phishing language.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • length(file.oletools(.).relationships) < 500
    • any(file.oletools(.).relationships, ( any(ml.nlu_classifier(ml.link_analysis(.target_url).final_dom.display_text ).intents, .name == "cred_theft" and .confidence in ("medium", "high") ) and .target_url.domain.root_domain not in ( "google.com", "goo.gl" ) and ml.link_analysis(.target_url).effective_url.domain.domain != "login.microsoftonline.com" ) or ml.link_analysis(.target_url).credphish.disposition == "phishing" )
  3. any of:
    • all of:
      • profile.by_sender().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.oletools, ml.link_analysis, ml.nlu_classifier, profile.by_sender. Reference lists: $file_extensions_macros.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
ml.nlu_classifier(ml.link_analysis(file.oletools(attachments[]).relationships[].target_url).final_dom.display_text).intents[].nameequalscred_theft
ml.nlu_classifier(ml.link_analysis(file.oletools(attachments[]).relationships[].target_url).final_dom.display_text).intents[].confidencemembermedium
ml.nlu_classifier(ml.link_analysis(file.oletools(attachments[]).relationships[].target_url).final_dom.display_text).intents[].confidencememberhigh

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
      length func_call "length(file.oletools(.).relationships) < 500"
       macro "any(file.oletools(.).relationships,\n                (\n                  any(ml.nlu_classifier(ml.link_analysis(.target_url).final_dom.display_text\n                      ).intents,\n                      .name == \"cred_theft\"\n                      and .confidence in (\"medium\", \"high\")\n                  )\n                  and .target_url.domain.root_domain not in (\n                    \"google.com\",\n                    \"goo.gl\"\n                  )\n                  and ml.link_analysis(.target_url).effective_url.domain.domain != \"login.microsoftonline.com\"\n                )\n                or ml.link_analysis(.target_url).credphish.disposition == \"phishing\"\n        )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender func_call "profile.by_sender().solicited"
      profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
  type.inbound eq "true"

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"

Attachment: Office file with credential phishing URLs

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

Detects Office documents containing embedded URLs that redirect to credential phishing pages. The rule filters out standard XML namespace and schema URLs commonly found in legitimate Office documents, then analyzes remaining URLs for malicious content using machine learning link analysis.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
// Filter to Office documents that contain 1-3 non-schema URLs
and any(filter(attachments,
               // Only check Office documents that can contain macros/embedded content
               .file_extension in $file_extensions_macros

               // Count URLs after filtering out common XML namespace/schema URLs
               and 0 < sum(map(map(file.explode(.),
                                   // Filter out standard XML namespace URLs that appear in all Office docs
                                   filter(.scan.url.urls,
                                          // Exclude OpenXML format schemas
                                          .domain.domain not in (
                                            'schemas.openxmlformats.org',
                                            'schemas.microsoft.com',
                                            'www.w3.org'
                                          )
                                          // Additional Microsoft domain exclusion
                                          and not .domain.domain in (
                                            'microsoft.com',
                                            'wps.cn' // WPS is a china based alt to MS Office and used in namespaces of the documents created by that product
                                          )
                                          // Exclude Dublin Core persistent URLs (metadata schemas)
                                          and not (
                                            .domain.domain == 'purl.org'
                                            and strings.starts_with(.path,
                                                                    '/dc/'
                                            )
                                          )
                                          // Exclude Dublin Core XML schemas
                                          and not (
                                            .domain.domain == "dublincore.org"
                                            and strings.starts_with(.path,
                                                                    '/schemas/xmls/'
                                            )
                                          )
                                   )
                               ),
                               // Count URLs in each exploded file component
                               length(.)
                           )
               ) <= 3 // Only process attachments with 3 or fewer non-schema URLs
        ),
        // For the filtered Office documents, check for malicious URLs
        any(file.explode(.),
            any(
                // Apply the same URL filtering to remove XML namespace noise
                filter(.scan.url.urls,
                       .domain.domain not in (
                         'schemas.openxmlformats.org',
                         'schemas.microsoft.com',
                         'www.w3.org'
                       )
                       and not .domain.domain in (
                         'microsoft.com',
                         'wps.cn' // WPS is a china based alt to MS Office and used in namespaces of the documents created by that product
                       )
                       and not (
                         .domain.domain == 'purl.org'
                         and strings.starts_with(.path, '/dc/')
                       )
                       and not (
                         .domain.domain == "dublincore.org"
                         and strings.starts_with(.path, '/schemas/xmls/')
                       )
                ),
                // Run link analysis on the filtered URLs to detect phishing
                ml.link_analysis(.).credphish.disposition == "phishing"
                // confidence is only returned when brands, if it's not there, consider this true
                // this ensures if there is a brand, the confidence is high
                // and allows matching when there is no confidence
                and coalesce(ml.link_analysis(.).credphish.confidence == "high",
                             true
                )
                and not (
                  ml.link_analysis(.).credphish.brand.name is not null
                  and ml.link_analysis(.).credphish.brand.name == "GoDaddy"
                  and strings.icontains(ml.link_analysis(.).final_dom.inner_text,
                                        'is parked free, courtesy of GoDaddy.com.'
                  )
                  and strings.icontains(ml.link_analysis(.).final_dom.inner_text,
                                        'Get This Domain'
                  )
                )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects Office documents containing embedded URLs that redirect to credential phishing pages. The rule filters out standard XML namespace and schema URLs commonly found in legitimate Office documents, then analyzes remaining URLs for malicious content using machine learning link analysis.

  1. inbound message
  2. any(filter(attachments, // Only check Office documents that can contain macros/embedded content .file_extension in $file_extensions_macros // Count URLs after filtering out common XML namespace/schema URLs and 0 < sum(map(map(file.explode(.), // Filter out standard XML namespace URLs that appear in all Office docs filter(.scan.url.urls, // Exclude OpenXML format schemas .domain.domain not in ( 'schemas.openxmlformats.org', 'schemas.microsoft.com', 'www.w3.org' ) // Additional Microsoft domain exclusion and not .domain.domain in ( 'microsoft.com', 'wps.cn' // WPS is a china based alt to MS Office and used in namespaces of the documents created by that product ) // Exclude Dublin Core persistent URLs (metadata schemas) and not ( .domain.domain == 'purl.org' and strings.starts_with(.path, '/dc/' ) ) // Exclude Dublin Core XML schemas and not ( .domain.domain == "dublincore.org" and strings.starts_with(.path, '/schemas/xmls/' ) ) ) ), // Count URLs in each exploded file component length(.) ) ) <= 3 // Only process attachments with 3 or fewer non-schema URLs ), // For the filtered Office documents, check for malicious URLs any(file.explode(.), any( // Apply the same URL filtering to remove XML namespace noise filter(.scan.url.urls, .domain.domain not in ( 'schemas.openxmlformats.org', 'schemas.microsoft.com', 'www.w3.org' ) and not .domain.domain in ( 'microsoft.com', 'wps.cn' // WPS is a china based alt to MS Office and used in namespaces of the documents created by that product ) and not ( .domain.domain == 'purl.org' and strings.starts_with(.path, '/dc/') ) and not ( .domain.domain == "dublincore.org" and strings.starts_with(.path, '/schemas/xmls/') ) ), // Run link analysis on the filtered URLs to detect phishing ml.link_analysis(.).credphish.disposition == "phishing" // confidence is only returned when brands, if it's not there, consider this true // this ensures if there is a brand, the confidence is high // and allows matching when there is no confidence and coalesce(ml.link_analysis(.).credphish.confidence == "high", true ) and not ( ml.link_analysis(.).credphish.brand.name is not null and ml.link_analysis(.).credphish.brand.name == "GoDaddy" and strings.icontains(ml.link_analysis(.).final_dom.inner_text, 'is parked free, courtesy of GoDaddy.com.' ) and strings.icontains(ml.link_analysis(.).final_dom.inner_text, 'Get This Domain' ) ) ) ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, ml.link_analysis, strings.icontains, strings.starts_with. Reference lists: $file_extensions_macros.

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments,\n               // Only check Office documents that can contain macros/embedded content\n               .file_extension in $file_extensions_macros\n\n               // Count URLs after filtering out common XML namespace/schema URLs\n               and 0 < sum(map(map(file.explode(.),\n                                   // Filter out standard XML namespace URLs that appear in all Office docs\n                                   filter(.scan.url.urls,\n                                          // Exclude OpenXML format schemas\n                                          .domain.domain not in (\n                                            'schemas.openxmlformats.org',\n                                            'schemas.microsoft.com',\n                                            'www.w3.org'\n                                          )\n                                          // Additional Microsoft domain exclusion\n                                          and not .domain.domain in (\n                                            'microsoft.com',\n                                            'wps.cn' // WPS is a china based alt to MS Office and used in namespaces of the documents created by that product\n                                          )\n                                          // Exclude Dublin Core persistent URLs (metadata schemas)\n                                          and not (\n                                            .domain.domain == 'purl.org'\n                                            and strings.starts_with(.path,\n                                                                    '/dc/'\n                                            )\n                                          )\n                                          // Exclude Dublin Core XML schemas\n                                          and not (\n                                            .domain.domain == \"dublincore.org\"\n                                            and strings.starts_with(.path,\n                                                                    '/schemas/xmls/'\n                                            )\n                                          )\n                                   )\n                               ),\n                               // Count URLs in each exploded file component\n                               length(.)\n                           )\n               ) <= 3 // Only process attachments with 3 or fewer non-schema URLs\n        ),\n        // For the filtered Office documents, check for malicious URLs\n        any(file.explode(.),\n            any(\n                // Apply the same URL filtering to remove XML namespace noise\n                filter(.scan.url.urls,\n                       .domain.domain not in (\n                         'schemas.openxmlformats.org',\n                         'schemas.microsoft.com',\n                         'www.w3.org'\n                       )\n                       and not .domain.domain in (\n                         'microsoft.com',\n                         'wps.cn' // WPS is a china based alt to MS Office and used in namespaces of the documents created by that product\n                       )\n                       and not (\n                         .domain.domain == 'purl.org'\n                         and strings.starts_with(.path, '/dc/')\n                       )\n                       and not (\n                         .domain.domain == \"dublincore.org\"\n                         and strings.starts_with(.path, '/schemas/xmls/')\n                       )\n                ),\n                // Run link analysis on the filtered URLs to detect phishing\n                ml.link_analysis(.).credphish.disposition == \"phishing\"\n                // confidence is only returned when brands, if it's not there, consider this true\n                // this ensures if there is a brand, the confidence is high\n                // and allows matching when there is no confidence\n                and coalesce(ml.link_analysis(.).credphish.confidence == \"high\",\n                             true\n                )\n                and not (\n                  ml.link_analysis(.).credphish.brand.name is not null\n                  and ml.link_analysis(.).credphish.brand.name == \"GoDaddy\"\n                  and strings.icontains(ml.link_analysis(.).final_dom.inner_text,\n                                        'is parked free, courtesy of GoDaddy.com.'\n                  )\n                  and strings.icontains(ml.link_analysis(.).final_dom.inner_text,\n                                        'Get This Domain'\n                  )\n                )\n            )\n        )\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"

Attachment: Office file with document sharing and browser instruction lures

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

Detects macro-enabled attachments containing document sharing language (sent, shared, forwarded) combined with browser interaction instructions (copy, right-click) or common email disclaimers. These tactics are often used to trick users into enabling macros or following malicious instructions.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesSocial engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments,
               .file_extension in $file_extensions_macros
               // limit the size to reduce FPs, the larger the document, the more likely it is for FPs on benign automated reports
               and .size < 2000000
        ),
        // Detection Note: There are multiple regex patterns used in multiple places, it'll be important to keep them in sync
        any(file.explode(.),
            // document sharing lure
            (
              length(.scan.strings.raw, ) < 1000
              and regex.icontains(.scan.strings.raw,
                                  '(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)',
              )
            )

            // ocr output
            or (
              length(.scan.ocr.raw) < 1000
              and regex.icontains(.scan.ocr.raw,
                                  '(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)',
              )
            )
            or (
              length(.scan.ocr.raw) < 500
              and strings.ends_with(.scan.ocr.raw, 'REVIEW DOCUMENTS')
            )
        )
        // copy/paste stuff or disclaimer text in the OCR output
        and (
          any(file.explode(.),
              (
                length(.scan.strings.raw, ) < 1000
                and (
                  regex.icontains(.scan.strings.raw,
                                  '(?:copy (?:and paste)?|right.?click)(?:\s+\w+\s*){0,9}browser',
                                  'click.{0,50}(?:above|below|button) to (?:access|open)'
                  )
                )
              )

              // ocr output
              or (
                length(.scan.ocr.raw) < 1000
                and (
                  regex.icontains(.scan.ocr.raw,
                                  '(?:copy (?:and paste)?|right.?click)(?:\s+\w+\s*){0,9}browser',
                                  'click.{0,50}(?:above|below|button) to (?:access|open)'
                  )
                )
              )
              or 5 of (
                strings.icontains(.scan.ocr.raw,
                                  'confidential and intended solely'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'intended solely for the use of'
                ),
                strings.icontains(.scan.ocr.raw, 'intended only for the people'),
                strings.icontains(.scan.ocr.raw, 'intended recipient'),
                strings.icontains(.scan.ocr.raw, 'received this email in error'),
                strings.icontains(.scan.ocr.raw,
                                  'notify the sender immediately'
                ),
                strings.icontains(.scan.ocr.raw, 'delete it from your system'),
                strings.icontains(.scan.ocr.raw, 'delete the email from'),
                strings.icontains(.scan.ocr.raw, 'virus-free'),
                strings.icontains(.scan.ocr.raw, 'scan for viruses'),
                strings.icontains(.scan.ocr.raw, 'legally binding agreement'),
                strings.icontains(.scan.ocr.raw, 'informational purposes only'),
                strings.icontains(.scan.ocr.raw,
                                  'any attachments are confidential'
                ),
                strings.icontains(.scan.ocr.raw, 'loss or damage arising'),
                strings.icontains(.scan.ocr.raw, 'responsibility for any loss'),
                strings.icontains(.scan.ocr.raw, 'unauthorised and prohibited'),
                strings.icontains(.scan.ocr.raw, 'subject to legal privilege'),
                strings.icontains(.scan.ocr.raw,
                                  'The information contained in or attached'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'The information contained in this email'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'people to whom it is addressed'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'received this in error, please inform'
                ),
                strings.icontains(.scan.ocr.raw, 'inform the sender and/or'),
                strings.icontains(.scan.ocr.raw,
                                  'immediately and delete the material'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'then delete the email from your inbox'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'confidential and/or privileged material'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'confidential and / or legally privileged'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'The information transmitted is intended'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'other than the intended recipient is prohibited'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'intended for use by the addressee'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'taking of any action in reliance upon'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'distribution is strictly prohibited'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'communication from the sender is confidential'
                ),
                strings.icontains(.scan.ocr.raw, 'use by the recipient'),
                strings.icontains(.scan.ocr.raw,
                                  'and others authorized to receive it'
                ),
                strings.icontains(.scan.ocr.raw, 'you are hereby notified'),
                strings.icontains(.scan.ocr.raw,
                                  'action in relation of the contents of this information'
                ),
                strings.icontains(.scan.ocr.raw,
                                  'The information contained in this'
                ),
                strings.icontains(.scan.ocr.raw, 'you are not the recipient'),
                strings.icontains(.scan.ocr.raw, 'may be unlawful'),
              )
          )
        )
)

Detection Logic

Scope: inbound message.

Detects macro-enabled attachments containing document sharing language (sent, shared, forwarded) combined with browser interaction instructions (copy, right-click) or common email disclaimers. These tactics are often used to trick users into enabling macros or following malicious instructions.

  1. inbound message
  2. any(filter(attachments, .file_extension in $file_extensions_macros // limit the size to reduce FPs, the larger the document, the more likely it is for FPs on benign automated reports and .size < 2000000 ), // Detection Note: There are multiple regex patterns used in multiple places, it'll be important to keep them in sync any(file.explode(.), // document sharing lure ( length(.scan.strings.raw, ) < 1000 and regex.icontains(.scan.strings.raw, '(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)', ) ) // ocr output or ( length(.scan.ocr.raw) < 1000 and regex.icontains(.scan.ocr.raw, '(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)', ) ) or ( length(.scan.ocr.raw) < 500 and strings.ends_with(.scan.ocr.raw, 'REVIEW DOCUMENTS') ) ) // copy/paste stuff or disclaimer text in the OCR output and ( any(file.explode(.), ( length(.scan.strings.raw, ) < 1000 and ( regex.icontains(.scan.strings.raw, '(?:copy (?:and paste)?|right.?click)(?:\s+\w+\s*){0,9}browser', 'click.{0,50}(?:above|below|button) to (?:access|open)' ) ) ) // ocr output or ( length(.scan.ocr.raw) < 1000 and ( regex.icontains(.scan.ocr.raw, '(?:copy (?:and paste)?|right.?click)(?:\s+\w+\s*){0,9}browser', 'click.{0,50}(?:above|below|button) to (?:access|open)' ) ) ) or 5 of ( strings.icontains(.scan.ocr.raw, 'confidential and intended solely' ), strings.icontains(.scan.ocr.raw, 'intended solely for the use of' ), strings.icontains(.scan.ocr.raw, 'intended only for the people'), strings.icontains(.scan.ocr.raw, 'intended recipient'), strings.icontains(.scan.ocr.raw, 'received this email in error'), strings.icontains(.scan.ocr.raw, 'notify the sender immediately' ), strings.icontains(.scan.ocr.raw, 'delete it from your system'), strings.icontains(.scan.ocr.raw, 'delete the email from'), strings.icontains(.scan.ocr.raw, 'virus-free'), strings.icontains(.scan.ocr.raw, 'scan for viruses'), strings.icontains(.scan.ocr.raw, 'legally binding agreement'), strings.icontains(.scan.ocr.raw, 'informational purposes only'), strings.icontains(.scan.ocr.raw, 'any attachments are confidential' ), strings.icontains(.scan.ocr.raw, 'loss or damage arising'), strings.icontains(.scan.ocr.raw, 'responsibility for any loss'), strings.icontains(.scan.ocr.raw, 'unauthorised and prohibited'), strings.icontains(.scan.ocr.raw, 'subject to legal privilege'), strings.icontains(.scan.ocr.raw, 'The information contained in or attached' ), strings.icontains(.scan.ocr.raw, 'The information contained in this email' ), strings.icontains(.scan.ocr.raw, 'people to whom it is addressed' ), strings.icontains(.scan.ocr.raw, 'received this in error, please inform' ), strings.icontains(.scan.ocr.raw, 'inform the sender and/or'), strings.icontains(.scan.ocr.raw, 'immediately and delete the material' ), strings.icontains(.scan.ocr.raw, 'then delete the email from your inbox' ), strings.icontains(.scan.ocr.raw, 'confidential and/or privileged material' ), strings.icontains(.scan.ocr.raw, 'confidential and / or legally privileged' ), strings.icontains(.scan.ocr.raw, 'The information transmitted is intended' ), strings.icontains(.scan.ocr.raw, 'other than the intended recipient is prohibited' ), strings.icontains(.scan.ocr.raw, 'intended for use by the addressee' ), strings.icontains(.scan.ocr.raw, 'taking of any action in reliance upon' ), strings.icontains(.scan.ocr.raw, 'distribution is strictly prohibited' ), strings.icontains(.scan.ocr.raw, 'communication from the sender is confidential' ), strings.icontains(.scan.ocr.raw, 'use by the recipient'), strings.icontains(.scan.ocr.raw, 'and others authorized to receive it' ), strings.icontains(.scan.ocr.raw, 'you are hereby notified'), strings.icontains(.scan.ocr.raw, 'action in relation of the contents of this information' ), strings.icontains(.scan.ocr.raw, 'The information contained in this' ), strings.icontains(.scan.ocr.raw, 'you are not the recipient'), strings.icontains(.scan.ocr.raw, 'may be unlawful'), ) ) ) )

Inspects: attachments[].file_extension, attachments[].size, type.inbound. Sensors: file.explode, regex.icontains, strings.ends_with, strings.icontains. Reference lists: $file_extensions_macros.

Indicators Matched (43)

FieldMatchValue
regex.icontainsregex(?:sent|shared|forwarded|provided|invited|received)(?:\s+\w+){0,9}\s+(?:document|file|attachment)
strings.ends_withsuffixREVIEW DOCUMENTS
regex.icontainsregex(?:copy (?:and paste)?|right.?click)(?:\s+\w+\s*){0,9}browser
regex.icontainsregexclick.{0,50}(?:above|below|button) to (?:access|open)
strings.icontainssubstringconfidential and intended solely
strings.icontainssubstringintended solely for the use of
strings.icontainssubstringintended only for the people
strings.icontainssubstringintended recipient
strings.icontainssubstringreceived this email in error
strings.icontainssubstringnotify the sender immediately
strings.icontainssubstringdelete it from your system
strings.icontainssubstringdelete the email from
31 more
strings.icontainssubstringvirus-free
strings.icontainssubstringscan for viruses
strings.icontainssubstringlegally binding agreement
strings.icontainssubstringinformational purposes only
strings.icontainssubstringany attachments are confidential
strings.icontainssubstringloss or damage arising
strings.icontainssubstringresponsibility for any loss
strings.icontainssubstringunauthorised and prohibited
strings.icontainssubstringsubject to legal privilege
strings.icontainssubstringThe information contained in or attached
strings.icontainssubstringThe information contained in this email
strings.icontainssubstringpeople to whom it is addressed
strings.icontainssubstringreceived this in error, please inform
strings.icontainssubstringinform the sender and/or
strings.icontainssubstringimmediately and delete the material
strings.icontainssubstringthen delete the email from your inbox
strings.icontainssubstringconfidential and/or privileged material
strings.icontainssubstringconfidential and / or legally privileged
strings.icontainssubstringThe information transmitted is intended
strings.icontainssubstringother than the intended recipient is prohibited
strings.icontainssubstringintended for use by the addressee
strings.icontainssubstringtaking of any action in reliance upon
strings.icontainssubstringdistribution is strictly prohibited
strings.icontainssubstringcommunication from the sender is confidential
strings.icontainssubstringuse by the recipient
strings.icontainssubstringand others authorized to receive it
strings.icontainssubstringyou are hereby notified
strings.icontainssubstringaction in relation of the contents of this information
strings.icontainssubstringThe information contained in this
strings.icontainssubstringyou are not the recipient
strings.icontainssubstringmay be unlawful

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments,\n               .file_extension in $file_extensions_macros\n               // limit the size to reduce FPs, the larger the document, the more likely it is for FPs on benign automated reports\n               and .size < 2000000\n        ),\n        // Detection Note: There are multiple regex patterns used in multiple places, it'll be important to keep them in sync\n        any(file.explode(.),\n            // document sharing lure\n            (\n              length(.scan.strings.raw, ) < 1000\n              and regex.icontains(.scan.strings.raw,\n                                  '(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)',\n              )\n            )\n\n            // ocr output\n            or (\n              length(.scan.ocr.raw) < 1000\n              and regex.icontains(.scan.ocr.raw,\n                                  '(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)',\n              )\n            )\n            or (\n              length(.scan.ocr.raw) < 500\n              and strings.ends_with(.scan.ocr.raw, 'REVIEW DOCUMENTS')\n            )\n        )\n        // copy/paste stuff or disclaimer text in the OCR output\n        and (\n          any(file.explode(.),\n              (\n                length(.scan.strings.raw, ) < 1000\n                and (\n                  regex.icontains(.scan.strings.raw,\n                                  '(?:copy (?:and paste)?|right.?click)(?:\\s+\\w+\\s*){0,9}browser',\n                                  'click.{0,50}(?:above|below|button) to (?:access|open)'\n                  )\n                )\n              )\n\n              // ocr output\n              or (\n                length(.scan.ocr.raw) < 1000\n                and (\n                  regex.icontains(.scan.ocr.raw,\n                                  '(?:copy (?:and paste)?|right.?click)(?:\\s+\\w+\\s*){0,9}browser',\n                                  'click.{0,50}(?:above|below|button) to (?:access|open)'\n                  )\n                )\n              )\n              or 5 of (\n                strings.icontains(.scan.ocr.raw,\n                                  'confidential and intended solely'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'intended solely for the use of'\n                ),\n                strings.icontains(.scan.ocr.raw, 'intended only for the people'),\n                strings.icontains(.scan.ocr.raw, 'intended recipient'),\n                strings.icontains(.scan.ocr.raw, 'received this email in error'),\n                strings.icontains(.scan.ocr.raw,\n                                  'notify the sender immediately'\n                ),\n                strings.icontains(.scan.ocr.raw, 'delete it from your system'),\n                strings.icontains(.scan.ocr.raw, 'delete the email from'),\n                strings.icontains(.scan.ocr.raw, 'virus-free'),\n                strings.icontains(.scan.ocr.raw, 'scan for viruses'),\n                strings.icontains(.scan.ocr.raw, 'legally binding agreement'),\n                strings.icontains(.scan.ocr.raw, 'informational purposes only'),\n                strings.icontains(.scan.ocr.raw,\n                                  'any attachments are confidential'\n                ),\n                strings.icontains(.scan.ocr.raw, 'loss or damage arising'),\n                strings.icontains(.scan.ocr.raw, 'responsibility for any loss'),\n                strings.icontains(.scan.ocr.raw, 'unauthorised and prohibited'),\n                strings.icontains(.scan.ocr.raw, 'subject to legal privilege'),\n                strings.icontains(.scan.ocr.raw,\n                                  'The information contained in or attached'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'The information contained in this email'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'people to whom it is addressed'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'received this in error, please inform'\n                ),\n                strings.icontains(.scan.ocr.raw, 'inform the sender and/or'),\n                strings.icontains(.scan.ocr.raw,\n                                  'immediately and delete the material'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'then delete the email from your inbox'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'confidential and/or privileged material'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'confidential and / or legally privileged'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'The information transmitted is intended'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'other than the intended recipient is prohibited'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'intended for use by the addressee'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'taking of any action in reliance upon'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'distribution is strictly prohibited'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'communication from the sender is confidential'\n                ),\n                strings.icontains(.scan.ocr.raw, 'use by the recipient'),\n                strings.icontains(.scan.ocr.raw,\n                                  'and others authorized to receive it'\n                ),\n                strings.icontains(.scan.ocr.raw, 'you are hereby notified'),\n                strings.icontains(.scan.ocr.raw,\n                                  'action in relation of the contents of this information'\n                ),\n                strings.icontains(.scan.ocr.raw,\n                                  'The information contained in this'\n                ),\n                strings.icontains(.scan.ocr.raw, 'you are not the recipient'),\n                strings.icontains(.scan.ocr.raw, 'may be unlawful'),\n              )\n          )\n        )\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"

Attachment: Office file with suspicious function calls or downloaded file path

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

Attached Office file contains suspicious function calls or known malicious file path pattern.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          // office files
          .file_extension in~ $file_extensions_macros
          or .file_extension in~ $file_extensions_common_archives
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000
          )
        )
        and (
          any(file.explode(.),
              (
                any(.scan.strings.strings,
                    strings.ilike(., '*URLDownloadToFile*')
                )
                and any(.scan.strings.strings, strings.ilike(., '*Auto_Open*'))
              )
              or any(.scan.strings.strings,
                     regex.icontains(.,
                                     'C:\\[A-Za-z]{7}\\[A-Za-z]{7}\\[A-Za-z]{7}'
                     )
              )
          )
        )
)
and (
  (
    profile.by_sender().prevalence in ("new", "outlier")
    and not profile.by_sender().solicited
  )
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Attached Office file contains suspicious function calls or known malicious file path pattern.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension in $file_extensions_common_archives
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000
    • ( any(file.explode(.), ( any(.scan.strings.strings, strings.ilike(., '*URLDownloadToFile*') ) and any(.scan.strings.strings, strings.ilike(., '*Auto_Open*')) ) or any(.scan.strings.strings, regex.icontains(., 'C:\\[A-Za-z]{7}\\[A-Za-z]{7}\\[A-Za-z]{7}' ) ) ) )
  3. any of:
    • all of:
      • profile.by_sender().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  4. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, profile.by_sender, regex.icontains, strings.ilike. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
strings.ilikesubstring*URLDownloadToFile*
strings.ilikesubstring*Auto_Open*
regex.icontainsregexC:\\[A-Za-z]{7}\\[A-Za-z]{7}\\[A-Za-z]{7}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "(\n          any(file.explode(.),\n              (\n                any(.scan.strings.strings,\n                    strings.ilike(., '*URLDownloadToFile*')\n                )\n                and any(.scan.strings.strings, strings.ilike(., '*Auto_Open*'))\n              )\n              or any(.scan.strings.strings,\n                     regex.icontains(.,\n                                     'C:\\\\[A-Za-z]{7}\\\\[A-Za-z]{7}\\\\[A-Za-z]{7}'\n                     )\n              )\n          )\n        )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender func_call "profile.by_sender().solicited"
      profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: OLE external relationship containing file scheme link to executable filetype

#

Attachment: OLE external relationship containing file scheme link to IP address

#

Attachment: Password-protected PDF with fake document indicators

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

Detects PDF attachments that are password protected and matching YARA signatures looking for specific content observed in previous activity.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesEncryption, Evasion, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(attachments) == 1
and any(filter(attachments, .file_type == "pdf"),
        //
        // This rule makes use of a beta feature and is subject to change without notice
        // using the beta featuer in custom rules is not suggested until it has been formally released.
        //
        any(beta.parse_exif(.).fields,
            strings.icontains(.value, 'password protected')
        )
        and any(file.explode(.),
                any(.scan.yara.matches,
                    .name in ("pwd_protected_pdf_fake_document_1")
                )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments that are password protected and matching YARA signatures looking for specific content observed in previous activity.

  1. inbound message
  2. length(attachments) == 1
  3. any(filter(attachments, .file_type == "pdf"), // // This rule makes use of a beta feature and is subject to change without notice // using the beta featuer in custom rules is not suggested until it has been formally released. // any(beta.parse_exif(.).fields, strings.icontains(.value, 'password protected') ) and any(file.explode(.), any(.scan.yara.matches, .name in ("pwd_protected_pdf_fake_document_1") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif, file.explode, strings.icontains.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
strings.icontainssubstringpassword protected
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpwd_protected_pdf_fake_document_1

Stages and Predicates

Stage 1: mql_rule

and
  attachments length_compare "1"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        //\n        // This rule makes use of a beta feature and is subject to change without notice\n        // using the beta featuer in custom rules is not suggested until it has been formally released.\n        //\n        any(beta.parse_exif(.).fields,\n            strings.icontains(.value, 'password protected')\n        )\n        and any(file.explode(.),\n                any(.scan.yara.matches,\n                    .name in (\"pwd_protected_pdf_fake_document_1\")\n                )\n        )\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"

Attachment: PDF Attachment with links to workers.dev

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

Detects inbound messages containing PDF attachments with fewer than 5 pages that, when analyzed, contain URLs pointing to workers.dev subdomains. This pattern indicates potential abuse of Cloudflare Workers infrastructure to host malicious content delivered via PDF documents.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Free subdomain host, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        beta.parse_exif(.).page_count <= 2
        and any(file.explode(.),
                any(.scan.url.urls, .domain.root_domain == "workers.dev")
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing PDF attachments with fewer than 5 pages that, when analyzed, contain URLs pointing to workers.dev subdomains. This pattern indicates potential abuse of Cloudflare Workers infrastructure to host malicious content delivered via PDF documents.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), beta.parse_exif(.).page_count <= 2 and any(file.explode(.), any(.scan.url.urls, .domain.root_domain == "workers.dev") ) )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif, file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.url.urls[].domain.root_domainequalsworkers.dev

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        beta.parse_exif(.).page_count <= 2\n        and any(file.explode(.),\n                any(.scan.url.urls, .domain.root_domain == \"workers.dev\")\n        )\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"

Attachment: PDF bid/proposal lure with credential theft indicators

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

Detects single-page PDF attachments containing bid, proposal, RFP, RFQ, or quotation-related lures combined with high-confidence credential theft language or suspicious domains. The rule examines various locations including PDF URLs, OCR content, file names, subject lines, and message body for these indicators.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesPDF, Social engineering, Free file host, Free subdomain host

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.links
  • sender.email
  • subject
  • type

Rule Body

type.inbound
// only one attachment
and length(attachments) == 1
// only pdfs with one page
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
and any(attachments, .file_type == 'pdf' and beta.parse_exif(.).page_count == 1)
// two of these...
and 2 of (
  // bid/rfp/proposal phrases commonly observed in lures which are in the display text of a url from the pdf
  any(attachments,
      any(file.explode(.),
          any(.scan.url.urls,
              regex.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
                              '(?:\b(?:request|review)\b.{1,5}\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)'
              )
          )
      )
  ),
  (
    // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message
    any([subject.base, sender.display_name, body.current_thread.text],
        regex.icontains(., '\b(?:bid|proposal|rfp|rfq|quotation)\b')
    )
  ),
  // bid/rfp/proposal phrases commonly observed in lures which are in the file name
  any(attachments,
      regex.icontains(.file_name, '\b(?:bid|proposal|rfp|rfq|quotation)\b')
  ),
  any(attachments,
      any(file.explode(.),
          // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf
          regex.icontains(.scan.ocr.raw,
                          '(?:\b(?:request|review)\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)'
          )
      )
  ),
  (
    any(attachments,
        any(file.explode(.),
            any(.scan.url.urls,
                // bid/rfp/proposal phrases commonly observed in lures which are in the url
                regex.icontains(.url,
                                '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'
                )
            )
        )
    )
  )
)

// ocr indicates high confidence cred theft
and (
  any(attachments,
      any(file.explode(.),
          any(ml.nlu_classifier(.scan.ocr.raw).intents,
              .name == 'cred_theft' and .confidence == 'high'
          )
          or any(ml.nlu_classifier(.scan.ocr.raw).topics,
                 .name == 'Purchase Orders' and .confidence == 'high'
          )
      )
  )
  // message body current thread indicates high confidence cred theft
  or any(ml.nlu_classifier(body.current_thread.text).intents,
         .name == 'cred_theft' and .confidence == 'high'
  )
  // message body current thread indicates high confidence cred theft
  or any(ml.nlu_classifier(body.current_thread.text).topics,
         .name == 'Purchase Orders' and .confidence == 'high'
  )
)

// pdf contains some suspicious url domain
and (
  any(attachments,
      any(file.explode(.),
          any(.scan.url.urls,
              .domain.root_domain in $self_service_creation_platform_domains
              or .domain.domain in $self_service_creation_platform_domains
              or .domain.root_domain in $free_file_hosts
              or .domain.domain in $free_file_hosts
              or .domain.root_domain in $free_subdomain_hosts
              or .domain.domain in $free_subdomain_hosts
              or .domain.tld in $suspicious_tlds
              or .domain.domain in $url_shorteners
              or .domain.root_domain in $url_shorteners
          )
      )
  )
)
// we dont want emails where all the links are docusign or dotloop
and not all(body.links,
            .href_url.domain.root_domain in (
              'docusign.net',
              'docusign.com',
              'dotloop.com'
            )
)
// negating solicited senders is necessary due to the nature of the rule
and not profile.by_sender().solicited

// negate workflow robot
and not (
  sender.email.local_part == 'workflow.robot'
  and sender.email.domain.root_domain == 'effem.com'
)

Detection Logic

Scope: inbound message.

Detects single-page PDF attachments containing bid, proposal, RFP, RFQ, or quotation-related lures combined with high-confidence credential theft language or suspicious domains. The rule examines various locations including PDF URLs, OCR content, file names, subject lines, and message body for these indicators.

  1. inbound message
  2. length(attachments) == 1
  3. any of attachments where all hold:
    • .file_type is 'pdf'
    • beta.parse_exif(.).page_count == 1
  4. at least 2 of:
    • any of attachments where:
      • any(file.explode(.), any(.scan.url.urls, regex.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text, '(?:\b(?:request|review)\b.{1,5}\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)' ) ) )
    • ( // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message any([subject.base, sender.display_name, body.current_thread.text], regex.icontains(., '\b(?:bid|proposal|rfp|rfq|quotation)\b') ) )
    • any of attachments where:
      • .file_name matches '\\b(?:bid|proposal|rfp|rfq|quotation)\\b'
    • any of attachments where:
      • any(file.explode(.), // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf regex.icontains(.scan.ocr.raw, '(?:\b(?:request|review)\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)' ) )
    • any of attachments where:
      • any(file.explode(.), any(.scan.url.urls, // bid/rfp/proposal phrases commonly observed in lures which are in the url regex.icontains(.url, '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)' ) ) )
  5. any of:
    • any of attachments where:
      • any(file.explode(.), any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == 'cred_theft' and .confidence == 'high' ) or any(ml.nlu_classifier(.scan.ocr.raw).topics, .name == 'Purchase Orders' and .confidence == 'high' ) )
    • any(ml.nlu_classifier(body.current_thread.text).intents, .name == 'cred_theft' and .confidence == 'high' )
    • any(ml.nlu_classifier(body.current_thread.text).topics, .name == 'Purchase Orders' and .confidence == 'high' )
  6. any of attachments where:
    • any(file.explode(.), any(.scan.url.urls, .domain.root_domain in $self_service_creation_platform_domains or .domain.domain in $self_service_creation_platform_domains or .domain.root_domain in $free_file_hosts or .domain.domain in $free_file_hosts or .domain.root_domain in $free_subdomain_hosts or .domain.domain in $free_subdomain_hosts or .domain.tld in $suspicious_tlds or .domain.domain in $url_shorteners or .domain.root_domain in $url_shorteners ) )
  7. not:
    • all of body.links where:
      • .href_url.domain.root_domain in ('docusign.net', 'docusign.com', 'dotloop.com')
  8. not:
    • profile.by_sender().solicited
  9. not:
    • all of:
      • sender.email.local_part is 'workflow.robot'
      • sender.email.domain.root_domain is 'effem.com'

Inspects: attachments[].file_name, attachments[].file_type, body.current_thread.text, body.links, body.links[].href_url.domain.root_domain, sender.display_name, sender.email.domain.root_domain, sender.email.local_part, subject.base, type.inbound. Sensors: beta.parse_exif, file.explode, ml.link_analysis, ml.nlu_classifier, profile.by_sender, regex.icontains. Reference lists: $free_file_hosts, $free_subdomain_hosts, $self_service_creation_platform_domains, $suspicious_tlds, $url_shorteners.

Indicators Matched (13)

FieldMatchValue
attachments[].file_typeequalspdf
regex.icontainsregex(?:\b(?:request|review)\b.{1,5}\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)
regex.icontainsregex\b(?:bid|proposal|rfp|rfq|quotation)\b
regex.icontainsregex(?:\b(?:request|review)\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)
regex.icontainsregex(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidenceequalshigh
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].nameequalsPurchase Orders
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].confidenceequalshigh
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidenceequalshigh
ml.nlu_classifier(body.current_thread.text).topics[].nameequalsPurchase Orders
1 more
ml.nlu_classifier(body.current_thread.text).topics[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      any(attachments)
        attachments.file_name regex_match "\\b(?:bid|proposal|rfp|rfq|quotation)\\b"
      any(attachments)
         macro "any(file.explode(.),\n            any(.scan.url.urls,\n                // bid/rfp/proposal phrases commonly observed in lures which are in the url\n                regex.icontains(.url,\n                                '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'\n                )\n            )\n        )"
    and
      any(attachments)
        attachments.file_name regex_match "\\b(?:bid|proposal|rfp|rfq|quotation)\\b"
      any(attachments)
         macro "any(file.explode(.),\n          // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf\n          regex.icontains(.scan.ocr.raw,\n                          '(?:\\b(?:request|review)\\b.{1,5}\\\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n          )\n      )"
    and
      any(attachments)
        attachments.file_name regex_match "\\b(?:bid|proposal|rfp|rfq|quotation)\\b"
      any(attachments)
         macro "any(file.explode(.),\n          any(.scan.url.urls,\n              regex.icontains(ml.link_analysis(., mode=\"aggressive\").final_dom.display_text,\n                              '(?:\\b(?:request|review)\\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n              )\n          )\n      )"
    and
      any(attachments)
        attachments.file_name regex_match "\\b(?:bid|proposal|rfp|rfq|quotation)\\b"
       macro "(\n    // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message\n    any([subject.base, sender.display_name, body.current_thread.text],\n        regex.icontains(., '\\b(?:bid|proposal|rfp|rfq|quotation)\\b')\n    )\n  )"
    and
      any(attachments)
         macro "any(file.explode(.),\n            any(.scan.url.urls,\n                // bid/rfp/proposal phrases commonly observed in lures which are in the url\n                regex.icontains(.url,\n                                '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'\n                )\n            )\n        )"
      any(attachments)
         macro "any(file.explode(.),\n          // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf\n          regex.icontains(.scan.ocr.raw,\n                          '(?:\\b(?:request|review)\\b.{1,5}\\\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n          )\n      )"
    and
      any(attachments)
         macro "any(file.explode(.),\n            any(.scan.url.urls,\n                // bid/rfp/proposal phrases commonly observed in lures which are in the url\n                regex.icontains(.url,\n                                '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'\n                )\n            )\n        )"
      any(attachments)
         macro "any(file.explode(.),\n          any(.scan.url.urls,\n              regex.icontains(ml.link_analysis(., mode=\"aggressive\").final_dom.display_text,\n                              '(?:\\b(?:request|review)\\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n              )\n          )\n      )"
    and
      any(attachments)
         macro "any(file.explode(.),\n            any(.scan.url.urls,\n                // bid/rfp/proposal phrases commonly observed in lures which are in the url\n                regex.icontains(.url,\n                                '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'\n                )\n            )\n        )"
       macro "(\n    // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message\n    any([subject.base, sender.display_name, body.current_thread.text],\n        regex.icontains(., '\\b(?:bid|proposal|rfp|rfq|quotation)\\b')\n    )\n  )"
    and
      any(attachments)
         macro "any(file.explode(.),\n          // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf\n          regex.icontains(.scan.ocr.raw,\n                          '(?:\\b(?:request|review)\\b.{1,5}\\\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n          )\n      )"
      any(attachments)
         macro "any(file.explode(.),\n          any(.scan.url.urls,\n              regex.icontains(ml.link_analysis(., mode=\"aggressive\").final_dom.display_text,\n                              '(?:\\b(?:request|review)\\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n              )\n          )\n      )"
    and
      any(attachments)
         macro "any(file.explode(.),\n          // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf\n          regex.icontains(.scan.ocr.raw,\n                          '(?:\\b(?:request|review)\\b.{1,5}\\\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n          )\n      )"
       macro "(\n    // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message\n    any([subject.base, sender.display_name, body.current_thread.text],\n        regex.icontains(., '\\b(?:bid|proposal|rfp|rfq|quotation)\\b')\n    )\n  )"
    and
      any(attachments)
         macro "any(file.explode(.),\n          any(.scan.url.urls,\n              regex.icontains(ml.link_analysis(., mode=\"aggressive\").final_dom.display_text,\n                              '(?:\\b(?:request|review)\\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\\b|\\b(?:bid|proposal|rfp|rfq|quotation)\\b.{1,5}\\b(?:request|review)\\b)'\n              )\n          )\n      )"
       macro "(\n    // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message\n    any([subject.base, sender.display_name, body.current_thread.text],\n        regex.icontains(., '\\b(?:bid|proposal|rfp|rfq|quotation)\\b')\n    )\n  )"
  any(attachments)
    and
      attachments.file_type eq "pdf"
      beta.parse_exif func_call "beta.parse_exif(.).page_count == 1"
  not
    and
      sender.email.domain.root_domain eq "effem.com"
      sender.email.local_part eq "workflow.robot"
  or
    any(attachments)
       macro "any(file.explode(.),\n          any(ml.nlu_classifier(.scan.ocr.raw).intents,\n              .name == 'cred_theft' and .confidence == 'high'\n          )\n          or any(ml.nlu_classifier(.scan.ocr.raw).topics,\n                 .name == 'Purchase Orders' and .confidence == 'high'\n          )\n      )"
     macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n         .name == 'cred_theft' and .confidence == 'high'\n  )"
     macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n         .name == 'Purchase Orders' and .confidence == 'high'\n  )"
  not
    profile.by_sender func_call "profile.by_sender().solicited"
  not
     macro "all(body.links,\n            .href_url.domain.root_domain in (\n              'docusign.net',\n              'docusign.com',\n              'dotloop.com'\n            )\n)"
  any(attachments)
     macro "any(file.explode(.),\n          any(.scan.url.urls,\n              .domain.root_domain in $self_service_creation_platform_domains\n              or .domain.domain in $self_service_creation_platform_domains\n              or .domain.root_domain in $free_file_hosts\n              or .domain.domain in $free_file_hosts\n              or .domain.root_domain in $free_subdomain_hosts\n              or .domain.domain in $free_subdomain_hosts\n              or .domain.tld in $suspicious_tlds\n              or .domain.domain in $url_shorteners\n              or .domain.root_domain in $url_shorteners\n          )\n      )"
  attachments length_compare "1"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

Attachment: PDF contains W9 or invoice YARA signatures

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

PDF attachment contains YARA signatures commonly associated with fraudulent W9 tax forms or invoice documents, which are frequently used in social engineering attacks to steal sensitive information or facilitate business email compromise.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name in ("w9_pdf_01", "invoice_pdf_01", "w9_pdf_IDs")
            )
        )
)

Detection Logic

Scope: inbound message.

PDF attachment contains YARA signatures commonly associated with fraudulent W9 tax forms or invoice documents, which are frequently used in social engineering attacks to steal sensitive information or facilitate business email compromise.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("w9_pdf_01", "invoice_pdf_01", "w9_pdf_IDs") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (4)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberw9_pdf_01
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberinvoice_pdf_01
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberw9_pdf_IDs

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name in (\"w9_pdf_01\", \"invoice_pdf_01\", \"w9_pdf_IDs\")\n            )\n        )\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"

Attachment: PDF credential phishing via wkhtmltopdf/Qt with suspicious link

#

Attachment: PDF file with link to fake Bitcoin exchange

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

Fraudulent message containing a PDF notification of unclaimed Bitcoin assets. The PDF file contains a link to a fake Cryptocurrency portal. Attempting to withdraw funds prompts the user to enter payment information.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesFree email provider, Impersonation: Brand, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • sender.email
  • type

Rule Body

type.inbound
and sender.email.domain.root_domain in $free_email_providers
and length(attachments) == 1
and all(attachments,
        .file_extension == "pdf"
        and regex.icontains(.file_name, '(\d\.\d{3,4}.{0,12}BTC|bitcoin)')
        and any(file.explode(.),
                .scan.exiftool.page_count >= 5
                and .depth == 0
                and length(filter(.scan.strings.strings,
                                  regex.match(., '^\/URI \(http.*')
                           )
                ) == 1
        )
)

Detection Logic

Scope: inbound message.

Fraudulent message containing a PDF notification of unclaimed Bitcoin assets. The PDF file contains a link to a fake Cryptocurrency portal. Attempting to withdraw funds prompts the user to enter payment information.

  1. inbound message
  2. sender.email.domain.root_domain in $free_email_providers
  3. length(attachments) == 1
  4. all of attachments where all hold:
    • .file_extension is 'pdf'
    • .file_name matches '(\\d\\.\\d{3,4}.{0,12}BTC|bitcoin)'
    • any(file.explode(.), .scan.exiftool.page_count >= 5 and .depth == 0 and length(filter(.scan.strings.strings, regex.match(., '^\/URI \(http.*') ) ) == 1 )

Inspects: attachments[].file_extension, attachments[].file_name, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, regex.icontains, regex.match. Reference lists: $free_email_providers.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionequalspdf
regex.icontainsregex(\d\.\d{3,4}.{0,12}BTC|bitcoin)
regex.matchregex^\/URI \(http.*

Stages and Predicates

Stage 1: mql_rule

and
  attachments length_compare "1"
  sender.email.domain.root_domain macro "sender.email.domain.root_domain in free_email_providers"
  type.inbound eq "true"
   macro "all(attachments,\n        .file_extension == \"pdf\"\n        and regex.icontains(.file_name, '(\\d\\.\\d{3,4}.{0,12}BTC|bitcoin)')\n        and any(file.explode(.),\n                .scan.exiftool.page_count >= 5\n                and .depth == 0\n                and length(filter(.scan.strings.strings,\n                                  regex.match(., '^\\/URI \\(http.*')\n                           )\n                ) == 1\n        )\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"

Attachment: PDF file with low reputation link to ZIP file (unsolicited)

#

Attachment: PDF file with low reputation links to suspicious filetypes (unsolicited)

#

Attachment: PDF file with recipient domain and ATT eCheckRun pattern

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

Detects PDF attachments with filenames containing the recipient's domain, potentially indicating targeted financial document spoofing.

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
  • recipients
  • recipients.to[0]
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        strings.icontains(.file_name, recipients.to[0].email.domain.sld)
        and strings.starts_with(.file_name, "ATT")
        and strings.icontains(.file_name, "eCheckRun")
)

Detection Logic

Scope: inbound message.

Detects PDF attachments with filenames containing the recipient's domain, potentially indicating targeted financial document spoofing.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), strings.icontains(.file_name, recipients.to[0].email.domain.sld) and strings.starts_with(.file_name, "ATT") and strings.icontains(.file_name, "eCheckRun") )

Inspects: attachments[].file_type, recipients.to[0].email.domain.sld, type.inbound. Sensors: strings.icontains, strings.starts_with.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
strings.starts_withprefixATT
strings.icontainssubstringeCheckRun

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        strings.icontains(.file_name, recipients.to[0].email.domain.sld)\n        and strings.starts_with(.file_name, \"ATT\")\n        and strings.icontains(.file_name, \"eCheckRun\")\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"

Attachment: PDF generated with wkhtmltopdf tool and default title

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

Detects PDF attachments that were generated using the wkhtmltopdf conversion tool, which converts HTML/CSS to PDF. This tool is commonly used by attackers to create legitimate-looking PDF documents from web content for social engineering purposes.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Callback Phishing, Credential Phishing, Malware/Ransomware
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_extension == "pdf"),
        strings.istarts_with(beta.parse_exif(.).producer, "Qt")
        and strings.icontains(beta.parse_exif(.).creator, "wkhtmltopdf")
        and beta.parse_exif(.).title == "Document"
)

Detection Logic

Scope: inbound message.

Detects PDF attachments that were generated using the wkhtmltopdf conversion tool, which converts HTML/CSS to PDF. This tool is commonly used by attackers to create legitimate-looking PDF documents from web content for social engineering purposes.

  1. inbound message
  2. any(filter(attachments, .file_extension == "pdf"), strings.istarts_with(beta.parse_exif(.).producer, "Qt") and strings.icontains(beta.parse_exif(.).creator, "wkhtmltopdf") and beta.parse_exif(.).title == "Document" )

Inspects: attachments[].file_extension, type.inbound. Sensors: beta.parse_exif, strings.icontains, strings.istarts_with.

Indicators Matched (3)

FieldMatchValue
attachments[].file_extensionequalspdf
strings.istarts_withprefixQt
strings.icontainssubstringwkhtmltopdf

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_extension == \"pdf\"),\n        strings.istarts_with(beta.parse_exif(.).producer, \"Qt\")\n        and strings.icontains(beta.parse_exif(.).creator, \"wkhtmltopdf\")\n        and beta.parse_exif(.).title == \"Document\"\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"

Attachment: PDF Grant Payment lure with embedded link

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

Inbound messages carrying a PDF attachment that references a 'Grant Payment Development' RFP or bid solicitation, often sent from compromised or spoofed education-sector (.k12, .esc) accounts. The PDF contains an embedded URL, consistent with a redirect to a credential-harvesting or malicious landing page disguised as bid documentation.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            strings.icontains(.scan.strings.raw, 'Grant Payment Development')
        )
        and any(file.explode(.), length(.scan.url.urls) > 0)
)

Detection Logic

Scope: inbound message.

Inbound messages carrying a PDF attachment that references a 'Grant Payment Development' RFP or bid solicitation, often sent from compromised or spoofed education-sector (.k12, .esc) accounts. The PDF contains an embedded URL, consistent with a redirect to a credential-harvesting or malicious landing page disguised as bid documentation.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), strings.icontains(.scan.strings.raw, 'Grant Payment Development') ) and any(file.explode(.), length(.scan.url.urls) > 0) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, strings.icontains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
strings.icontainssubstringGrant Payment Development

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            strings.icontains(.scan.strings.raw, 'Grant Payment Development')\n        )\n        and any(file.explode(.), length(.scan.url.urls) > 0)\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"

Attachment: PDF Object Hash - Encrypted PDFs with fake payment notification

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

Detects PDF attachments containing a specific object hash (63bf167b66091a4bc53e8944a76f6b08) that may indicate malicious content or known threat indicators.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .scan.pdf_obj_hash.object_hash == "63bf167b66091a4bc53e8944a76f6b08"
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing a specific object hash (63bf167b66091a4bc53e8944a76f6b08) that may indicate malicious content or known threat indicators.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .scan.pdf_obj_hash.object_hash == "63bf167b66091a4bc53e8944a76f6b08" ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.pdf_obj_hash.object_hashequals63bf167b66091a4bc53e8944a76f6b08

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .scan.pdf_obj_hash.object_hash == \"63bf167b66091a4bc53e8944a76f6b08\"\n        )\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"

Attachment: PDF Object Hash associated with a fake invoice and a W-9

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

Matching PDF Object Hash associated with a fake invoice followed by a W-9.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .scan.pdf_obj_hash.object_hash == "cc08b7eae4b6f5f4e897dd0998b90e21"
        )
)

Detection Logic

Scope: inbound message.

Matching PDF Object Hash associated with a fake invoice followed by a W-9.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .scan.pdf_obj_hash.object_hash == "cc08b7eae4b6f5f4e897dd0998b90e21" ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.pdf_obj_hash.object_hashequalscc08b7eae4b6f5f4e897dd0998b90e21

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .scan.pdf_obj_hash.object_hash == \"cc08b7eae4b6f5f4e897dd0998b90e21\"\n        )\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"

Attachment: PDF Object Hash associated with fake Canada Revenue Agency documents

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

Matching PDF Object Hash associated with chrome -> export to pdf of a shared document related to Canada's Revenue Agency.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .scan.pdf_obj_hash.object_hash == "cf509abbdc5aa6b1b759a216e3e570cf"
        )
)

Detection Logic

Scope: inbound message.

Matching PDF Object Hash associated with chrome -> export to pdf of a shared document related to Canada's Revenue Agency.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .scan.pdf_obj_hash.object_hash == "cf509abbdc5aa6b1b759a216e3e570cf" ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.pdf_obj_hash.object_hashequalscf509abbdc5aa6b1b759a216e3e570cf

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .scan.pdf_obj_hash.object_hash == \"cf509abbdc5aa6b1b759a216e3e570cf\"\n        )\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"

Attachment: PDF Object Hash with Blue File Icon

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

Detects PDF attachments containing a specific object hash (8638ef6bfe382a927aa12a18f2150757) associated with encrypted PDFs leading to cred phishing.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .scan.pdf_obj_hash.object_hash == "8638ef6bfe382a927aa12a18f2150757"
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing a specific object hash (8638ef6bfe382a927aa12a18f2150757) associated with encrypted PDFs leading to cred phishing.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .scan.pdf_obj_hash.object_hash == "8638ef6bfe382a927aa12a18f2150757" ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.pdf_obj_hash.object_hashequals8638ef6bfe382a927aa12a18f2150757

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .scan.pdf_obj_hash.object_hash == \"8638ef6bfe382a927aa12a18f2150757\"\n        )\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"

Attachment: PDF proposal with credential theft indicators

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

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • subject
  • type

Rule Body

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(filter(.scan.url.urls,
                                  not strings.istarts_with(.url, 'mailto')
                                  and not strings.istarts_with(.url, 'email:')
                                  and .domain.root_domain != sender.email.domain.root_domain
                                  and .domain.root_domain not in (
                                    'iso.org',
                                    'w3.org',
                                    'bfo.com', // pdf producer
                                    'camscanner.com', // pdf producer
                                  )
                           )
                ) == 1
        )
)
// 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.

  1. inbound message
  2. not:
    • all of:
      • any of:
        • subject.is_reply
        • subject.is_forward
      • any of:
        • length(headers.references) > 0
        • headers.in_reply_to is set
  3. length(filter(attachments, .file_type == "pdf")) == 1
  4. any of attachments where all hold:
    • .file_type is 'pdf'
    • .file_name matches '(?:proposal|bid|document|rf[pq])\\b'
    • beta.parse_exif(.).page_count == 1
    • any(ml.nlu_classifier(beta.ocr(.).text).intents, .name == "cred_theft" )
    • length(beta.ocr(.).text) < 2000
    • beta.ocr(.).success
    • any(file.explode(.), .depth == 0 and length(filter(.scan.url.urls, not strings.istarts_with(.url, 'mailto') and not strings.istarts_with(.url, 'email:') and .domain.root_domain != sender.email.domain.root_domain and .domain.root_domain not in ( 'iso.org', 'w3.org', 'bfo.com', // pdf producer 'camscanner.com', // pdf producer ) ) ) == 1 )
  5. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

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 (3)

FieldMatchValue
attachments[].file_typeequalspdf
regex.icontainsregex(?:proposal|bid|document|rf[pq])\b
ml.nlu_classifier(beta.ocr(attachments[]).text).intents[].nameequalscred_theft

Stages and Predicates

Stage 1: mql_rule

and
  not
    and
      or
        headers.in_reply_to is_not_null
        headers.references length_compare "0"
      or
        subject.is_forward eq "true"
        subject.is_reply eq "true"
  any(attachments)
    and
      attachments.file_name regex_match "(?:proposal|bid|document|rf[pq])\\b"
      attachments.file_type eq "pdf"
      beta.ocr func_call "beta.ocr(.).success"
      beta.parse_exif func_call "beta.parse_exif(.).page_count == 1"
      length func_call "length(beta.ocr(.).text) < 2000"
       macro "any(file.explode(.),\n                .depth == 0\n                and length(filter(.scan.url.urls,\n                                  not strings.istarts_with(.url, 'mailto')\n                                  and not strings.istarts_with(.url, 'email:')\n                                  and .domain.root_domain != sender.email.domain.root_domain\n                                  and .domain.root_domain not in (\n                                    'iso.org',\n                                    'w3.org',\n                                    'bfo.com', // pdf producer\n                                    'camscanner.com', // pdf producer\n                                  )\n                           )\n                ) == 1\n        )"
       macro "any(ml.nlu_classifier(beta.ocr(.).text).intents,\n                .name == \"cred_theft\"\n        )"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  length func_call "length(filter(attachments, .file_type == \"pdf\")) == 1"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.in_reply_tois_not_null(no value, null check)excludes:headers.in_reply_to
headers.referenceslength_compare0excludes:headers.references field:"headers.references" value:"0"
subject.is_forwardeqtrueexcludes:subject.is_forward field:"subject.is_forward" value:"true"
subject.is_replyeqtrueexcludes:subject.is_reply field:"subject.is_reply" value:"true"
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: PDF RFP lure

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

Detects inbound messages with PDF attachments that match a YARA signature identifying RFP-themed lure documents with a specific black and white lure.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, BEC/Fraud
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name == "pdf_rfp_bw_lure")
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages with PDF attachments that match a YARA signature identifying RFP-themed lure documents with a specific black and white lure.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name == "pdf_rfp_bw_lure") ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalspdf_rfp_bw_lure

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name == \"pdf_rfp_bw_lure\")\n        )\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"

Attachment: PDF templated investment lure

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

Detects inbound messages carrying PDF attachments that match a YARA signature for a recurring templated lure using a blue and white design theme.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name == "pdf_templated_lure_blue_white")
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages carrying PDF attachments that match a YARA signature for a recurring templated lure using a blue and white design theme.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name == "pdf_templated_lure_blue_white") ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalspdf_templated_lure_blue_white

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name == \"pdf_templated_lure_blue_white\")\n        )\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"

Attachment: PDF with a suspicious string and single URL

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

Detects single-page PDF attachments containing suspicious language such as 'View Document' or 'View PDF' along with exactly one URL, commonly used in credential theft attacks.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type == "pdf"
        and (
          //
          // This rule makes use of a beta feature and is subject to change without notice
          // using the beta feature in custom rules is not suggested until it has been formally released
          //
          // a single page pdf
          beta.parse_exif(.).page_count == 1
          // in some cases the pdf might have an invalid xref table
          // so we can instead use the number of pages in the pdf scanner
          or (
            beta.parse_exif(.).page_count == 0
            and any(beta.parse_exif(.).fields,
                    .key == "Warning" and .value == "Invalid xref table"
            )
            and length(filter(file.explode(.),
                              strings.istarts_with(.file_name, 'pdf_2_png_')
                       )
            ) == 1
          )
        )
        and any(file.explode(.),
                // the pdf contains specific suspicious wording
                // these are exact matches when split on new lines extracted from the text of the PDF from the scanPDF scanner
                any(.scan.strings.strings,
                    regex.icontains(.,
                                    // action!
                                    '^\s*(?:view documents?|view pdf|view presentation|preview new docusign|Download Secure PDF|VIEW DOCUMENT HERE|ACCESS DOCUMENT|REVIEW NEW SECURE DOCUMENT|OPEN SECURE VIEWER|DOWNLOAD RFP DOCUMENT|View Dashboard here|ACCESS SECURE DOCUMENTS|VIEW PROPOSAL DOCUMENTS|ACCESS / VIEW PROPOSAL DOCUMENT|Review & Sign Document|Open PDF|Access Document\(s\)|(?:P?RE)?VIEW SHARED DOCUMENT|New Secured Document|ACCESS SECURE RFP PORTAL|Please Review and Sign|Review and Validate|SECURE DOCUMENT|Open Document|View Details|Q!_Compensation/Salary Amendments\.pptx|PREVIEW DOCUMENT HERE|Download Tax Details Below:|Review and Sign Document|Review Document|Open Encrypted|OPEN DOCUMENT HERE|Click to read message|CLICK HERE TO VIEW DOCUMENTS|VIEW FULL DOCUMENT HERE|View Full Proposal)\s*$',
                                    // "secure fax"
                                    'View Secure Fax',
                                    // more fake errors
                                    'It seems there was an issue opening the document. Please view it online.',
                                    // fake adobe update
                                    'Update Adobe Viewer',
                                    // fake sharepoint wording
                                    'Learn more about messages protected by Microsoft',
                                    // fake encryption crap
                                    'This document is protected by 256-bit encryption.',
                                    // sent you a document
                                    '.*sent you a \S+ to review(?:\s*(?:and|&)\s*sign)$',
                                    '^You received a \S+ to review and sign$',
                                    // docusign
                                    '\s*DocuSign Contract Under Review\s*',
                                    'DOCUMENT PREVIEW',
                                    'PREVIEW DOCUMENT',
                                    'VIEW REMITTANCE COPY HERE',
                                    'shared a file with you',
                                    '(?:check your personal|view your) forecast',
                                    'full new state pension',
                                    'UN1TED STATES',
                                    'view secure documents'
                    )
                )
                // fake error messages
                or (
                  'Error' in~ .scan.strings.strings
                  and any(.scan.strings.strings,
                          regex.icontains(., '^\s*(?:View Video)\s*$')
                  )
                )
                // really terse PDF with link
                or (
                  length(.scan.strings.strings) == 1
                  and 'Some additional information here' in~ .scan.strings.strings
                )
        )
        and any(file.explode(.),
                .depth == 0
                and (
                  length(filter(.scan.url.urls,
                                // remove mailto: links
                                not strings.istarts_with(.url, 'mailto:')
                                and not strings.istarts_with(.url, 'email:')
                                // remove links found in exiftool output producer/creator
                                and not any([
                                              ..scan.exiftool.producer,
                                              ..scan.exiftool.creator
                                            ],
                                            . is not null
                                            and strings.icontains(.,
                                                                  ..domain.domain
                                            )
                                )
                                and not .domain.root_domain in ('pdf-tools.com')
                                and not .url in (
                                  'https://gamma.app/?utm_source=made-with-gamma'
                                )
                         )
                  ) == 1
                  or 
                  // there is only one unique domain
                  (
                    length(distinct(filter(.scan.url.urls,
                                           // remove mailto: links
                                           not strings.istarts_with(.url,
                                                                    'mailto:'
                                           )
                                           and not strings.istarts_with(.url,
                                                                        'email:'
                                           )
                                           // remove links found in exiftool output producer/creator
                                           and not any([
                                                         ..scan.exiftool.producer,
                                                         ..scan.exiftool.creator
                                                       ],
                                                       . is not null
                                                       and strings.icontains(.,
                                                                             ..domain.domain
                                                       )
                                           )
                                           and not .domain.root_domain in (
                                             'pdf-tools.com'
                                           )
                                           and not .url in (
                                             'https://gamma.app/?utm_source=made-with-gamma'
                                           )
                                    ),
                                    .domain.domain
                           )
                    ) == 1
                    // all of them are in self_service
                    and all(distinct(filter(.scan.url.urls,
                                            // remove mailto: links
                                            not strings.istarts_with(.url,
                                                                     'mailto:'
                                            )
                                            and not strings.istarts_with(.url,
                                                                         'email:'
                                            )
                                            // remove links found in exiftool output producer/creator
                                            and not any([
                                                          ..scan.exiftool.producer,
                                                          ..scan.exiftool.creator
                                                        ],
                                                        . is not null
                                                        and strings.icontains(.,
                                                                              ..domain.domain
                                                        )
                                            )
                                            and not .domain.root_domain in (
                                              'pdf-tools.com'
                                            )
                                            and not .url in (
                                              'https://gamma.app/?utm_source=made-with-gamma'
                                            )
                                     ),
                                     .domain.domain
                            ),
                            .domain.domain in $self_service_creation_platform_domains
                            or .domain.root_domain in $self_service_creation_platform_domains
                    )
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

Detects single-page PDF attachments containing suspicious language such as 'View Document' or 'View PDF' along with exactly one URL, commonly used in credential theft attacks.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • any of:
      • beta.parse_exif(.).page_count == 1
      • all of:
        • beta.parse_exif(.).page_count == 0
        • any(beta.parse_exif(.).fields, .key == "Warning" and .value == "Invalid xref table" )
        • length(filter(file.explode(.), strings.istarts_with(.file_name, 'pdf_2_png_') ) ) == 1
    • any(file.explode(.), // the pdf contains specific suspicious wording // these are exact matches when split on new lines extracted from the text of the PDF from the scanPDF scanner any(.scan.strings.strings, regex.icontains(., // action! '^\s*(?:view documents?|view pdf|view presentation|preview new docusign|Download Secure PDF|VIEW DOCUMENT HERE|ACCESS DOCUMENT|REVIEW NEW SECURE DOCUMENT|OPEN SECURE VIEWER|DOWNLOAD RFP DOCUMENT|View Dashboard here|ACCESS SECURE DOCUMENTS|VIEW PROPOSAL DOCUMENTS|ACCESS / VIEW PROPOSAL DOCUMENT|Review & Sign Document|Open PDF|Access Document\(s\)|(?:P?RE)?VIEW SHARED DOCUMENT|New Secured Document|ACCESS SECURE RFP PORTAL|Please Review and Sign|Review and Validate|SECURE DOCUMENT|Open Document|View Details|Q!_Compensation/Salary Amendments\.pptx|PREVIEW DOCUMENT HERE|Download Tax Details Below:|Review and Sign Document|Review Document|Open Encrypted|OPEN DOCUMENT HERE|Click to read message|CLICK HERE TO VIEW DOCUMENTS|VIEW FULL DOCUMENT HERE|View Full Proposal)\s*$', // "secure fax" 'View Secure Fax', // more fake errors 'It seems there was an issue opening the document. Please view it online.', // fake adobe update 'Update Adobe Viewer', // fake sharepoint wording 'Learn more about messages protected by Microsoft', // fake encryption crap 'This document is protected by 256-bit encryption.', // sent you a document '.*sent you a \S+ to review(?:\s*(?:and|&)\s*sign)$', '^You received a \S+ to review and sign$', // docusign '\s*DocuSign Contract Under Review\s*', 'DOCUMENT PREVIEW', 'PREVIEW DOCUMENT', 'VIEW REMITTANCE COPY HERE', 'shared a file with you', '(?:check your personal|view your) forecast', 'full new state pension', 'UN1TED STATES', 'view secure documents' ) ) // fake error messages or ( 'Error' in~ .scan.strings.strings and any(.scan.strings.strings, regex.icontains(., '^\s*(?:View Video)\s*$') ) ) // really terse PDF with link or ( length(.scan.strings.strings) == 1 and 'Some additional information here' in~ .scan.strings.strings ) )
    • any(file.explode(.), .depth == 0 and ( length(filter(.scan.url.urls, // remove mailto: links not strings.istarts_with(.url, 'mailto:') and not strings.istarts_with(.url, 'email:') // remove links found in exiftool output producer/creator and not any([ ..scan.exiftool.producer, ..scan.exiftool.creator ], . is not null and strings.icontains(., ..domain.domain ) ) and not .domain.root_domain in ('pdf-tools.com') and not .url in ( 'https://gamma.app/?utm_source=made-with-gamma' ) ) ) == 1 or // there is only one unique domain ( length(distinct(filter(.scan.url.urls, // remove mailto: links not strings.istarts_with(.url, 'mailto:' ) and not strings.istarts_with(.url, 'email:' ) // remove links found in exiftool output producer/creator and not any([ ..scan.exiftool.producer, ..scan.exiftool.creator ], . is not null and strings.icontains(., ..domain.domain ) ) and not .domain.root_domain in ( 'pdf-tools.com' ) and not .url in ( 'https://gamma.app/?utm_source=made-with-gamma' ) ), .domain.domain ) ) == 1 // all of them are in self_service and all(distinct(filter(.scan.url.urls, // remove mailto: links not strings.istarts_with(.url, 'mailto:' ) and not strings.istarts_with(.url, 'email:' ) // remove links found in exiftool output producer/creator and not any([ ..scan.exiftool.producer, ..scan.exiftool.creator ], . is not null and strings.icontains(., ..domain.domain ) ) and not .domain.root_domain in ( 'pdf-tools.com' ) and not .url in ( 'https://gamma.app/?utm_source=made-with-gamma' ) ), .domain.domain ), .domain.domain in $self_service_creation_platform_domains or .domain.root_domain in $self_service_creation_platform_domains ) ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif, file.explode, regex.icontains, strings.icontains, strings.istarts_with. Reference lists: $self_service_creation_platform_domains.

Indicators Matched (24)

FieldMatchValue
attachments[].file_typeequalspdf
beta.parse_exif(attachments[]).fields[].keyequalsWarning
beta.parse_exif(attachments[]).fields[].valueequalsInvalid xref table
strings.istarts_withprefixpdf_2_png_
regex.icontainsregex^\s*(?:view documents?|view pdf|view presentation|preview new docusign|Download Secure PDF|VIEW DOCUMENT HERE|ACCESS DOCUMENT|REVIEW NEW SECURE DOCUMENT|OPEN SECURE VIEWER|DOWNLOAD RFP DOCUMENT|View Dashboard here|ACCESS SECURE DOCUMENTS|VIEW PROPOSAL DOCUMENTS|ACCESS / VIEW PROPOSAL DOCUMENT|Review & Sign Document|Open PDF|Access Document\(s\)|(?:P?RE)?VIEW SHARED DOCUMENT|New Secured Document|ACCESS SECURE RFP PORTAL|Please Review and Sign|Review and Validate|SECURE DOCUMENT|Open Document|View Details|Q!_Compensation/Salary Amendments\.pptx|PREVIEW DOCUMENT HERE|Download Tax Details Below:|Review and Sign Document|Review Document|Open Encrypted|OPEN DOCUMENT HERE|Click to read message|CLICK HERE TO VIEW DOCUMENTS|VIEW FULL DOCUMENT HERE|View Full Proposal)\s*$
regex.icontainsregexView Secure Fax
regex.icontainsregexIt seems there was an issue opening the document. Please view it online.
regex.icontainsregexUpdate Adobe Viewer
regex.icontainsregexLearn more about messages protected by Microsoft
regex.icontainsregexThis document is protected by 256-bit encryption.
regex.icontainsregex.*sent you a \S+ to review(?:\s*(?:and|&)\s*sign)$
regex.icontainsregex^You received a \S+ to review and sign$
12 more
regex.icontainsregex\s*DocuSign Contract Under Review\s*
regex.icontainsregexDOCUMENT PREVIEW
regex.icontainsregexPREVIEW DOCUMENT
regex.icontainsregexVIEW REMITTANCE COPY HERE
regex.icontainsregexshared a file with you
regex.icontainsregex(?:check your personal|view your) forecast
regex.icontainsregexfull new state pension
regex.icontainsregexUN1TED STATES
regex.icontainsregexview secure documents
file.explode(attachments[])[].scan.strings.stringscontainsError
regex.icontainsregex^\s*(?:View Video)\s*$
file.explode(attachments[])[].scan.strings.stringscontainsSome additional information here

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          beta.parse_exif func_call "beta.parse_exif(.).page_count == 0"
          length func_call "length(filter(file.explode(.),\n                              strings.istarts_with(.file_name, 'pdf_2_png_')\n                       )\n            ) == 1"
           macro "any(beta.parse_exif(.).fields,\n                    .key == \"Warning\" and .value == \"Invalid xref table\"\n            )"
        beta.parse_exif func_call "beta.parse_exif(.).page_count == 1"
      attachments.file_type eq "pdf"
       macro "any(file.explode(.),\n                .depth == 0\n                and (\n                  length(filter(.scan.url.urls,\n                                // remove mailto: links\n                                not strings.istarts_with(.url, 'mailto:')\n                                and not strings.istarts_with(.url, 'email:')\n                                // remove links found in exiftool output producer/creator\n                                and not any([\n                                              ..scan.exiftool.producer,\n                                              ..scan.exiftool.creator\n                                            ],\n                                            . is not null\n                                            and strings.icontains(.,\n                                                                  ..domain.domain\n                                            )\n                                )\n                                and not .domain.root_domain in ('pdf-tools.com')\n                                and not .url in (\n                                  'https://gamma.app/?utm_source=made-with-gamma'\n                                )\n                         )\n                  ) == 1\n                  or \n                  // there is only one unique domain\n                  (\n                    length(distinct(filter(.scan.url.urls,\n                                           // remove mailto: links\n                                           not strings.istarts_with(.url,\n                                                                    'mailto:'\n                                           )\n                                           and not strings.istarts_with(.url,\n                                                                        'email:'\n                                           )\n                                           // remove links found in exiftool output producer/creator\n                                           and not any([\n                                                         ..scan.exiftool.producer,\n                                                         ..scan.exiftool.creator\n                                                       ],\n                                                       . is not null\n                                                       and strings.icontains(.,\n                                                                             ..domain.domain\n                                                       )\n                                           )\n                                           and not .domain.root_domain in (\n                                             'pdf-tools.com'\n                                           )\n                                           and not .url in (\n                                             'https://gamma.app/?utm_source=made-with-gamma'\n                                           )\n                                    ),\n                                    .domain.domain\n                           )\n                    ) == 1\n                    // all of them are in self_service\n                    and all(distinct(filter(.scan.url.urls,\n                                            // remove mailto: links\n                                            not strings.istarts_with(.url,\n                                                                     'mailto:'\n                                            )\n                                            and not strings.istarts_with(.url,\n                                                                         'email:'\n                                            )\n                                            // remove links found in exiftool output producer/creator\n                                            and not any([\n                                                          ..scan.exiftool.producer,\n                                                          ..scan.exiftool.creator\n                                                        ],\n                                                        . is not null\n                                                        and strings.icontains(.,\n                                                                              ..domain.domain\n                                                        )\n                                            )\n                                            and not .domain.root_domain in (\n                                              'pdf-tools.com'\n                                            )\n                                            and not .url in (\n                                              'https://gamma.app/?utm_source=made-with-gamma'\n                                            )\n                                     ),\n                                     .domain.domain\n                            ),\n                            .domain.domain in $self_service_creation_platform_domains\n                            or .domain.root_domain in $self_service_creation_platform_domains\n                    )\n                  )\n                )\n        )"
       macro "any(file.explode(.),\n                // the pdf contains specific suspicious wording\n                // these are exact matches when split on new lines extracted from the text of the PDF from the scanPDF scanner\n                any(.scan.strings.strings,\n                    regex.icontains(.,\n                                    // action!\n                                    '^\\s*(?:view documents?|view pdf|view presentation|preview new docusign|Download Secure PDF|VIEW DOCUMENT HERE|ACCESS DOCUMENT|REVIEW NEW SECURE DOCUMENT|OPEN SECURE VIEWER|DOWNLOAD RFP DOCUMENT|View Dashboard here|ACCESS SECURE DOCUMENTS|VIEW PROPOSAL DOCUMENTS|ACCESS / VIEW PROPOSAL DOCUMENT|Review & Sign Document|Open PDF|Access Document\\(s\\)|(?:P?RE)?VIEW SHARED DOCUMENT|New Secured Document|ACCESS SECURE RFP PORTAL|Please Review and Sign|Review and Validate|SECURE DOCUMENT|Open Document|View Details|Q!_Compensation/Salary Amendments\\.pptx|PREVIEW DOCUMENT HERE|Download Tax Details Below:|Review and Sign Document|Review Document|Open Encrypted|OPEN DOCUMENT HERE|Click to read message|CLICK HERE TO VIEW DOCUMENTS|VIEW FULL DOCUMENT HERE|View Full Proposal)\\s*$',\n                                    // \"secure fax\"\n                                    'View Secure Fax',\n                                    // more fake errors\n                                    'It seems there was an issue opening the document. Please view it online.',\n                                    // fake adobe update\n                                    'Update Adobe Viewer',\n                                    // fake sharepoint wording\n                                    'Learn more about messages protected by Microsoft',\n                                    // fake encryption crap\n                                    'This document is protected by 256-bit encryption.',\n                                    // sent you a document\n                                    '.*sent you a \\S+ to review(?:\\s*(?:and|&)\\s*sign)$',\n                                    '^You received a \\S+ to review and sign$',\n                                    // docusign\n                                    '\\s*DocuSign Contract Under Review\\s*',\n                                    'DOCUMENT PREVIEW',\n                                    'PREVIEW DOCUMENT',\n                                    'VIEW REMITTANCE COPY HERE',\n                                    'shared a file with you',\n                                    '(?:check your personal|view your) forecast',\n                                    'full new state pension',\n                                    'UN1TED STATES',\n                                    'view secure documents'\n                    )\n                )\n                // fake error messages\n                or (\n                  'Error' in~ .scan.strings.strings\n                  and any(.scan.strings.strings,\n                          regex.icontains(., '^\\s*(?:View Video)\\s*$')\n                  )\n                )\n                // really terse PDF with link\n                or (\n                  length(.scan.strings.strings) == 1\n                  and 'Some additional information here' in~ .scan.strings.strings\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: PDF with base64 JavaScript and eval functions

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

PDF attachment contains base64-encoded JavaScript variables with eval functions, indicating potential code obfuscation and execution techniques commonly used in malicious documents.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .depth == 0
            and any(.scan.yara.matches, .name in ("pdf_b64_js_var_eval", ))
        )
)

Detection Logic

Scope: inbound message.

PDF attachment contains base64-encoded JavaScript variables with eval functions, indicating potential code obfuscation and execution techniques commonly used in malicious documents.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .depth == 0 and any(.scan.yara.matches, .name in ("pdf_b64_js_var_eval", )) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_b64_js_var_eval

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .depth == 0\n            and any(.scan.yara.matches, .name in (\"pdf_b64_js_var_eval\", ))\n        )\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"

Attachment: PDF with blurry lure image

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

Detects PDF attachments containing a blurry image used in credential phishing lures.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name in ("pdf_lure_image_blurry", ))
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing a blurry image used in credential phishing lures.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("pdf_lure_image_blurry", )) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_lure_image_blurry

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name in (\"pdf_lure_image_blurry\", ))\n        )\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"

Attachment: PDF with credential theft language and invalid reply-to domain

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

Detects PDF attachments containing high-confidence credential theft language that references the recipient's email address, combined with an invalid reply-to domain header.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering, Spoofing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • headers.reply_to
  • recipients
  • recipients.to[0]
  • sender.email
  • type

Rule Body

type.inbound
and length(recipients.to) == 1
and recipients.to[0].email.domain.valid
and any(headers.reply_to, .email.email == "")
and any(attachments,
        .file_type == 'pdf'
        and any(file.explode(.),
                any(ml.nlu_classifier(.scan.strings.raw).intents,
                    .name == 'cred_theft' and .confidence == 'high'
                )
                and strings.icontains(.scan.strings.raw,
                                      recipients.to[0].email.email
                )
        )
)
// negate highly trusted sender domains unless they fail DMARC authentication or DMARC is missing
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.

Detects PDF attachments containing high-confidence credential theft language that references the recipient's email address, combined with an invalid reply-to domain header.

  1. inbound message
  2. length(recipients.to) == 1
  3. recipients.to[0].email.domain.valid
  4. any of headers.reply_to where:
    • .email.email is ''
  5. any of attachments where all hold:
    • .file_type is 'pdf'
    • any(file.explode(.), any(ml.nlu_classifier(.scan.strings.raw).intents, .name == 'cred_theft' and .confidence == 'high' ) and strings.icontains(.scan.strings.raw, recipients.to[0].email.email ) )
  6. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_type, headers.auth_summary.dmarc.pass, headers.reply_to, headers.reply_to[].email.email, recipients.to, recipients.to[0].email.domain.valid, recipients.to[0].email.email, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.nlu_classifier, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (4)

FieldMatchValue
headers.reply_to[].email.emailequals
attachments[].file_typeequalspdf
ml.nlu_classifier(file.explode(attachments[])[].scan.strings.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(attachments[])[].scan.strings.raw).intents[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type eq "pdf"
       macro "any(file.explode(.),\n                any(ml.nlu_classifier(.scan.strings.raw).intents,\n                    .name == 'cred_theft' and .confidence == 'high'\n                )\n                and strings.icontains(.scan.strings.raw,\n                                      recipients.to[0].email.email\n                )\n        )"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  any(headers.reply_to)
    headers.reply_to.email.email eq ""
  recipients.to length_compare "1"
  recipients.to[0].email.domain.valid eq "true"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
recipients.to[0].email.domain.valideq
  • true transforms: boolean corpus 15 (mql 15)
field:"recipients.to[0].email.domain.valid" kind:eq value:"true"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

Attachment: PDF with credential theft language and link to a free subdomain (unsolicited)

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

Detects messages with credential theft PDFs linking to free subdomains.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree subdomain host, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • type

Rule Body

type.inbound
and any(ml.nlu_classifier(body.current_thread.text).intents,
        .name == "cred_theft" and .confidence in ("medium", "high")
)
and any(attachments,
        .file_extension == "pdf"
        and any(file.explode(.),
                any(.scan.pdf.urls,
                    .domain.root_domain in $free_subdomain_hosts
                    and .domain.subdomain is not null
                    and .domain.subdomain != "www"
                )
                and any(ml.nlu_classifier(.scan.ocr.raw).intents,
                        .name == "cred_theft"
                        and .confidence in ("medium", "high")
                )
        )
)
// unsolicited
and (
  not profile.by_sender().solicited
  or profile.by_sender().any_messages_malicious_or_spam
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Detects messages with credential theft PDFs linking to free subdomains.

  1. inbound message
  2. any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence in ("medium", "high") )
  3. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any(file.explode(.), any(.scan.pdf.urls, .domain.root_domain in $free_subdomain_hosts and .domain.subdomain is not null and .domain.subdomain != "www" ) and any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence in ("medium", "high") ) )
  4. any of:
    • not:
      • profile.by_sender().solicited
    • profile.by_sender().any_messages_malicious_or_spam
  5. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, body.current_thread.text, type.inbound. Sensors: file.explode, ml.nlu_classifier, profile.by_sender. Reference lists: $free_subdomain_hosts.

Indicators Matched (7)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidencemembermedium
ml.nlu_classifier(body.current_thread.text).intents[].confidencememberhigh
attachments[].file_extensionequalspdf
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidencemembermedium
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidencememberhigh

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension eq "pdf"
       macro "any(file.explode(.),\n                any(.scan.pdf.urls,\n                    .domain.root_domain in $free_subdomain_hosts\n                    and .domain.subdomain is not null\n                    and .domain.subdomain != \"www\"\n                )\n                and any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                        .name == \"cred_theft\"\n                        and .confidence in (\"medium\", \"high\")\n                )\n        )"
  or
    not
      profile.by_sender func_call "profile.by_sender().solicited"
    profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"
   macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n        .name == \"cred_theft\" and .confidence in (\"medium\", \"high\")\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"

Attachment: PDF with CVE-2026-34621 lures

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

Detects PDF attachments containing YARA signatures associated with CVE-2026-34621's observed lures.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesPDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .depth == 0
            and any(.scan.yara.matches,
                    .name == "pdf_cve_2026_34621_observed_lures"
            )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing YARA signatures associated with CVE-2026-34621's observed lures.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .depth == 0 and any(.scan.yara.matches, .name == "pdf_cve_2026_34621_observed_lures" ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalspdf_cve_2026_34621_observed_lures

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .depth == 0\n            and any(.scan.yara.matches,\n                    .name == \"pdf_cve_2026_34621_observed_lures\"\n            )\n        )\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"

Attachment: PDF with eCheckRun lures

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

Detects PDF attachments matching yara rules looking for attachments containing artifacts from related to fake financial/invoice themes, including eCheckRun lures. These are commonly used to trick users into believe they have received legitmate electronic payment messages.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name in ("pdf_eCheckLure_format", ))
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments matching yara rules looking for attachments containing artifacts from related to fake financial/invoice themes, including eCheckRun lures. These are commonly used to trick users into believe they have received legitmate electronic payment messages.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("pdf_eCheckLure_format", )) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_eCheckLure_format

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name in (\"pdf_eCheckLure_format\", ))\n        )\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"

Attachment: PDF with embedded box-lure and javascript

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

Detects inbound messages containing a PDF attachment that matches YARA signatures looking for JavaScript functions or specific lure boxes that have been observed within malicious documents.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesPDF, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name in ("pdf_js_function_box_lure", "pdf_rect_size_box_lure")
            )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing a PDF attachment that matches YARA signatures looking for JavaScript functions or specific lure boxes that have been observed within malicious documents.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("pdf_js_function_box_lure", "pdf_rect_size_box_lure") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_js_function_box_lure
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_rect_size_box_lure

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name in (\"pdf_js_function_box_lure\", \"pdf_rect_size_box_lure\")\n            )\n        )\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"

Attachment: PDF with fake invoice using suspicious font sizing

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

PDF attachment contains a fake invoice with suspicious font size patterns and unique image sizes, typically used in fraudulent billing schemes.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Callback Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name == "pdf_fake_invoice_image_font_sizes"
            )
        )
)

Detection Logic

Scope: inbound message.

PDF attachment contains a fake invoice with suspicious font size patterns and unique image sizes, typically used in fraudulent billing schemes.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name == "pdf_fake_invoice_image_font_sizes" ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalspdf_fake_invoice_image_font_sizes

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name == \"pdf_fake_invoice_image_font_sizes\"\n            )\n        )\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"

Attachment: PDF with JSFck obfuscation

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

PDF attachment contains JavaScript obfuscated using JSFck encoding techniques. JSFck is a method of writing JavaScript code using only six characters: !+ which is often used to evade detection by security tools.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .depth == 0
            and any(.scan.yara.matches,
                    .name in ("pdf_jsfck_strings", "pdf_jsfck_ratio")
            )
        )
)

Detection Logic

Scope: inbound message.

PDF attachment contains JavaScript obfuscated using JSFck encoding techniques. JSFck is a method of writing JavaScript code using only six characters: !+ which is often used to evade detection by security tools.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .depth == 0 and any(.scan.yara.matches, .name in ("pdf_jsfck_strings", "pdf_jsfck_ratio") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_jsfck_strings
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_jsfck_ratio

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .depth == 0\n            and any(.scan.yara.matches,\n                    .name in (\"pdf_jsfck_strings\", \"pdf_jsfck_ratio\")\n            )\n        )\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"

Attachment: PDF with link to DMG file download

#

Attachment: PDF with link to zip containing a wsf file

#

Attachment: PDF with localhost IP in EXIF title metadata

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

Detects inbound PDF attachments where the EXIF title metadata starts with '127.0.0.1', sent either to a self-addressed recipient or an invalid recipient domain. This technique may indicate automated or malicious document generation tools embedding localhost references in file metadata.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to[0]
  • sender.email
  • type

Rule Body

type.inbound
// self sender or invaild recipent domain
and length(recipients.to) == 1
and (
  sender.email.email == recipients.to[0].email.email
  or recipients.to[0].email.domain.valid == false
)
and any(filter(attachments, .file_type == "pdf"),
        strings.starts_with(beta.parse_exif(.).title, "127.0.0.1")
)

Detection Logic

Scope: inbound message.

Detects inbound PDF attachments where the EXIF title metadata starts with '127.0.0.1', sent either to a self-addressed recipient or an invalid recipient domain. This technique may indicate automated or malicious document generation tools embedding localhost references in file metadata.

  1. inbound message
  2. length(recipients.to) == 1
  3. any of:
    • sender.email.email is recipients.to[0].email.email
    • recipients.to[0].email.domain.valid is False
  4. any(filter(attachments, .file_type == "pdf"), strings.starts_with(beta.parse_exif(.).title, "127.0.0.1") )

Inspects: attachments[].file_type, recipients.to, recipients.to[0].email.domain.valid, recipients.to[0].email.email, sender.email.email, type.inbound. Sensors: beta.parse_exif, strings.starts_with.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
strings.starts_withprefix127.0.0.1

Stages and Predicates

Stage 1: mql_rule

and
  or
    recipients.to[0].email.domain.valid eq "false"
    sender.email.email cross_field_compare "recipients.to[0].email.email"
  recipients.to length_compare "1"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        strings.starts_with(beta.parse_exif(.).title, \"127.0.0.1\")\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
recipients.to[0].email.domain.valideq
  • false transforms: boolean corpus 10 (mql 10)
field:"recipients.to[0].email.domain.valid" kind:eq value:"false"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: PDF with Microsoft Purview message impersonation

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

Detects PDF attachments containing text that impersonates Microsoft Purview secure message notifications, potentially used to trick users into believing they have received legitimate secure communications from Microsoft services.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_extension == 'pdf'),
        any(ml.nlu_classifier(beta.ocr(.).text).topics,
            .name == 'Secure Message' and .confidence == 'high'
        )
        and strings.icontains(beta.ocr(.).text, "Microsoft Purview Message")
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing text that impersonates Microsoft Purview secure message notifications, potentially used to trick users into believing they have received legitimate secure communications from Microsoft services.

  1. inbound message
  2. any(filter(attachments, .file_extension == 'pdf'), any(ml.nlu_classifier(beta.ocr(.).text).topics, .name == 'Secure Message' and .confidence == 'high' ) and strings.icontains(beta.ocr(.).text, "Microsoft Purview Message") )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].file_extension, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.ocr, ml.nlu_classifier, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (4)

FieldMatchValue
attachments[].file_extensionequalspdf
ml.nlu_classifier(beta.ocr(filter(attachments)[]).text).topics[].nameequalsSecure Message
ml.nlu_classifier(beta.ocr(filter(attachments)[]).text).topics[].confidenceequalshigh
strings.icontainssubstringMicrosoft Purview Message

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_extension == 'pdf'),\n        any(ml.nlu_classifier(beta.ocr(.).text).topics,\n            .name == 'Secure Message' and .confidence == 'high'\n        )\n        and strings.icontains(beta.ocr(.).text, \"Microsoft Purview Message\")\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"

Attachment: PDF with multistage landing - ClickUp abuse

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

Detects PDF attachments containing ClickUp document links that either redirect to unavailable pages or contain embedded links leading to newly registered domains, free file hosts, URL shorteners, or verified credential theft pages.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Free file host, Free subdomain host, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(attachments) == 1
and any(attachments,
        .file_type == "pdf"
        and any(file.explode(.),
                .depth == 0
                and length(.scan.url.urls) == 1
                and any(.scan.url.urls,
                        .domain.domain == "doc.clickup.com"
                        and (
                          // landing page has been removed
                          strings.istarts_with(ml.link_analysis(.).final_dom.display_text,
                                               'This page is currently unavailable'
                          )
                          // inspection of links within the doc.clickup.com
                          or any(filter(ml.link_analysis(.).final_dom.links,
                                        .href_url.domain.root_domain != 'clickup.com'
                                        and .href_url.domain.root_domain not in $org_domains
                                 ),
                                 (
                                   // any of those links domains are new
                                   network.whois(.href_url.domain).days_old < 30
                                   // go to free file hosts
                                   or .href_url.domain.root_domain in $free_file_hosts
                                   or .href_url.domain.domain in $free_file_hosts

                                   // go to free subdomains hosts
                                   or (
                                     .href_url.domain.root_domain in $free_subdomain_hosts
                                     // where there is a subdomain
                                     and .href_url.domain.subdomain is not null
                                     and .href_url.domain.subdomain != "www"
                                   )
                                   // go to url shortners
                                   or .href_url.domain.root_domain in $url_shorteners
                                   or .href_url.domain.root_domain in $social_landing_hosts
                                   or .href_url.domain.domain in $url_shorteners
                                   or .href_url.domain.domain in $social_landing_hosts
                                   // or the page has been taken down
                                   or (
                                     // find any links that mention common "action" words
                                     regex.icontains(.display_text,
                                                     '(?:view|click|show|access|download|goto|Validate|Va[il]idar|login|verify|account)'
                                     )
                                     and (
                                       // and when visiting those links, are phishing
                                       ml.link_analysis(., mode="aggressive").credphish.disposition == "phishing"

                                       // hit a captcha page
                                       or ml.link_analysis(., mode="aggressive").credphish.contains_captcha

                                       // or the page redirects to common website, observed when evasion happens
                                       or (
                                         length(ml.link_analysis(.,
                                                                 mode="aggressive"
                                                ).redirect_history
                                         ) > 0
                                         and ml.link_analysis(.,
                                                              mode="aggressive"
                                         ).effective_url.domain.root_domain in $tranco_10k
                                       )
                                     )
                                   )
                                 )
                          )
                        )
                )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing ClickUp document links that either redirect to unavailable pages or contain embedded links leading to newly registered domains, free file hosts, URL shorteners, or verified credential theft pages.

  1. inbound message
  2. length(attachments) == 1
  3. any of attachments where all hold:
    • .file_type is 'pdf'
    • any(file.explode(.), .depth == 0 and length(.scan.url.urls) == 1 and any(.scan.url.urls, .domain.domain == "doc.clickup.com" and ( // landing page has been removed strings.istarts_with(ml.link_analysis(.).final_dom.display_text, 'This page is currently unavailable' ) // inspection of links within the doc.clickup.com or any(filter(ml.link_analysis(.).final_dom.links, .href_url.domain.root_domain != 'clickup.com' and .href_url.domain.root_domain not in $org_domains ), ( // any of those links domains are new network.whois(.href_url.domain).days_old < 30 // go to free file hosts or .href_url.domain.root_domain in $free_file_hosts or .href_url.domain.domain in $free_file_hosts // go to free subdomains hosts or ( .href_url.domain.root_domain in $free_subdomain_hosts // where there is a subdomain and .href_url.domain.subdomain is not null and .href_url.domain.subdomain != "www" ) // go to url shortners or .href_url.domain.root_domain in $url_shorteners or .href_url.domain.root_domain in $social_landing_hosts or .href_url.domain.domain in $url_shorteners or .href_url.domain.domain in $social_landing_hosts // or the page has been taken down or ( // find any links that mention common "action" words regex.icontains(.display_text, '(?:view|click|show|access|download|goto|Validate|Va[il]idar|login|verify|account)' ) and ( // and when visiting those links, are phishing ml.link_analysis(., mode="aggressive").credphish.disposition == "phishing" // hit a captcha page or ml.link_analysis(., mode="aggressive").credphish.contains_captcha // or the page redirects to common website, observed when evasion happens or ( length(ml.link_analysis(., mode="aggressive" ).redirect_history ) > 0 and ml.link_analysis(., mode="aggressive" ).effective_url.domain.root_domain in $tranco_10k ) ) ) ) ) ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, ml.link_analysis, network.whois, regex.icontains, strings.istarts_with. Reference lists: $free_file_hosts, $free_subdomain_hosts, $org_domains, $social_landing_hosts, $tranco_10k, $url_shorteners.

Indicators Matched (4)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(attachments[])[].scan.url.urls[].domain.domainequalsdoc.clickup.com
strings.istarts_withprefixThis page is currently unavailable
regex.icontainsregex(?:view|click|show|access|download|goto|Validate|Va[il]idar|login|verify|account)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type eq "pdf"
       macro "any(file.explode(.),\n                .depth == 0\n                and length(.scan.url.urls) == 1\n                and any(.scan.url.urls,\n                        .domain.domain == \"doc.clickup.com\"\n                        and (\n                          // landing page has been removed\n                          strings.istarts_with(ml.link_analysis(.).final_dom.display_text,\n                                               'This page is currently unavailable'\n                          )\n                          // inspection of links within the doc.clickup.com\n                          or any(filter(ml.link_analysis(.).final_dom.links,\n                                        .href_url.domain.root_domain != 'clickup.com'\n                                        and .href_url.domain.root_domain not in $org_domains\n                                 ),\n                                 (\n                                   // any of those links domains are new\n                                   network.whois(.href_url.domain).days_old < 30\n                                   // go to free file hosts\n                                   or .href_url.domain.root_domain in $free_file_hosts\n                                   or .href_url.domain.domain in $free_file_hosts\n\n                                   // go to free subdomains hosts\n                                   or (\n                                     .href_url.domain.root_domain in $free_subdomain_hosts\n                                     // where there is a subdomain\n                                     and .href_url.domain.subdomain is not null\n                                     and .href_url.domain.subdomain != \"www\"\n                                   )\n                                   // go to url shortners\n                                   or .href_url.domain.root_domain in $url_shorteners\n                                   or .href_url.domain.root_domain in $social_landing_hosts\n                                   or .href_url.domain.domain in $url_shorteners\n                                   or .href_url.domain.domain in $social_landing_hosts\n                                   // or the page has been taken down\n                                   or (\n                                     // find any links that mention common \"action\" words\n                                     regex.icontains(.display_text,\n                                                     '(?:view|click|show|access|download|goto|Validate|Va[il]idar|login|verify|account)'\n                                     )\n                                     and (\n                                       // and when visiting those links, are phishing\n                                       ml.link_analysis(., mode=\"aggressive\").credphish.disposition == \"phishing\"\n\n                                       // hit a captcha page\n                                       or ml.link_analysis(., mode=\"aggressive\").credphish.contains_captcha\n\n                                       // or the page redirects to common website, observed when evasion happens\n                                       or (\n                                         length(ml.link_analysis(.,\n                                                                 mode=\"aggressive\"\n                                                ).redirect_history\n                                         ) > 0\n                                         and ml.link_analysis(.,\n                                                              mode=\"aggressive\"\n                                         ).effective_url.domain.root_domain in $tranco_10k\n                                       )\n                                     )\n                                   )\n                                 )\n                          )\n                        )\n                )\n        )"
  attachments length_compare "1"
  type.inbound eq "true"

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"

Attachment: PDF with password in filename matching body text

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

Detects messages containing a single PDF attachment where the filename includes a numeric password that is explicitly referenced in the message body text.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesEncryption, Evasion, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • type

Rule Body

type.inbound
and length(filter(attachments, .file_type == "pdf")) == 1
and any(regex.extract(body.current_thread.text, 'password is (?P<pw>[0-9]{1,})'),
        any(filter(attachments, .file_type == "pdf"),
            strings.contains(.file_name, ..named_groups["pw"])
        )
)

Detection Logic

Scope: inbound message.

Detects messages containing a single PDF attachment where the filename includes a numeric password that is explicitly referenced in the message body text.

  1. inbound message
  2. length(filter(attachments, .file_type == "pdf")) == 1
  3. any(regex.extract(body.current_thread.text, 'password is (?P<pw>[0-9]{1,})'), any(filter(attachments, .file_type == "pdf"), strings.contains(.file_name, ..named_groups["pw"]) ) )

Inspects: attachments[].file_type, body.current_thread.text, type.inbound. Sensors: regex.extract, strings.contains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
regex.extractregexpassword is (?P<pw>[0-9]{1,})

Stages and Predicates

Stage 1: mql_rule

and
  length func_call "length(filter(attachments, .file_type == \"pdf\")) == 1"
  type.inbound eq "true"
   macro "any(regex.extract(body.current_thread.text, 'password is (?P<pw>[0-9]{1,})'),\n        any(filter(attachments, .file_type == \"pdf\"),\n            strings.contains(.file_name, ..named_groups[\"pw\"])\n        )\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"

Attachment: PDF with personal Microsoft OneNote URL

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

Detects PDF attachments containing a sharepoint URL referencing the senders personal OneNote.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • sender.email
  • type

Rule Body

type.inbound
and length(filter(attachments, .file_type == "pdf")) >= 1
and any(attachments,
        .file_type == "pdf"
        and any(file.explode(.),
                any(.scan.url.urls,
                    strings.icontains(.path,
                                      strings.concat("/:o:/p/",
                                                     sender.email.local_part
                                      )
                    )
                    or strings.icontains(.path, "/:o:/g/personal/")
                )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing a sharepoint URL referencing the senders personal OneNote.

  1. inbound message
  2. length(filter(attachments, .file_type == "pdf")) >= 1
  3. any of attachments where all hold:
    • .file_type is 'pdf'
    • any(file.explode(.), any(.scan.url.urls, strings.icontains(.path, strings.concat("/:o:/p/", sender.email.local_part ) ) or strings.icontains(.path, "/:o:/g/personal/") ) )

Inspects: attachments[].file_type, sender.email.local_part, type.inbound. Sensors: file.explode, strings.concat, strings.icontains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
strings.icontainssubstring/:o:/g/personal/

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type eq "pdf"
       macro "any(file.explode(.),\n                any(.scan.url.urls,\n                    strings.icontains(.path,\n                                      strings.concat(\"/:o:/p/\",\n                                                     sender.email.local_part\n                                      )\n                    )\n                    or strings.icontains(.path, \"/:o:/g/personal/\")\n                )\n        )"
  length func_call "length(filter(attachments, .file_type == \"pdf\")) >= 1"
  type.inbound eq "true"

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"

Attachment: PDF with QR code containing recipient-specific credential theft content

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

Detects PDF attachments containing QR codes that include the recipient's email address (either plaintext or base64 encoded) combined with credential theft language detected through natural language processing. This technique personalizes the attack by incorporating the target's email into the QR code URL while using PDF content to establish credibility.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, QR code, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        ( // the strings produced by the PDF scanner contains cred theft language
          any(filter(file.explode(.), .depth == 1 and .file_name == "text"),
              any(ml.nlu_classifier(.scan.strings.raw).intents,
                  .name == "cred_theft"
              )
          )
        )
        // there is a QR code
        and length(beta.scan_qr(.).items) > 0
        // QR code contians the recipient email
        and any(beta.scan_qr(.).items,
                .url.domain.valid
                and any(recipients.to,
                        .email.domain.valid
                        // QR code contains the email
                        and (
                          strings.icontains(..url.url, .email.email)
                          // QR code contains the base64 endcoded email
                          or any(strings.scan_base64(..url.url,
                                                     format="url",
                                                     ignore_padding=true
                                 ),
                                 strings.icontains(., ..email.email)
                          )
                        )
                )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing QR codes that include the recipient's email address (either plaintext or base64 encoded) combined with credential theft language detected through natural language processing. This technique personalizes the attack by incorporating the target's email into the QR code URL while using PDF content to establish credibility.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), ( // the strings produced by the PDF scanner contains cred theft language any(filter(file.explode(.), .depth == 1 and .file_name == "text"), any(ml.nlu_classifier(.scan.strings.raw).intents, .name == "cred_theft" ) ) ) // there is a QR code and length(beta.scan_qr(.).items) > 0 // QR code contians the recipient email and any(beta.scan_qr(.).items, .url.domain.valid and any(recipients.to, .email.domain.valid // QR code contains the email and ( strings.icontains(..url.url, .email.email) // QR code contains the base64 endcoded email or any(strings.scan_base64(..url.url, format="url", ignore_padding=true ), strings.icontains(., ..email.email) ) ) ) ) )

Inspects: attachments[].file_type, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: beta.scan_qr, file.explode, ml.nlu_classifier, strings.icontains, strings.scan_base64.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].file_nameequalstext
ml.nlu_classifier(filter(...)[].scan.strings.raw).intents[].nameequalscred_theft

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        ( // the strings produced by the PDF scanner contains cred theft language\n          any(filter(file.explode(.), .depth == 1 and .file_name == \"text\"),\n              any(ml.nlu_classifier(.scan.strings.raw).intents,\n                  .name == \"cred_theft\"\n              )\n          )\n        )\n        // there is a QR code\n        and length(beta.scan_qr(.).items) > 0\n        // QR code contians the recipient email\n        and any(beta.scan_qr(.).items,\n                .url.domain.valid\n                and any(recipients.to,\n                        .email.domain.valid\n                        // QR code contains the email\n                        and (\n                          strings.icontains(..url.url, .email.email)\n                          // QR code contains the base64 endcoded email\n                          or any(strings.scan_base64(..url.url,\n                                                     format=\"url\",\n                                                     ignore_padding=true\n                                 ),\n                                 strings.icontains(., ..email.email)\n                          )\n                        )\n                )\n        )\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"

Attachment: PDF with quote lure

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

Detects PDF attachments containing quote-themed lure content.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name in ("pdf_quote_lure_01"))
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing quote-themed lure content.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("pdf_quote_lure_01")) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_quote_lure_01

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name in (\"pdf_quote_lure_01\"))\n        )\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"

Attachment: PDF with recipient email in link

#

Attachment: PDF with ReportLab library and default metadata

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

Detects PDF attachments generated using the ReportLab PDF Library with default anonymous metadata values, including untitled document, anonymous creator/author, and unspecified subject. This combination of characteristics is commonly associated with automated PDF generation tools used in malicious activities.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • type

Rule Body

type.inbound
and any(attachments,
        beta.parse_exif(.).producer == "ReportLab PDF Library - (opensource)"
        and beta.parse_exif(.).title == "untitled"
        and beta.parse_exif(.).creator == "anonymous"
        and any(beta.parse_exif(.).fields,
                .key == "Subject" and .value == "unspecified"
        )
        and beta.parse_exif(.).author == "anonymous"
) 

Detection Logic

Scope: inbound message.

Detects PDF attachments generated using the ReportLab PDF Library with default anonymous metadata values, including untitled document, anonymous creator/author, and unspecified subject. This combination of characteristics is commonly associated with automated PDF generation tools used in malicious activities.

  1. inbound message
  2. any of attachments where all hold:
    • beta.parse_exif(.).producer == "ReportLab PDF Library - (opensource)"
    • beta.parse_exif(.).title == "untitled"
    • beta.parse_exif(.).creator == "anonymous"
    • any(beta.parse_exif(.).fields, .key == "Subject" and .value == "unspecified" )
    • beta.parse_exif(.).author == "anonymous"

Inspects: type.inbound. Sensors: beta.parse_exif.

Indicators Matched (2)

FieldMatchValue
beta.parse_exif(attachments[]).fields[].keyequalsSubject
beta.parse_exif(attachments[]).fields[].valueequalsunspecified

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      beta.parse_exif func_call "beta.parse_exif(.).author == \"anonymous\""
      beta.parse_exif func_call "beta.parse_exif(.).creator == \"anonymous\""
      beta.parse_exif func_call "beta.parse_exif(.).producer == \"ReportLab PDF Library - (opensource)\""
      beta.parse_exif func_call "beta.parse_exif(.).title == \"untitled\""
       macro "any(beta.parse_exif(.).fields,\n                .key == \"Subject\" and .value == \"unspecified\"\n        )"
  type.inbound eq "true"

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"

Attachment: PDF with secure document acknowledgment prompt

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

Detects PDF attachments matching yara rules looking for fake secure document prompts, including acknowledgment-style lures and suspicious image sizing.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, PDF, Social engineering, Image as content, Impersonation: Brand

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name in (
                  "pdf_prompt_ack_secure_document_link",
                  "pdf_prompt_ack_secure_document_image_sizes"
                )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments matching yara rules looking for fake secure document prompts, including acknowledgment-style lures and suspicious image sizing.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ( "pdf_prompt_ack_secure_document_link", "pdf_prompt_ack_secure_document_image_sizes" ) ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_prompt_ack_secure_document_link
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_prompt_ack_secure_document_image_sizes

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name in (\n                  \"pdf_prompt_ack_secure_document_link\",\n                  \"pdf_prompt_ack_secure_document_image_sizes\"\n                )\n            )\n        )\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"

Attachment: PDF with self-service platform links with self sender or blank recipients

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

Detects single-page PDF attachments containing links to self-service content creation platforms, sent to either the sender's own email address or an invalid email domain. This pattern may indicate testing of malicious content or preparation for distribution.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesPDF, Evasion, Free file host

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • attachments[0]
  • recipients
  • recipients.to[0]
  • sender.email
  • type

Rule Body

type.inbound
and sum([length(recipients.to), length(recipients.cc)]) == 1
and (
  sender.email.email == recipients.to[0].email.email
  or recipients.to[0].email.domain.valid == false
)
and length(attachments) == 1
and beta.parse_exif(attachments[0]).page_count == 1
and any(filter(attachments, .file_type == "pdf"),
        any(filter(file.explode(.), .depth == 0),
            1 <= length(filter(.scan.url.urls,
                               // remove mailto: links
                               not strings.istarts_with(.url, 'mailto:')
                               and not strings.istarts_with(.url, 'email:')
                               // remove links found in exiftool output producer/creator
                               and not any([
                                             ..scan.exiftool.producer,
                                             ..scan.exiftool.creator
                                           ],
                                           . is not null
                                           and strings.icontains(.,
                                                                 ..domain.domain
                                           )
                               )
                               and not .domain.root_domain in ('pdf-tools.com')
                               and not .url in (
                                 'https://gamma.app/?utm_source=made-with-gamma'
                               )
                        )
            ) <= 3
            and all(.scan.url.urls,
                    .domain.root_domain in $self_service_creation_platform_domains
                    or .domain.domain in $self_service_creation_platform_domains
            )
        )
)

Detection Logic

Scope: inbound message.

Detects single-page PDF attachments containing links to self-service content creation platforms, sent to either the sender's own email address or an invalid email domain. This pattern may indicate testing of malicious content or preparation for distribution.

  1. inbound message
  2. sum([length(recipients.to), length(recipients.cc)]) == 1
  3. any of:
    • sender.email.email is recipients.to[0].email.email
    • recipients.to[0].email.domain.valid is False
  4. length(attachments) == 1
  5. beta.parse_exif(attachments[0]).page_count == 1
  6. any(filter(attachments, .file_type == "pdf"), any(filter(file.explode(.), .depth == 0), 1 <= length(filter(.scan.url.urls, // remove mailto: links not strings.istarts_with(.url, 'mailto:') and not strings.istarts_with(.url, 'email:') // remove links found in exiftool output producer/creator and not any([ ..scan.exiftool.producer, ..scan.exiftool.creator ], . is not null and strings.icontains(., ..domain.domain ) ) and not .domain.root_domain in ('pdf-tools.com') and not .url in ( 'https://gamma.app/?utm_source=made-with-gamma' ) ) ) <= 3 and all(.scan.url.urls, .domain.root_domain in $self_service_creation_platform_domains or .domain.domain in $self_service_creation_platform_domains ) ) )

Inspects: attachments[0], attachments[].file_type, recipients.cc, recipients.to, recipients.to[0].email.domain.valid, recipients.to[0].email.email, sender.email.email, type.inbound. Sensors: beta.parse_exif, file.explode, strings.icontains, strings.istarts_with. Reference lists: $self_service_creation_platform_domains.

Indicators Matched (1)

FieldMatchValue
attachments[].file_typeequalspdf

Stages and Predicates

Stage 1: mql_rule

and
  or
    recipients.to[0].email.domain.valid eq "false"
    sender.email.email cross_field_compare "recipients.to[0].email.email"
  attachments length_compare "1"
  beta.parse_exif func_call "beta.parse_exif(attachments[0]).page_count == 1"
  sum func_call "sum([length(recipients.to), length(recipients.cc)]) == 1"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(filter(file.explode(.), .depth == 0),\n            1 <= length(filter(.scan.url.urls,\n                               // remove mailto: links\n                               not strings.istarts_with(.url, 'mailto:')\n                               and not strings.istarts_with(.url, 'email:')\n                               // remove links found in exiftool output producer/creator\n                               and not any([\n                                             ..scan.exiftool.producer,\n                                             ..scan.exiftool.creator\n                                           ],\n                                           . is not null\n                                           and strings.icontains(.,\n                                                                 ..domain.domain\n                                           )\n                               )\n                               and not .domain.root_domain in ('pdf-tools.com')\n                               and not .url in (\n                                 'https://gamma.app/?utm_source=made-with-gamma'\n                               )\n                        )\n            ) <= 3\n            and all(.scan.url.urls,\n                    .domain.root_domain in $self_service_creation_platform_domains\n                    or .domain.domain in $self_service_creation_platform_domains\n            )\n        )\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
recipients.to[0].email.domain.valideq
  • false transforms: boolean corpus 10 (mql 10)
field:"recipients.to[0].email.domain.valid" kind:eq value:"false"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: PDF with specific author metadata

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

Detects inbound messages containing PDF attachments where the EXIF metadata indicates the author or creator is 'Shelby Porter'.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and length(filter(attachments, .file_type == "pdf")) >= 1
and any(filter(attachments, .file_type == "pdf"),
        beta.parse_exif(.).author == "Shelby Porter"
        or beta.parse_exif(.).creator == "Shelby Porter"
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing PDF attachments where the EXIF metadata indicates the author or creator is 'Shelby Porter'.

  1. inbound message
  2. length(filter(attachments, .file_type == "pdf")) >= 1
  3. any(filter(attachments, .file_type == "pdf"), beta.parse_exif(.).author == "Shelby Porter" or beta.parse_exif(.).creator == "Shelby Porter" )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif.

Indicators Matched (1)

FieldMatchValue
attachments[].file_typeequalspdf

Stages and Predicates

Stage 1: mql_rule

and
  length func_call "length(filter(attachments, .file_type == \"pdf\")) >= 1"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        beta.parse_exif(.).author == \"Shelby Porter\"\n        or beta.parse_exif(.).creator == \"Shelby Porter\"\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"

Attachment: PDF with specific W-9 lure

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

Detects PDF attachments containing W-9 related lures. This one is looking for signatures that have been observed across multiple samples.

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
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name in ("pdf_w9_signature_c003"))
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing W-9 related lures. This one is looking for signatures that have been observed across multiple samples.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("pdf_w9_signature_c003")) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberpdf_w9_signature_c003

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name in (\"pdf_w9_signature_c003\"))\n        )\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"

Attachment: PDF with split QR code

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

Detects PDF attachments containing split QR codes positioned close together, a technique used to evade detection while maintaining QR code functionality for credential theft.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, PDF, QR code

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                // yara rules match on "split" QR codes that are 290x290, 300x300, 370x370 and placed close to eachtoher in the PDF
                strings.istarts_with(.name, 'Phishing_PDF_Split_QR_Code_Pair')
            )
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing split QR codes positioned close together, a technique used to evade detection while maintaining QR code functionality for credential theft.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, // yara rules match on "split" QR codes that are 290x290, 300x300, 370x370 and placed close to eachtoher in the PDF strings.istarts_with(.name, 'Phishing_PDF_Split_QR_Code_Pair') ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, strings.istarts_with.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
strings.istarts_withprefixPhishing_PDF_Split_QR_Code_Pair

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                // yara rules match on \"split\" QR codes that are 290x290, 300x300, 370x370 and placed close to eachtoher in the PDF\n                strings.istarts_with(.name, 'Phishing_PDF_Split_QR_Code_Pair')\n            )\n        )\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"

Attachment: PDF with suspicious document view lure

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

Detects PDF attachments containing a title box designed to lure recipients into viewing a document, a common social engineering technique used to direct users to malicious content.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name == "pdf_view_doc_here_title_box")
        )
)

Detection Logic

Scope: inbound message.

Detects PDF attachments containing a title box designed to lure recipients into viewing a document, a common social engineering technique used to direct users to malicious content.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name == "pdf_view_doc_here_title_box") ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalspdf_view_doc_here_title_box

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name == \"pdf_view_doc_here_title_box\")\n        )\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"

Attachment: PDF with suspicious HeadlessChrome metadata

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

Detects PDF attachments created by HeadlessChrome with suspicious characteristics, including MD5-formatted HTML filenames or blank titles with Windows Skia/PDF producer, excluding legitimate Google Docs files.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_extension == "pdf"),
        strings.icontains(beta.parse_exif(.).creator, "HeadlessChrome")
        and beta.parse_exif(.).page_count == 1
        and (
          // MD5 filename, 32 hex chars and .html
          (
            regex.imatch(beta.parse_exif(.).title, '^[a-f0-9]{32}\.html$')
            or 
            // about:blank and Windows HeadlessChrome
            (
              beta.parse_exif(.).title == "about:blank"
              and strings.istarts_with(beta.parse_exif(.).producer, "Skia/PDF")
              and strings.icontains(beta.parse_exif(.).creator, "Windows")
            )
            // cred theft intents on the message and Windows Headless Chrome
            or (
              any(ml.nlu_classifier(body.current_thread.text).intents,
                  .name in ("bec", "cred_theft") and .confidence != "low"
              )
              and strings.istarts_with(beta.parse_exif(.).producer, "Skia/PDF")
              and strings.icontains(beta.parse_exif(.).creator, "Windows")
            )
          )
          and not strings.icontains(beta.parse_exif(.).producer, "Google Docs")
        )
)
and not (
  sender.email.domain.root_domain in (
    "guardtek.net",
    "gominis.com",
    "aglgroup.com",
    "truckerzoom.com"
  )
  and coalesce(headers.auth_summary.dmarc.pass, false)
)

Detection Logic

Scope: inbound message.

Detects PDF attachments created by HeadlessChrome with suspicious characteristics, including MD5-formatted HTML filenames or blank titles with Windows Skia/PDF producer, excluding legitimate Google Docs files.

  1. inbound message
  2. any(filter(attachments, .file_extension == "pdf"), strings.icontains(beta.parse_exif(.).creator, "HeadlessChrome") and beta.parse_exif(.).page_count == 1 and ( // MD5 filename, 32 hex chars and .html ( regex.imatch(beta.parse_exif(.).title, '^[a-f0-9]{32}\.html$') or // about:blank and Windows HeadlessChrome ( beta.parse_exif(.).title == "about:blank" and strings.istarts_with(beta.parse_exif(.).producer, "Skia/PDF") and strings.icontains(beta.parse_exif(.).creator, "Windows") ) // cred theft intents on the message and Windows Headless Chrome or ( any(ml.nlu_classifier(body.current_thread.text).intents, .name in ("bec", "cred_theft") and .confidence != "low" ) and strings.istarts_with(beta.parse_exif(.).producer, "Skia/PDF") and strings.icontains(beta.parse_exif(.).creator, "Windows") ) ) and not strings.icontains(beta.parse_exif(.).producer, "Google Docs") ) )
  3. not:
    • all of:
      • sender.email.domain.root_domain in ('guardtek.net', 'gominis.com', 'aglgroup.com', 'truckerzoom.com')
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_extension, body.current_thread.text, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.parse_exif, ml.nlu_classifier, regex.imatch, strings.icontains, strings.istarts_with.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionequalspdf
strings.icontainssubstringHeadlessChrome
regex.imatchregex^[a-f0-9]{32}\.html$
strings.istarts_withprefixSkia/PDF
strings.icontainssubstringWindows
ml.nlu_classifier(body.current_thread.text).intents[].namememberbec
ml.nlu_classifier(body.current_thread.text).intents[].namemembercred_theft

Stages and Predicates

Stage 1: mql_rule

and
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain in ["aglgroup.com", "gominis.com", "guardtek.net", "truckerzoom.com"]
  type.inbound eq "true"
   macro "any(filter(attachments, .file_extension == \"pdf\"),\n        strings.icontains(beta.parse_exif(.).creator, \"HeadlessChrome\")\n        and beta.parse_exif(.).page_count == 1\n        and (\n          // MD5 filename, 32 hex chars and .html\n          (\n            regex.imatch(beta.parse_exif(.).title, '^[a-f0-9]{32}\\.html$')\n            or \n            // about:blank and Windows HeadlessChrome\n            (\n              beta.parse_exif(.).title == \"about:blank\"\n              and strings.istarts_with(beta.parse_exif(.).producer, \"Skia/PDF\")\n              and strings.icontains(beta.parse_exif(.).creator, \"Windows\")\n            )\n            // cred theft intents on the message and Windows Headless Chrome\n            or (\n              any(ml.nlu_classifier(body.current_thread.text).intents,\n                  .name in (\"bec\", \"cred_theft\") and .confidence != \"low\"\n              )\n              and strings.istarts_with(beta.parse_exif(.).producer, \"Skia/PDF\")\n              and strings.icontains(beta.parse_exif(.).creator, \"Windows\")\n            )\n          )\n          and not strings.icontains(beta.parse_exif(.).producer, \"Google Docs\")\n        )\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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass
sender.email.domain.root_domaininaglgroup.com, gominis.com, guardtek.net, truckerzoom.comexcludes:sender.email.domain.root_domain

Attachment: PDF with suspicious internal object reference identifier

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

Detects inbound messages containing PDF attachments with a specific internal object reference identifier pattern, which may indicate a crafted or malicious PDF file.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesPDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            .depth == 0
            and any(.scan.strings.strings,
                    strings.contains(., "[<C57237C22450666518136DE404118E5E>")
            )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing PDF attachments with a specific internal object reference identifier pattern, which may indicate a crafted or malicious PDF file.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), .depth == 0 and any(.scan.strings.strings, strings.contains(., "[<C57237C22450666518136DE404118E5E>") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, strings.contains.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
strings.containssubstring[<C57237C22450666518136DE404118E5E>

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            .depth == 0\n            and any(.scan.strings.strings,\n                    strings.contains(., \"[<C57237C22450666518136DE404118E5E>\")\n            )\n        )\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"

Attachment: PDF with suspicious language and redirect to suspicious file type

#

Attachment: PDF with suspicious link and action-oriented language

#

Attachment: PDF with suspicious view document characteristics

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

PDF attachment contains suspicious characteristics commonly associated with document viewing lures, as detected by YARA pattern matching.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesPDF, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name == "view_document_pdf_characteristics"
            )
        )
)

Detection Logic

Scope: inbound message.

PDF attachment contains suspicious characteristics commonly associated with document viewing lures, as detected by YARA pattern matching.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name == "view_document_pdf_characteristics" ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalsview_document_pdf_characteristics

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name == \"view_document_pdf_characteristics\"\n            )\n        )\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"

Attachment: PDF with View RFP Document lure with external link

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

Detects inbound emails containing a PDF attachment that references a 'VIEW RFP DOCUMENT' lure and embeds a URL pointing to a domain that differs from the sender's domain, a pattern consistent with document-based social engineering used to redirect recipients to attacker-controlled infrastructure.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • sender.email
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.strings.strings, . =~ 'VIEW RFP DOCUMENT')
        )
        and any(file.explode(.),
                length(filter(.scan.url.urls,
                              .scheme != "mailto"
                              and .domain.domain != sender.email.domain.domain
                       )
                ) > 0
        )
)

Detection Logic

Scope: inbound message.

Detects inbound emails containing a PDF attachment that references a 'VIEW RFP DOCUMENT' lure and embeds a URL pointing to a domain that differs from the sender's domain, a pattern consistent with document-based social engineering used to redirect recipients to attacker-controlled infrastructure.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.strings.strings, . =~ 'VIEW RFP DOCUMENT') ) and any(file.explode(.), length(filter(.scan.url.urls, .scheme != "mailto" and .domain.domain != sender.email.domain.domain ) ) > 0 ) )

Inspects: attachments[].file_type, sender.email.domain.domain, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.strings.strings[]equalsVIEW RFP DOCUMENT

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.strings.strings, . =~ 'VIEW RFP DOCUMENT')\n        )\n        and any(file.explode(.),\n                length(filter(.scan.url.urls,\n                              .scheme != \"mailto\"\n                              and .domain.domain != sender.email.domain.domain\n                       )\n                ) > 0\n        )\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"

Attachment: PDF with W-9 form indicators

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

Detects inbound messages containing PDF attachments that match structural or signature patterns consistent with specific W-9 tax lure activity sets.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesPDF, Social engineering, Impersonation: Brand

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches,
                .name in ("w9_c001_signatures", "w9_c001_structure")
            )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing PDF attachments that match structural or signature patterns consistent with specific W-9 tax lure activity sets.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name in ("w9_c001_signatures", "w9_c001_structure") ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberw9_c001_signatures
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberw9_c001_structure

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches,\n                .name in (\"w9_c001_signatures\", \"w9_c001_structure\")\n            )\n        )\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"

Attachment: Potential sandbox evasion in Office file

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

Scans attached files with known Office file extension, and alerts on the presence of strings indicative of sandbox evasion checks. Malicious code may carry out checks against the local host (e.g. running processes, disk size, domain-joined status) before running its final payload.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Macros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.explode(.),
                1 of (
                  any(.scan.strings.strings,
                      strings.ilike(., "*Win32_Processor*")
                  ),
                  any(.scan.strings.strings,
                      strings.ilike(., "*Win32_LogicalDisk*")
                  ),
                  any(.scan.strings.strings,
                      strings.ilike(., "*Win32_ComputerSystem*")
                  ),
                  any(.scan.strings.strings,
                      strings.ilike(., "*Win32_Process*")
                  ),
                  any(.scan.strings.strings,
                      strings.ilike(., "*LDAP://RootDSE*")
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

Scans attached files with known Office file extension, and alerts on the presence of strings indicative of sandbox evasion checks. Malicious code may carry out checks against the local host (e.g. running processes, disk size, domain-joined status) before running its final payload.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • any(file.explode(.), 1 of ( any(.scan.strings.strings, strings.ilike(., "*Win32_Processor*") ), any(.scan.strings.strings, strings.ilike(., "*Win32_LogicalDisk*") ), any(.scan.strings.strings, strings.ilike(., "*Win32_ComputerSystem*") ), any(.scan.strings.strings, strings.ilike(., "*Win32_Process*") ), any(.scan.strings.strings, strings.ilike(., "*LDAP://RootDSE*") ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode, strings.ilike. Reference lists: $file_extensions_macros.

Indicators Matched (7)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
strings.ilikesubstring*Win32_Processor*
strings.ilikesubstring*Win32_LogicalDisk*
strings.ilikesubstring*Win32_ComputerSystem*
strings.ilikesubstring*Win32_Process*
strings.ilikesubstring*LDAP://RootDSE*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
       macro "any(file.explode(.),\n                1 of (\n                  any(.scan.strings.strings,\n                      strings.ilike(., \"*Win32_Processor*\")\n                  ),\n                  any(.scan.strings.strings,\n                      strings.ilike(., \"*Win32_LogicalDisk*\")\n                  ),\n                  any(.scan.strings.strings,\n                      strings.ilike(., \"*Win32_ComputerSystem*\")\n                  ),\n                  any(.scan.strings.strings,\n                      strings.ilike(., \"*Win32_Process*\")\n                  ),\n                  any(.scan.strings.strings,\n                      strings.ilike(., \"*LDAP://RootDSE*\")\n                  )\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: PowerPoint with suspicious hyperlink

#

Attachment: PowerShell content

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

Recursively scans files and archives to detect PowerShell content. While scripts are often blocked by mail filtering, alternative file formats and archived content may be employed to bypass such controls.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesScripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ (
            // PowerShell related file extensions
            "ps1",
            "ps1xml",
            "psm1",
            "psd1",
            "pssc",
            "psrc",
            "cdxml",
            "ps2",
            "ps2xml",
            "psc2",
          )
          or .file_extension in~ $file_extensions_common_archives
        )
        and any(file.explode(.),
                .file_extension in~ (
                  "ps1",
                  "ps1xml",
                  "psm1",
                  "psd1",
                  "pssc",
                  "psrc",
                  "cdxml",
                  "ps2",
                  "ps2xml",
                  "psc2",
                )
        )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect PowerShell content. While scripts are often blocked by mail filtering, alternative file formats and archived content may be employed to bypass such controls.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in ('ps1', 'ps1xml', 'psm1', 'psd1', 'pssc', 'psrc', 'cdxml', 'ps2', 'ps2xml', 'psc2')
      • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), .file_extension in~ ( "ps1", "ps1xml", "psm1", "psd1", "pssc", "psrc", "cdxml", "ps2", "ps2xml", "psc2", ) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (20)

FieldMatchValue
attachments[].file_extensionmemberps1
attachments[].file_extensionmemberps1xml
attachments[].file_extensionmemberpsm1
attachments[].file_extensionmemberpsd1
attachments[].file_extensionmemberpssc
attachments[].file_extensionmemberpsrc
attachments[].file_extensionmembercdxml
attachments[].file_extensionmemberps2
attachments[].file_extensionmemberps2xml
attachments[].file_extensionmemberpsc2
file.explode(attachments[])[].file_extensionmemberps1
file.explode(attachments[])[].file_extensionmemberps1xml
8 more
file.explode(attachments[])[].file_extensionmemberpsm1
file.explode(attachments[])[].file_extensionmemberpsd1
file.explode(attachments[])[].file_extensionmemberpssc
file.explode(attachments[])[].file_extensionmemberpsrc
file.explode(attachments[])[].file_extensionmembercdxml
file.explode(attachments[])[].file_extensionmemberps2
file.explode(attachments[])[].file_extensionmemberps2xml
file.explode(attachments[])[].file_extensionmemberpsc2

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension in ["cdxml", "ps1", "ps1xml", "ps2", "ps2xml", "psc2", "psd1", "psm1", "psrc", "pssc"]
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.),\n                .file_extension in~ (\n                  \"ps1\",\n                  \"ps1xml\",\n                  \"psm1\",\n                  \"psd1\",\n                  \"pssc\",\n                  \"psrc\",\n                  \"cdxml\",\n                  \"ps2\",\n                  \"ps2xml\",\n                  \"psc2\",\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: QR code link with base64-encoded recipient address

#

Attachment: QR code with credential phishing indicators

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

Detects messages with between 1-3 attachments containing a QR code with suspicious credential theft indicators, such as: LinkAnalysis credential phishing conclusion, decoded QR code url traverses suspicious infrastructure, the final destination is in URLhaus, decoded URL downloads a zip or executable, leverages URL shorteners, known QR abused openredirects, and more.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • recipients
  • recipients.to
  • sender.email
  • type

Rule Body

type.inbound
and (
  1 <= length(attachments) < 3
  or (
    // if there are more than three attachments
    3 <= length(attachments) < 20
    // there are only pngs and pdf/docx
    and length(distinct(map(attachments, .file_extension))) == 2
    and all(distinct(map(attachments, .file_extension)),
            . in ('png', 'pdf', 'docx')
    )
    and (
      // multiple attachments mention common brands or other common common filenames
      (
        length(filter(attachments,
                      strings.icontains(.file_name, 'adobe')
                      or strings.icontains(.file_name, 'office')
                      or strings.icontains(.file_name, 'appstore')
                      or strings.icontains(.file_name, 'google')
                      or strings.icontains(.file_name, 'padlock')
                      or regex.icontains(.file_name, '\bdoc\b')
               )
        ) > 3
      )
      // the attachment name contains the SLD of a recipient
      or any(filter(attachments, .file_extension in ('pdf', 'docx')),
             any(filter(recipients.to, .email.domain.valid),
                 strings.icontains(..file_name, .email.domain.sld)
             )
      )
    )
  )
)

// Inspects image attachments for QR codes
and any(attachments,
        (
          .file_type in $file_types_images
          or .file_type == "pdf"
          or .file_extension in $file_extensions_macros
        )
        and (
          any(file.explode(.),
              .scan.qr.type == "url"
              and not .scan.qr.url.domain.domain == "geico.app.link"
              and (
                // pass the QR URL to LinkAnalysis
                any([ml.link_analysis(.scan.qr.url)],
                    .credphish.disposition == "phishing"

                    // any routing traverses via $suspicious_tld list
                    or any(.redirect_history, .domain.tld in $suspicious_tlds)

                    // effective destination in $suspicious_tld list
                    or .effective_url.domain.tld in $suspicious_tlds

                    // or the effective destination domain is in $abuse_ch_urlhaus_domains_trusted_reporters
                    or .effective_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters

                    // or any files downloaded are zips or executables
                    or any(.files_downloaded,
                           .file_extension in $file_extensions_common_archives
                           or .file_extension in $file_extensions_executables
                    )
                )
                or (

                  // or the QR code's root domain is a url_shortener
                  .scan.qr.url.domain.root_domain in $url_shorteners
                  or (
                    .scan.qr.url.domain.root_domain in $social_landing_hosts
                    and (
                      not (
                        any(ml.nlu_classifier(body.current_thread.text).intents,
                            .name == "benign"
                        )
                        or any(ml.nlu_classifier(body.current_thread.text).entities,
                               .name == "disclaimer"
                        )
                      )
                      or not any(attachments,
                                 any(file.explode(.),
                                     any(ml.nlu_classifier(.scan.ocr.raw).intents,
                                         .name == "benign"
                                     )
                                 )
                      )
                      // the QR code contains the email address of a recipient
                      or (
                        any(filter(recipients.to, .email.domain.valid),
                            strings.icontains(..scan.qr.url.url, .email.email)
                        )
                      )
                    )

                    // exclude google maps
                    and not strings.starts_with(.scan.qr.url.url,
                                                'https://goo.gl/maps'
                    )
                    and not strings.starts_with(.scan.qr.url.url,
                                                'https://maps.app.goo.gl'
                    )
                  )
                )

                // the QR code url is a bing open redirect
                or (
                  .scan.qr.url.domain.root_domain == 'bing.com'
                  and .scan.qr.url.path =~ '/ck/a'
                )
                // QR code contains non ascii chars
                or regex.contains(.scan.qr.url.url, '[^\x00-\x7F]')
                or (
                  (
                    // usap-dc open redirect
                    .scan.qr.url.domain.root_domain == "usap-dc.org"
                    and .scan.qr.url.path =~ "/tracker"
                    and strings.starts_with(.scan.qr.url.query_params,
                                            "type=dataset&url=http"
                    )
                  )
                  // the QR code contains the email address of a recipient
                  // allowing for base64 encoded variants
                  or (
                    any(filter(recipients.to, .email.domain.valid),
                        strings.icontains(..scan.qr.url.url, .email.email)
                        or any(strings.scan_base64(..scan.qr.url.url,
                                                   ignore_padding=true
                               ),
                               strings.icontains(., ..email.email)
                        )
                        or any(strings.scan_base64(..scan.qr.url.fragment,
                                                   ignore_padding=true
                               ),
                               strings.icontains(., ..email.email)
                        )
                    )
                  )
                )
              )
          )
        )
)
and (
  (
    profile.by_sender_email().prevalence in ("new", "outlier")
    and not profile.by_sender_email().solicited
  )
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
  or (
    sender.email.domain.domain in $org_domains
    and not coalesce(headers.auth_summary.dmarc.pass, false)
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects messages with between 1-3 attachments containing a QR code with suspicious credential theft indicators, such as: LinkAnalysis credential phishing conclusion, decoded QR code url traverses suspicious infrastructure, the final destination is in URLhaus, decoded URL downloads a zip or executable, leverages URL shorteners, known QR abused openredirects, and more.

  1. inbound message
  2. any of:
    • all of:
      • (1) <= (length(attachments))
      • (length(attachments)) < (3)
    • all of:
      • all of:
        • (3) <= (length(attachments))
        • (length(attachments)) < (20)
      • length(distinct(map(attachments, .file_extension))) == 2
      • all(distinct(map(attachments, .file_extension)), . in ('png', 'pdf', 'docx') )
      • any of:
        • ( length(filter(attachments, strings.icontains(.file_name, 'adobe') or strings.icontains(.file_name, 'office') or strings.icontains(.file_name, 'appstore') or strings.icontains(.file_name, 'google') or strings.icontains(.file_name, 'padlock') or regex.icontains(.file_name, '\bdoc\b') ) ) > 3 )
        • any(filter(attachments, .file_extension in ('pdf', 'docx')), any(filter(recipients.to, .email.domain.valid), strings.icontains(..file_name, .email.domain.sld) ) )
  3. any of attachments where all hold:
    • any of:
      • .file_type in $file_types_images
      • .file_type is 'pdf'
      • .file_extension in $file_extensions_macros
    • ( any(file.explode(.), .scan.qr.type == "url" and not .scan.qr.url.domain.domain == "geico.app.link" and ( // pass the QR URL to LinkAnalysis any([ml.link_analysis(.scan.qr.url)], .credphish.disposition == "phishing" // any routing traverses via $suspicious_tld list or any(.redirect_history, .domain.tld in $suspicious_tlds) // effective destination in $suspicious_tld list or .effective_url.domain.tld in $suspicious_tlds // or the effective destination domain is in $abuse_ch_urlhaus_domains_trusted_reporters or .effective_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters // or any files downloaded are zips or executables or any(.files_downloaded, .file_extension in $file_extensions_common_archives or .file_extension in $file_extensions_executables ) ) or ( // or the QR code's root domain is a url_shortener .scan.qr.url.domain.root_domain in $url_shorteners or ( .scan.qr.url.domain.root_domain in $social_landing_hosts and ( not ( any(ml.nlu_classifier(body.current_thread.text).intents, .name == "benign" ) or any(ml.nlu_classifier(body.current_thread.text).entities, .name == "disclaimer" ) ) or not any(attachments, any(file.explode(.), any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "benign" ) ) ) // the QR code contains the email address of a recipient or ( any(filter(recipients.to, .email.domain.valid), strings.icontains(..scan.qr.url.url, .email.email) ) ) ) // exclude google maps and not strings.starts_with(.scan.qr.url.url, 'https://goo.gl/maps' ) and not strings.starts_with(.scan.qr.url.url, 'https://maps.app.goo.gl' ) ) ) // the QR code url is a bing open redirect or ( .scan.qr.url.domain.root_domain == 'bing.com' and .scan.qr.url.path =~ '/ck/a' ) // QR code contains non ascii chars or regex.contains(.scan.qr.url.url, '[^\x00-\x7F]') or ( ( // usap-dc open redirect .scan.qr.url.domain.root_domain == "usap-dc.org" and .scan.qr.url.path =~ "/tracker" and strings.starts_with(.scan.qr.url.query_params, "type=dataset&url=http" ) ) // the QR code contains the email address of a recipient // allowing for base64 encoded variants or ( any(filter(recipients.to, .email.domain.valid), strings.icontains(..scan.qr.url.url, .email.email) or any(strings.scan_base64(..scan.qr.url.url, ignore_padding=true ), strings.icontains(., ..email.email) ) or any(strings.scan_base64(..scan.qr.url.fragment, ignore_padding=true ), strings.icontains(., ..email.email) ) ) ) ) ) ) )
  4. any of:
    • all of:
      • profile.by_sender_email().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender_email().solicited
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
    • all of:
      • sender.email.domain.domain in $org_domains
      • not:
        • coalesce(headers.auth_summary.dmarc.pass, false)
  5. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, body.current_thread.text, headers.auth_summary.dmarc.pass, recipients.to, recipients.to[].email.domain.valid, sender.email.domain.domain, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.link_analysis, ml.nlu_classifier, profile.by_sender_email, regex.contains, regex.icontains, strings.icontains, strings.scan_base64, strings.starts_with. Reference lists: $abuse_ch_urlhaus_domains_trusted_reporters, $file_extensions_common_archives, $file_extensions_executables, $file_extensions_macros, $file_types_images, $high_trust_sender_root_domains, $org_domains, $social_landing_hosts, $suspicious_tlds, $url_shorteners.

Indicators Matched (20)

FieldMatchValue
distinct(...)[]memberpng
distinct(...)[]memberpdf
distinct(...)[]memberdocx
strings.icontainssubstringadobe
strings.icontainssubstringoffice
strings.icontainssubstringappstore
strings.icontainssubstringgoogle
strings.icontainssubstringpadlock
regex.icontainsregex\bdoc\b
attachments[].file_extensionmemberpdf
attachments[].file_extensionmemberdocx
attachments[].file_typeequalspdf
8 more
file.explode(attachments[])[].scan.qr.typeequalsurl
[ml.link_analysis(file.explode(attachments[])[].scan.qr.url)][].credphish.dispositionequalsphishing
file.explode(attachments[])[].scan.qr.url.domain.root_domainequalsbing.com
file.explode(attachments[])[].scan.qr.url.pathequals/ck/a
regex.containsregex[^\x00-\x7F]
file.explode(attachments[])[].scan.qr.url.domain.root_domainequalsusap-dc.org
file.explode(attachments[])[].scan.qr.url.pathequals/tracker
strings.starts_withprefixtype=dataset&url=http

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        and
          headers.auth_summary.dmarc.pass eq "true"
          headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.domain macro "sender.email.domain.domain in org_domains"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().solicited"
      profile.by_sender_email func_call "profile.by_sender_email().prevalence in (\"new\", \"outlier\")"
  any(attachments)
    and
      or
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
        attachments.file_type eq "pdf"
        attachments.file_type macro "attachments[].file_type in file_types_images"
       macro "(\n          any(file.explode(.),\n              .scan.qr.type == \"url\"\n              and not .scan.qr.url.domain.domain == \"geico.app.link\"\n              and (\n                // pass the QR URL to LinkAnalysis\n                any([ml.link_analysis(.scan.qr.url)],\n                    .credphish.disposition == \"phishing\"\n\n                    // any routing traverses via $suspicious_tld list\n                    or any(.redirect_history, .domain.tld in $suspicious_tlds)\n\n                    // effective destination in $suspicious_tld list\n                    or .effective_url.domain.tld in $suspicious_tlds\n\n                    // or the effective destination domain is in $abuse_ch_urlhaus_domains_trusted_reporters\n                    or .effective_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters\n\n                    // or any files downloaded are zips or executables\n                    or any(.files_downloaded,\n                           .file_extension in $file_extensions_common_archives\n                           or .file_extension in $file_extensions_executables\n                    )\n                )\n                or (\n\n                  // or the QR code's root domain is a url_shortener\n                  .scan.qr.url.domain.root_domain in $url_shorteners\n                  or (\n                    .scan.qr.url.domain.root_domain in $social_landing_hosts\n                    and (\n                      not (\n                        any(ml.nlu_classifier(body.current_thread.text).intents,\n                            .name == \"benign\"\n                        )\n                        or any(ml.nlu_classifier(body.current_thread.text).entities,\n                               .name == \"disclaimer\"\n                        )\n                      )\n                      or not any(attachments,\n                                 any(file.explode(.),\n                                     any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                                         .name == \"benign\"\n                                     )\n                                 )\n                      )\n                      // the QR code contains the email address of a recipient\n                      or (\n                        any(filter(recipients.to, .email.domain.valid),\n                            strings.icontains(..scan.qr.url.url, .email.email)\n                        )\n                      )\n                    )\n\n                    // exclude google maps\n                    and not strings.starts_with(.scan.qr.url.url,\n                                                'https://goo.gl/maps'\n                    )\n                    and not strings.starts_with(.scan.qr.url.url,\n                                                'https://maps.app.goo.gl'\n                    )\n                  )\n                )\n\n                // the QR code url is a bing open redirect\n                or (\n                  .scan.qr.url.domain.root_domain == 'bing.com'\n                  and .scan.qr.url.path =~ '/ck/a'\n                )\n                // QR code contains non ascii chars\n                or regex.contains(.scan.qr.url.url, '[^\\x00-\\x7F]')\n                or (\n                  (\n                    // usap-dc open redirect\n                    .scan.qr.url.domain.root_domain == \"usap-dc.org\"\n                    and .scan.qr.url.path =~ \"/tracker\"\n                    and strings.starts_with(.scan.qr.url.query_params,\n                                            \"type=dataset&url=http\"\n                    )\n                  )\n                  // the QR code contains the email address of a recipient\n                  // allowing for base64 encoded variants\n                  or (\n                    any(filter(recipients.to, .email.domain.valid),\n                        strings.icontains(..scan.qr.url.url, .email.email)\n                        or any(strings.scan_base64(..scan.qr.url.url,\n                                                   ignore_padding=true\n                               ),\n                               strings.icontains(., ..email.email)\n                        )\n                        or any(strings.scan_base64(..scan.qr.url.fragment,\n                                                   ignore_padding=true\n                               ),\n                               strings.icontains(., ..email.email)\n                        )\n                    )\n                  )\n                )\n              )\n          )\n        )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      or
        length func_call "(\n        length(filter(attachments,\n                      strings.icontains(.file_name, 'adobe')\n                      or strings.icontains(.file_name, 'office')\n                      or strings.icontains(.file_name, 'appstore')\n                      or strings.icontains(.file_name, 'google')\n                      or strings.icontains(.file_name, 'padlock')\n                      or regex.icontains(.file_name, '\\bdoc\\b')\n               )\n        ) > 3\n      )"
         macro "any(filter(attachments, .file_extension in ('pdf', 'docx')),\n             any(filter(recipients.to, .email.domain.valid),\n                 strings.icontains(..file_name, .email.domain.sld)\n             )\n      )"
      attachments length_compare "3"
      attachments length_compare "20"
      length func_call "length(distinct(map(attachments, .file_extension))) == 2"
       macro "all(distinct(map(attachments, .file_extension)),\n            . in ('png', 'pdf', 'docx')\n    )"
    and
      attachments length_compare "1"
      attachments length_compare "3"
  type.inbound eq "true"

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"

Attachment: QR code with encoded recipient targeting and redirect indicators

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

Detects QR codes in attachments that contain the recipient's email address (either plaintext or base64 encoded) and redirect through suspicious URI structures commonly associated with Kratos/SneakyLog redirection services.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code, Evasion, Image as content, Open redirect

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule Body

type.inbound
// QR code detection in attachments
and any(attachments,
        (
          // Office documents
          .file_extension in $file_extensions_macros
          and any(file.explode(.),
                  .scan.qr.type == "url"
                  // QR code URL contains recipient's email (targeting indicator)
                  and any(recipients.to,
                          .email.domain.valid
                          and (
                            // Plaintext email address in URL
                            strings.icontains(..scan.qr.url.url, .email.email)
                            // OR base64 encoded email address
                            or any(strings.scan_base64(..scan.qr.url.url,
                                                       format="url",
                                                       ignore_padding=true
                                   ),
                                   strings.icontains(., ..email.email)
                            )
                          )
                  )
                  // URI Struct for Common Kratos/SneakyLog Redir
                  and regex.contains(.scan.qr.url.url,
                                     '\.(?:c(?:ompany|you)|sbs)(?:[$#]|\?a=)'
                  )
          )
        )
        or (
          // pdf or images
          (
            .file_type == "pdf" or .file_type in $file_types_images
          )
          //
          // This rule makes use of a beta feature and is subject to change without notice
          // using the beta feature in custom rules is not suggested until it has been formally released
          //
          and any(beta.scan_qr(.).items,
                  .type is not null
                  and regex.contains(.url.url,
                                     '\.(?:c(?:ompany|you)|sbs)(?:[$#]|\?a=)'
                  )
          )
        )
)

Detection Logic

Scope: inbound message.

Detects QR codes in attachments that contain the recipient's email address (either plaintext or base64 encoded) and redirect through suspicious URI structures commonly associated with Kratos/SneakyLog redirection services.

  1. inbound message
  2. any of attachments where any holds:
    • all of:
      • .file_extension in $file_extensions_macros
      • any(file.explode(.), .scan.qr.type == "url" // QR code URL contains recipient's email (targeting indicator) and any(recipients.to, .email.domain.valid and ( // Plaintext email address in URL strings.icontains(..scan.qr.url.url, .email.email) // OR base64 encoded email address or any(strings.scan_base64(..scan.qr.url.url, format="url", ignore_padding=true ), strings.icontains(., ..email.email) ) ) ) // URI Struct for Common Kratos/SneakyLog Redir and regex.contains(.scan.qr.url.url, '\.(?:c(?:ompany|you)|sbs)(?:[$#]|\?a=)' ) )
    • all of:
      • any of:
        • .file_type is 'pdf'
        • .file_type in $file_types_images
      • any(beta.scan_qr(.).items, .type is not null and regex.contains(.url.url, '\.(?:c(?:ompany|you)|sbs)(?:[$#]|\?a=)' ) )

Inspects: attachments[].file_extension, attachments[].file_type, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: beta.scan_qr, file.explode, regex.contains, strings.icontains, strings.scan_base64. Reference lists: $file_extensions_macros, $file_types_images.

Indicators Matched (3)

FieldMatchValue
file.explode(attachments[])[].scan.qr.typeequalsurl
regex.containsregex\.(?:c(?:ompany|you)|sbs)(?:[$#]|\?a=)
attachments[].file_typeequalspdf

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        or
          attachments.file_type eq "pdf"
          attachments.file_type macro "attachments[].file_type in file_types_images"
         macro "any(beta.scan_qr(.).items,\n                  .type is not null\n                  and regex.contains(.url.url,\n                                     '\\.(?:c(?:ompany|you)|sbs)(?:[$#]|\\?a=)'\n                  )\n          )"
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
         macro "any(file.explode(.),\n                  .scan.qr.type == \"url\"\n                  // QR code URL contains recipient's email (targeting indicator)\n                  and any(recipients.to,\n                          .email.domain.valid\n                          and (\n                            // Plaintext email address in URL\n                            strings.icontains(..scan.qr.url.url, .email.email)\n                            // OR base64 encoded email address\n                            or any(strings.scan_base64(..scan.qr.url.url,\n                                                       format=\"url\",\n                                                       ignore_padding=true\n                                   ),\n                                   strings.icontains(., ..email.email)\n                            )\n                          )\n                  )\n                  // URI Struct for Common Kratos/SneakyLog Redir\n                  and regex.contains(.scan.qr.url.url,\n                                     '\\.(?:c(?:ompany|you)|sbs)(?:[$#]|\\?a=)'\n                  )\n          )"
  type.inbound eq "true"

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"

Attachment: QR code with recipient targeting and special characters

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

Detects messages with QR code in attachments containing special characters in the path that include the recipient's email address in either the URL path or fragment, potentially encoded in base64. The URLs have a simple path structure and may end with suspicious patterns.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • recipients.to[0]
  • type

Rule Body

type.inbound
and length(recipients.to) == 1
and recipients.to[0].email.domain.valid
and any(attachments,
        (
          // Office documents
          .file_extension in $file_extensions_macros
          and any(file.explode(.),
                  .scan.qr.type == "url"
                  // QR code URL contains recipient's email (targeting indicator)
                  and any(recipients.to,
                          .email.domain.valid
                          and (
                            // Plaintext email address in URL
                            strings.icontains(..scan.qr.url.url, .email.email)
                            // OR base64 encoded email address
                            or any(strings.scan_base64(..scan.qr.url.url,
                                                       format="url",
                                                       ignore_padding=true
                                   ),
                                   strings.icontains(., ..email.email)
                            )
                          )
                  )
                  // a single path
                  and strings.count(.scan.qr.url.path, '/') == 2
                  and (
                    (
                      (
                        strings.contains(.scan.qr.url.path, '/$')
                        or strings.contains(.scan.qr.url.path, '/*')
                        or strings.contains(.scan.qr.url.path, '/#')
                      )
                      // subdomain should contain num{3}alpha or alphanum{3}
                      and regex.icontains(.scan.qr.url.domain.subdomain,
                                          '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)'
                      )
                      // url path should contain num{3}alpha or alphanum{3}
                      and regex.icontains(.scan.qr.url.path,
                                          '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/'
                      )
                    )
                    or (
                      // special char in the path
                      (
                        strings.contains(.scan.qr.url.path, '!')
                        or strings.contains(.scan.qr.url.path, '@')
                      )
                      and (
                        strings.contains(.scan.qr.url.path, '/$')
                        or strings.contains(.scan.qr.url.path, '/*')
                        or strings.contains(.scan.qr.url.path, '/#')
                        // hex dollar sign
                        or strings.icontains(.scan.qr.url.path, '%24')
                        // hex star
                        or strings.icontains(.scan.qr.url.path, '%2A')
                        // hex pound
                        or strings.icontains(.scan.qr.url.path, '%23')
                      )
                      // ensure expected ordering
                      and regex.icontains(.scan.qr.url.url,
                                          '[!@].*(?:[$*]|%2[A43])'
                      )
                    )
                  )
          )
        )
        or (
          // pdf or images
          (
            .file_type == "pdf" or .file_type in $file_types_images
          )
          //
          // This rule makes use of a beta feature and is subject to change without notice
          // using the beta feature in custom rules is not suggested until it has been formally released
          //
          and any(beta.scan_qr(.).items,
                  .type is not null
                  // a single path
                  and strings.count(.url.path, '/') == 2
                  and (
                    (
                      (
                        strings.contains(.url.path, '/$')
                        or strings.contains(.url.path, '/*')
                        or strings.contains(.url.path, '/#')
                      )
                      // subdomain should contain num{3}alpha or alphanum{3}
                      and regex.icontains(.url.domain.subdomain,
                                          '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)'
                      )
                      // url path should contain num{3}alpha or alphanum{3}
                      and regex.icontains(.url.path,
                                          '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/'
                      )
                    )
                    or (
                      // special char in the path
                      (
                        strings.contains(.url.path, '!')
                        or strings.contains(.url.path, '@')
                      )
                      and (
                        strings.contains(.url.path, '/$')
                        or strings.contains(.url.path, '/*')
                        or strings.contains(.url.path, '/#')
                        // hex dollar sign
                        or strings.icontains(.url.path, '%24')
                        // hex star
                        or strings.icontains(.url.path, '%2A')
                        // hex pound
                        or strings.icontains(.url.path, '%23')
                      )
                      // ensure expected ordering
                      and regex.icontains(.url.url, '[!@].*(?:[$*]|%2[A43])')
                    )
                  )
          )
        )
)

Detection Logic

Scope: inbound message.

Detects messages with QR code in attachments containing special characters in the path that include the recipient's email address in either the URL path or fragment, potentially encoded in base64. The URLs have a simple path structure and may end with suspicious patterns.

  1. inbound message
  2. length(recipients.to) == 1
  3. recipients.to[0].email.domain.valid
  4. any of attachments where any holds:
    • all of:
      • .file_extension in $file_extensions_macros
      • any(file.explode(.), .scan.qr.type == "url" // QR code URL contains recipient's email (targeting indicator) and any(recipients.to, .email.domain.valid and ( // Plaintext email address in URL strings.icontains(..scan.qr.url.url, .email.email) // OR base64 encoded email address or any(strings.scan_base64(..scan.qr.url.url, format="url", ignore_padding=true ), strings.icontains(., ..email.email) ) ) ) // a single path and strings.count(.scan.qr.url.path, '/') == 2 and ( ( ( strings.contains(.scan.qr.url.path, '/$') or strings.contains(.scan.qr.url.path, '/*') or strings.contains(.scan.qr.url.path, '/#') ) // subdomain should contain num{3}alpha or alphanum{3} and regex.icontains(.scan.qr.url.domain.subdomain, '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)' ) // url path should contain num{3}alpha or alphanum{3} and regex.icontains(.scan.qr.url.path, '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/' ) ) or ( // special char in the path ( strings.contains(.scan.qr.url.path, '!') or strings.contains(.scan.qr.url.path, '@') ) and ( strings.contains(.scan.qr.url.path, '/$') or strings.contains(.scan.qr.url.path, '/*') or strings.contains(.scan.qr.url.path, '/#') // hex dollar sign or strings.icontains(.scan.qr.url.path, '%24') // hex star or strings.icontains(.scan.qr.url.path, '%2A') // hex pound or strings.icontains(.scan.qr.url.path, '%23') ) // ensure expected ordering and regex.icontains(.scan.qr.url.url, '[!@].*(?:[$*]|%2[A43])' ) ) ) )
    • all of:
      • any of:
        • .file_type is 'pdf'
        • .file_type in $file_types_images
      • any(beta.scan_qr(.).items, .type is not null // a single path and strings.count(.url.path, '/') == 2 and ( ( ( strings.contains(.url.path, '/$') or strings.contains(.url.path, '/*') or strings.contains(.url.path, '/#') ) // subdomain should contain num{3}alpha or alphanum{3} and regex.icontains(.url.domain.subdomain, '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)' ) // url path should contain num{3}alpha or alphanum{3} and regex.icontains(.url.path, '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/' ) ) or ( // special char in the path ( strings.contains(.url.path, '!') or strings.contains(.url.path, '@') ) and ( strings.contains(.url.path, '/$') or strings.contains(.url.path, '/*') or strings.contains(.url.path, '/#') // hex dollar sign or strings.icontains(.url.path, '%24') // hex star or strings.icontains(.url.path, '%2A') // hex pound or strings.icontains(.url.path, '%23') ) // ensure expected ordering and regex.icontains(.url.url, '[!@].*(?:[$*]|%2[A43])') ) ) )

Inspects: attachments[].file_extension, attachments[].file_type, recipients.to, recipients.to[0].email.domain.valid, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: beta.scan_qr, file.explode, regex.icontains, strings.contains, strings.count, strings.icontains, strings.scan_base64. Reference lists: $file_extensions_macros, $file_types_images.

Indicators Matched (13)

FieldMatchValue
file.explode(attachments[])[].scan.qr.typeequalsurl
strings.containssubstring/$
strings.containssubstring/*
strings.containssubstring/#
regex.icontainsregex^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)
regex.icontainsregex\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/
strings.containssubstring!
strings.containssubstring@
strings.icontainssubstring%24
strings.icontainssubstring%2A
strings.icontainssubstring%23
regex.icontainsregex[!@].*(?:[$*]|%2[A43])
1 more
attachments[].file_typeequalspdf

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        or
          attachments.file_type eq "pdf"
          attachments.file_type macro "attachments[].file_type in file_types_images"
         macro "any(beta.scan_qr(.).items,\n                  .type is not null\n                  // a single path\n                  and strings.count(.url.path, '/') == 2\n                  and (\n                    (\n                      (\n                        strings.contains(.url.path, '/$')\n                        or strings.contains(.url.path, '/*')\n                        or strings.contains(.url.path, '/#')\n                      )\n                      // subdomain should contain num{3}alpha or alphanum{3}\n                      and regex.icontains(.url.domain.subdomain,\n                                          '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'\n                      )\n                      // url path should contain num{3}alpha or alphanum{3}\n                      and regex.icontains(.url.path,\n                                          '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'\n                      )\n                    )\n                    or (\n                      // special char in the path\n                      (\n                        strings.contains(.url.path, '!')\n                        or strings.contains(.url.path, '@')\n                      )\n                      and (\n                        strings.contains(.url.path, '/$')\n                        or strings.contains(.url.path, '/*')\n                        or strings.contains(.url.path, '/#')\n                        // hex dollar sign\n                        or strings.icontains(.url.path, '%24')\n                        // hex star\n                        or strings.icontains(.url.path, '%2A')\n                        // hex pound\n                        or strings.icontains(.url.path, '%23')\n                      )\n                      // ensure expected ordering\n                      and regex.icontains(.url.url, '[!@].*(?:[$*]|%2[A43])')\n                    )\n                  )\n          )"
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
         macro "any(file.explode(.),\n                  .scan.qr.type == \"url\"\n                  // QR code URL contains recipient's email (targeting indicator)\n                  and any(recipients.to,\n                          .email.domain.valid\n                          and (\n                            // Plaintext email address in URL\n                            strings.icontains(..scan.qr.url.url, .email.email)\n                            // OR base64 encoded email address\n                            or any(strings.scan_base64(..scan.qr.url.url,\n                                                       format=\"url\",\n                                                       ignore_padding=true\n                                   ),\n                                   strings.icontains(., ..email.email)\n                            )\n                          )\n                  )\n                  // a single path\n                  and strings.count(.scan.qr.url.path, '/') == 2\n                  and (\n                    (\n                      (\n                        strings.contains(.scan.qr.url.path, '/$')\n                        or strings.contains(.scan.qr.url.path, '/*')\n                        or strings.contains(.scan.qr.url.path, '/#')\n                      )\n                      // subdomain should contain num{3}alpha or alphanum{3}\n                      and regex.icontains(.scan.qr.url.domain.subdomain,\n                                          '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'\n                      )\n                      // url path should contain num{3}alpha or alphanum{3}\n                      and regex.icontains(.scan.qr.url.path,\n                                          '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'\n                      )\n                    )\n                    or (\n                      // special char in the path\n                      (\n                        strings.contains(.scan.qr.url.path, '!')\n                        or strings.contains(.scan.qr.url.path, '@')\n                      )\n                      and (\n                        strings.contains(.scan.qr.url.path, '/$')\n                        or strings.contains(.scan.qr.url.path, '/*')\n                        or strings.contains(.scan.qr.url.path, '/#')\n                        // hex dollar sign\n                        or strings.icontains(.scan.qr.url.path, '%24')\n                        // hex star\n                        or strings.icontains(.scan.qr.url.path, '%2A')\n                        // hex pound\n                        or strings.icontains(.scan.qr.url.path, '%23')\n                      )\n                      // ensure expected ordering\n                      and regex.icontains(.scan.qr.url.url,\n                                          '[!@].*(?:[$*]|%2[A43])'\n                      )\n                    )\n                  )\n          )"
  recipients.to length_compare "1"
  recipients.to[0].email.domain.valid eq "true"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
recipients.to[0].email.domain.valideq
  • true transforms: boolean corpus 15 (mql 15)
field:"recipients.to[0].email.domain.valid" kind:eq value:"true"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: QR code with suspicious URL patterns in EML file

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

Detects EML attachments containing QR codes that link to URLs with suspicious patterns, including specific alphanumeric combinations in subdomains and paths, or special characters followed by encoded terminators. These patterns are commonly used to evade detection in credential theft attacks.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code, Evasion, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • recipients
  • recipients.to
  • recipients.to[0]
  • type

Rule Body

type.inbound
and length(recipients.to) == 1
and recipients.to[0].email.domain.valid
and any(attachments,
        // Email Attachments
        any(file.parse_eml(.).attachments,
            (
              // looks for office docs in the attached eml
              .file_extension in $file_extensions_macros
              and any(file.explode(.),
                      .scan.qr.type == "url"
                      // QR code URL contains recipient's email (targeting indicator)
                      and any(recipients.to,
                              .email.domain.valid
                              and (
                                // Plaintext email address in URL
                                strings.icontains(..scan.qr.url.url,
                                                  .email.email
                                )
                                // OR base64 encoded email address
                                or any(strings.scan_base64(..scan.qr.url.url,
                                                           format="url",
                                                           ignore_padding=true
                                       ),
                                       strings.icontains(., ..email.email)
                                )
                              )
                      )
                      // a single path
                      and strings.count(.scan.qr.url.path, '/') == 2
                      and (
                        (
                          (
                            strings.contains(.scan.qr.url.path, '/$')
                            or strings.contains(.scan.qr.url.path, '/*')
                            or strings.contains(.scan.qr.url.path, '/#')
                          )
                          // subdomain should contain num{3}alpha or alphanum{3}
                          and regex.icontains(.scan.qr.url.domain.subdomain,
                                              '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)'
                          )
                          // url path should contain num{3}alpha or alphanum{3}
                          and regex.icontains(.scan.qr.url.path,
                                              '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/'
                          )
                        )
                        or (
                          // special char in the path
                          (
                            strings.contains(.scan.qr.url.path, '!')
                            or strings.contains(.scan.qr.url.path, '@')
                          )
                          and (
                            strings.contains(.scan.qr.url.path, '/$')
                            or strings.contains(.scan.qr.url.path, '/*')
                            or strings.contains(.scan.qr.url.path, '/#')
                            // hex dollar sign
                            or strings.icontains(.scan.qr.url.path, '%24')
                            // hex star
                            or strings.icontains(.scan.qr.url.path, '%2A')
                            // hex pound
                            or strings.icontains(.scan.qr.url.path, '%23')
                          )
                          // ensure expected ordering
                          and regex.icontains(.scan.qr.url.url,
                                              '[!@].*(?:[$*]|%2[A43])'
                          )
                        )
                      )
              )
            )
            or (
              // looks for pdfs and images in the attached eml
              //
              // This rule makes use of a beta feature and is subject to change without notice
              // using the beta feature in custom rules is not suggested until it has been formally released
              //
              any(beta.scan_qr(.).items,
                  .type is not null
                  // a single path
                  and strings.count(.url.path, '/') == 2
                  and (
                    (
                      (
                        strings.contains(.url.path, '/$')
                        or strings.contains(.url.path, '/*')
                        or strings.contains(.url.path, '/#')
                      )
                      // subdomain should contain num{3}alpha or alphanum{3}
                      and regex.icontains(.url.domain.subdomain,
                                          '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)'
                      )
                      // url path should contain num{3}alpha or alphanum{3}
                      and regex.icontains(.url.path,
                                          '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/'
                      )
                    )
                    or (
                      // special char in the path
                      (
                        strings.contains(.url.path, '!')
                        or strings.contains(.url.path, '@')
                      )
                      and (
                        strings.contains(.url.path, '/$')
                        or strings.contains(.url.path, '/*')
                        or strings.contains(.url.path, '/#')
                        // hex dollar sign
                        or strings.icontains(.url.path, '%24')
                        // hex star
                        or strings.icontains(.url.path, '%2A')
                        // hex pound
                        or strings.icontains(.url.path, '%23')
                      )
                      // ensure expected ordering
                      and regex.icontains(.url.url, '[!@].*(?:[$*]|%2[A43])')
                    )
                  )
              )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects EML attachments containing QR codes that link to URLs with suspicious patterns, including specific alphanumeric combinations in subdomains and paths, or special characters followed by encoded terminators. These patterns are commonly used to evade detection in credential theft attacks.

  1. inbound message
  2. length(recipients.to) == 1
  3. recipients.to[0].email.domain.valid
  4. any of attachments where:
    • any(file.parse_eml(.).attachments, ( // looks for office docs in the attached eml .file_extension in $file_extensions_macros and any(file.explode(.), .scan.qr.type == "url" // QR code URL contains recipient's email (targeting indicator) and any(recipients.to, .email.domain.valid and ( // Plaintext email address in URL strings.icontains(..scan.qr.url.url, .email.email ) // OR base64 encoded email address or any(strings.scan_base64(..scan.qr.url.url, format="url", ignore_padding=true ), strings.icontains(., ..email.email) ) ) ) // a single path and strings.count(.scan.qr.url.path, '/') == 2 and ( ( ( strings.contains(.scan.qr.url.path, '/$') or strings.contains(.scan.qr.url.path, '/*') or strings.contains(.scan.qr.url.path, '/#') ) // subdomain should contain num{3}alpha or alphanum{3} and regex.icontains(.scan.qr.url.domain.subdomain, '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)' ) // url path should contain num{3}alpha or alphanum{3} and regex.icontains(.scan.qr.url.path, '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/' ) ) or ( // special char in the path ( strings.contains(.scan.qr.url.path, '!') or strings.contains(.scan.qr.url.path, '@') ) and ( strings.contains(.scan.qr.url.path, '/$') or strings.contains(.scan.qr.url.path, '/*') or strings.contains(.scan.qr.url.path, '/#') // hex dollar sign or strings.icontains(.scan.qr.url.path, '%24') // hex star or strings.icontains(.scan.qr.url.path, '%2A') // hex pound or strings.icontains(.scan.qr.url.path, '%23') ) // ensure expected ordering and regex.icontains(.scan.qr.url.url, '[!@].*(?:[$*]|%2[A43])' ) ) ) ) ) or ( // looks for pdfs and images in the attached eml // // This rule makes use of a beta feature and is subject to change without notice // using the beta feature in custom rules is not suggested until it has been formally released // any(beta.scan_qr(.).items, .type is not null // a single path and strings.count(.url.path, '/') == 2 and ( ( ( strings.contains(.url.path, '/$') or strings.contains(.url.path, '/*') or strings.contains(.url.path, '/#') ) // subdomain should contain num{3}alpha or alphanum{3} and regex.icontains(.url.domain.subdomain, '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)' ) // url path should contain num{3}alpha or alphanum{3} and regex.icontains(.url.path, '\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/' ) ) or ( // special char in the path ( strings.contains(.url.path, '!') or strings.contains(.url.path, '@') ) and ( strings.contains(.url.path, '/$') or strings.contains(.url.path, '/*') or strings.contains(.url.path, '/#') // hex dollar sign or strings.icontains(.url.path, '%24') // hex star or strings.icontains(.url.path, '%2A') // hex pound or strings.icontains(.url.path, '%23') ) // ensure expected ordering and regex.icontains(.url.url, '[!@].*(?:[$*]|%2[A43])') ) ) ) ) )

Inspects: recipients.to, recipients.to[0].email.domain.valid, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: beta.scan_qr, file.explode, file.parse_eml, regex.icontains, strings.contains, strings.count, strings.icontains, strings.scan_base64. Reference lists: $file_extensions_macros.

Indicators Matched (12)

FieldMatchValue
file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.typeequalsurl
strings.containssubstring/$
strings.containssubstring/*
strings.containssubstring/#
regex.icontainsregex^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\.)
regex.icontainsregex\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\/
strings.containssubstring!
strings.containssubstring@
strings.icontainssubstring%24
strings.icontainssubstring%2A
strings.icontainssubstring%23
regex.icontainsregex[!@].*(?:[$*]|%2[A43])

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
     macro "any(file.parse_eml(.).attachments,\n            (\n              // looks for office docs in the attached eml\n              .file_extension in $file_extensions_macros\n              and any(file.explode(.),\n                      .scan.qr.type == \"url\"\n                      // QR code URL contains recipient's email (targeting indicator)\n                      and any(recipients.to,\n                              .email.domain.valid\n                              and (\n                                // Plaintext email address in URL\n                                strings.icontains(..scan.qr.url.url,\n                                                  .email.email\n                                )\n                                // OR base64 encoded email address\n                                or any(strings.scan_base64(..scan.qr.url.url,\n                                                           format=\"url\",\n                                                           ignore_padding=true\n                                       ),\n                                       strings.icontains(., ..email.email)\n                                )\n                              )\n                      )\n                      // a single path\n                      and strings.count(.scan.qr.url.path, '/') == 2\n                      and (\n                        (\n                          (\n                            strings.contains(.scan.qr.url.path, '/$')\n                            or strings.contains(.scan.qr.url.path, '/*')\n                            or strings.contains(.scan.qr.url.path, '/#')\n                          )\n                          // subdomain should contain num{3}alpha or alphanum{3}\n                          and regex.icontains(.scan.qr.url.domain.subdomain,\n                                              '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'\n                          )\n                          // url path should contain num{3}alpha or alphanum{3}\n                          and regex.icontains(.scan.qr.url.path,\n                                              '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'\n                          )\n                        )\n                        or (\n                          // special char in the path\n                          (\n                            strings.contains(.scan.qr.url.path, '!')\n                            or strings.contains(.scan.qr.url.path, '@')\n                          )\n                          and (\n                            strings.contains(.scan.qr.url.path, '/$')\n                            or strings.contains(.scan.qr.url.path, '/*')\n                            or strings.contains(.scan.qr.url.path, '/#')\n                            // hex dollar sign\n                            or strings.icontains(.scan.qr.url.path, '%24')\n                            // hex star\n                            or strings.icontains(.scan.qr.url.path, '%2A')\n                            // hex pound\n                            or strings.icontains(.scan.qr.url.path, '%23')\n                          )\n                          // ensure expected ordering\n                          and regex.icontains(.scan.qr.url.url,\n                                              '[!@].*(?:[$*]|%2[A43])'\n                          )\n                        )\n                      )\n              )\n            )\n            or (\n              // looks for pdfs and images in the attached eml\n              //\n              // This rule makes use of a beta feature and is subject to change without notice\n              // using the beta feature in custom rules is not suggested until it has been formally released\n              //\n              any(beta.scan_qr(.).items,\n                  .type is not null\n                  // a single path\n                  and strings.count(.url.path, '/') == 2\n                  and (\n                    (\n                      (\n                        strings.contains(.url.path, '/$')\n                        or strings.contains(.url.path, '/*')\n                        or strings.contains(.url.path, '/#')\n                      )\n                      // subdomain should contain num{3}alpha or alphanum{3}\n                      and regex.icontains(.url.domain.subdomain,\n                                          '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'\n                      )\n                      // url path should contain num{3}alpha or alphanum{3}\n                      and regex.icontains(.url.path,\n                                          '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'\n                      )\n                    )\n                    or (\n                      // special char in the path\n                      (\n                        strings.contains(.url.path, '!')\n                        or strings.contains(.url.path, '@')\n                      )\n                      and (\n                        strings.contains(.url.path, '/$')\n                        or strings.contains(.url.path, '/*')\n                        or strings.contains(.url.path, '/#')\n                        // hex dollar sign\n                        or strings.icontains(.url.path, '%24')\n                        // hex star\n                        or strings.icontains(.url.path, '%2A')\n                        // hex pound\n                        or strings.icontains(.url.path, '%23')\n                      )\n                      // ensure expected ordering\n                      and regex.icontains(.url.url, '[!@].*(?:[$*]|%2[A43])')\n                    )\n                  )\n              )\n            )\n        )"
  recipients.to length_compare "1"
  recipients.to[0].email.domain.valid eq "true"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
recipients.to[0].email.domain.valideq
  • true transforms: boolean corpus 15 (mql 15)
field:"recipients.to[0].email.domain.valid" kind:eq value:"true"
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Attachment: QR code with userinfo portion

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

Detects inbound messages that contain image or document attachments with QR codes containing embedded usernames, passwords, or excessively padded URLs. This technique is used to bypass traditional text-based detection methods.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, Image as content, PDF, QR code

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.cc
  • recipients.to
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_type in $file_types_images
          or .file_extension in $file_extensions_macros
          or .file_type == "pdf"
        )
        and any(file.explode(.),
                (
                  .scan.qr.url.username is not null
                  or .scan.qr.url.password is not null
                  // keep in sync with https://github.com/sublime-security/sublime-rules/blob/main/detection-rules/link_userinfo_excessive_padding.yml
                  or regex.icontains(coalesce(.scan.qr.url.rewrite.original,
                                              .scan.qr.url.url
                                     ),
                                     'https?(?:(?:%3a|\:)?(?:\/|%2f){2})[^\/]+(?:\s+|%(?:25)?[a-f0-9]{2}|0x[a-f0-9]+){30,}(?:@|%(?:25)?40)[^\/]+(?:\/|%(?:25)?2f)'
                  )
                )
                and .scan.qr.url.domain.root_domain != sender.email.domain.root_domain
                and not any(recipients.to,
                            .email.domain.root_domain == ..scan.qr.url.domain.root_domain
                )
                and not any(recipients.cc,
                            .email.domain.root_domain == ..scan.qr.url.domain.root_domain
                )
                // an error to strings.parse_email returns null for the full object
                // this cehck ensures that the url is not a valid email address
                and strings.parse_email(.scan.qr.url.url).email is null
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages that contain image or document attachments with QR codes containing embedded usernames, passwords, or excessively padded URLs. This technique is used to bypass traditional text-based detection methods.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type in $file_types_images
      • .file_extension in $file_extensions_macros
      • .file_type is 'pdf'
    • any(file.explode(.), ( .scan.qr.url.username is not null or .scan.qr.url.password is not null // keep in sync with https://github.com/sublime-security/sublime-rules/blob/main/detection-rules/link_userinfo_excessive_padding.yml or regex.icontains(coalesce(.scan.qr.url.rewrite.original, .scan.qr.url.url ), 'https?(?:(?:%3a|\:)?(?:\/|%2f){2})[^\/]+(?:\s+|%(?:25)?[a-f0-9]{2}|0x[a-f0-9]+){30,}(?:@|%(?:25)?40)[^\/]+(?:\/|%(?:25)?2f)' ) ) and .scan.qr.url.domain.root_domain != sender.email.domain.root_domain and not any(recipients.to, .email.domain.root_domain == ..scan.qr.url.domain.root_domain ) and not any(recipients.cc, .email.domain.root_domain == ..scan.qr.url.domain.root_domain ) // an error to strings.parse_email returns null for the full object // this cehck ensures that the url is not a valid email address and strings.parse_email(.scan.qr.url.url).email is null )

Inspects: attachments[].file_extension, attachments[].file_type, recipients.cc, recipients.cc[].email.domain.root_domain, recipients.to, recipients.to[].email.domain.root_domain, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, regex.icontains, strings.parse_email. Reference lists: $file_extensions_macros, $file_types_images.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
regex.icontainsregexhttps?(?:(?:%3a|\:)?(?:\/|%2f){2})[^\/]+(?:\s+|%(?:25)?[a-f0-9]{2}|0x[a-f0-9]+){30,}(?:@|%(?:25)?40)[^\/]+(?:\/|%(?:25)?2f)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
        attachments.file_type eq "pdf"
        attachments.file_type macro "attachments[].file_type in file_types_images"
       macro "any(file.explode(.),\n                (\n                  .scan.qr.url.username is not null\n                  or .scan.qr.url.password is not null\n                  // keep in sync with https://github.com/sublime-security/sublime-rules/blob/main/detection-rules/link_userinfo_excessive_padding.yml\n                  or regex.icontains(coalesce(.scan.qr.url.rewrite.original,\n                                              .scan.qr.url.url\n                                     ),\n                                     'https?(?:(?:%3a|\\:)?(?:\\/|%2f){2})[^\\/]+(?:\\s+|%(?:25)?[a-f0-9]{2}|0x[a-f0-9]+){30,}(?:@|%(?:25)?40)[^\\/]+(?:\\/|%(?:25)?2f)'\n                  )\n                )\n                and .scan.qr.url.domain.root_domain != sender.email.domain.root_domain\n                and not any(recipients.to,\n                            .email.domain.root_domain == ..scan.qr.url.domain.root_domain\n                )\n                and not any(recipients.cc,\n                            .email.domain.root_domain == ..scan.qr.url.domain.root_domain\n                )\n                // an error to strings.parse_email returns null for the full object\n                // this cehck ensures that the url is not a valid email address\n                and strings.parse_email(.scan.qr.url.url).email is null\n        )"
  type.inbound eq "true"

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"

Attachment: QuickBooks PDF lure

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

Detects inbound messages containing PDF attachments that match YARA signatures identifying QuickBooks-themed lure content.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Malware/Ransomware
Tactics and techniquesPDF, Impersonation: Brand, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "pdf"),
        any(file.explode(.),
            any(.scan.yara.matches, .name == "quickbooks_pdf_payment_lure")
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages containing PDF attachments that match YARA signatures identifying QuickBooks-themed lure content.

  1. inbound message
  2. any(filter(attachments, .file_type == "pdf"), any(file.explode(.), any(.scan.yara.matches, .name == "quickbooks_pdf_payment_lure") ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalsquickbooks_pdf_payment_lure

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"pdf\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name == \"quickbooks_pdf_payment_lure\")\n        )\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"

Attachment: RDP connection file

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

Recursively scans files and archives to detect RDP connection files. Coercing a target user into connecting to an attacker-owned RDP server can expose elements of their host and potentially lead to compromise.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and (
  any(attachments, .file_extension =~ "rdp")
  or (
    any(attachments,
        .file_extension in~ $file_extensions_common_archives
        and any(file.explode(.), .file_extension =~ "rdp")
    )
  )
)

Detection Logic

Scope: inbound message.

Recursively scans files and archives to detect RDP connection files. Coercing a target user into connecting to an attacker-owned RDP server can expose elements of their host and potentially lead to compromise.

  1. inbound message
  2. any of:
    • any of attachments where:
      • .file_extension is 'rdp'
    • any of attachments where all hold:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), .file_extension =~ "rdp")

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $file_extensions_common_archives.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalsrdp
file.explode(attachments[])[].file_extensionequalsrdp

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.), .file_extension =~ \"rdp\")"
    any(attachments)
      attachments.file_extension eq "rdp"
  type.inbound eq "true"

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"

Attachment: RFC822 containing suspicious file sharing language with links from untrusted sender

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

This rule identifies messages with an RFC822 attachment contains language indicative of suspicious file-sharing activity. It checks both the original sender and the nested sender against highly trusted domains. The original message is unsolicited, and has not been previously flagged as a false positive.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.hops
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type == "unknown"
        and (.content_type == "message/rfc822" or .file_extension in ('eml'))
        and regex.contains(file.parse_eml(.).subject.subject,
                           '(shared.{0,30}with you|View Document)'
        )
        and 0 < length(file.parse_eml(.).body.links) < 10
        and file.parse_eml(.).sender.email.email not in $recipient_emails

        // exclude bounce backs & read receipts
        and not strings.like(file.parse_eml(.).sender.email.local_part,
                             "*postmaster*",
                             "*mailer-daemon*",
                             "*administrator*"
        )
        and not regex.imatch(file.parse_eml(.).subject.subject,
                             "(undeliverable|read:).*"
        )
        and not any(file.parse_eml(.).attachments,
                    .content_type == "message/delivery-status"
        )

        // negate highly trusted sender domains in the nested eml unless they fail DMARC
        and (
          (
            file.parse_eml(.).sender.email.domain.root_domain in $high_trust_sender_root_domains
            and (
              any(distinct(file.parse_eml(.).headers.hops,
                           .authentication_results.dmarc is not null
                  ),
                  strings.ilike(.authentication_results.dmarc, "*fail")
              )
            )
          )
          or file.parse_eml(.).sender.email.domain.root_domain not in $high_trust_sender_root_domains
        )
        // negate org domains that passed dmarc
        and not file.parse_eml(.).sender.email.domain.root_domain in $org_domains
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and (
      any(distinct(headers.hops, .authentication_results.dmarc is not null),
          strings.ilike(.authentication_results.dmarc, "*fail")
      )
    )
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

This rule identifies messages with an RFC822 attachment contains language indicative of suspicious file-sharing activity. It checks both the original sender and the nested sender against highly trusted domains. The original message is unsolicited, and has not been previously flagged as a false positive.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'unknown'
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension in ('eml')
    • regex.contains(file.parse_eml(.).subject.subject, '(shared.{0,30}with you|View Document)' )
    • all of:
      • (0) < (length(file.parse_eml(.).body.links))
      • (length(file.parse_eml(.).body.links)) < (10)
    • file.parse_eml(.).sender.email.email not in $recipient_emails
    • not:
      • strings.like(file.parse_eml(.).sender.email.local_part, "*postmaster*", "*mailer-daemon*", "*administrator*" )
    • not:
      • regex.imatch(file.parse_eml(.).subject.subject, "(undeliverable|read:).*" )
    • not:
      • any(file.parse_eml(.).attachments, .content_type == "message/delivery-status" )
    • any of:
      • all of:
        • file.parse_eml(.).sender.email.domain.root_domain in $high_trust_sender_root_domains
        • ( any(distinct(file.parse_eml(.).headers.hops, .authentication_results.dmarc is not null ), strings.ilike(.authentication_results.dmarc, "*fail") ) )
      • file.parse_eml(.).sender.email.domain.root_domain not in $high_trust_sender_root_domains
    • not:
      • file.parse_eml(.).sender.email.domain.root_domain in $org_domains
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • ( any(distinct(headers.hops, .authentication_results.dmarc is not null), strings.ilike(.authentication_results.dmarc, "*fail") ) )
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  4. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  5. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.hops, headers.hops[].authentication_results.dmarc, sender.email.domain.root_domain, type.inbound. Sensors: file.parse_eml, profile.by_sender, regex.contains, regex.imatch, strings.ilike, strings.like. Reference lists: $high_trust_sender_root_domains, $org_domains, $recipient_emails.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionmembereml
regex.containsregex(shared.{0,30}with you|View Document)
strings.ilikesubstring*fail

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          file.parse_eml func_call "file.parse_eml(.).sender.email.domain.root_domain in $high_trust_sender_root_domains"
           macro "(\n              any(distinct(file.parse_eml(.).headers.hops,\n                           .authentication_results.dmarc is not null\n                  ),\n                  strings.ilike(.authentication_results.dmarc, \"*fail\")\n              )\n            )"
        file.parse_eml func_call "file.parse_eml(.).sender.email.domain.root_domain not in $high_trust_sender_root_domains"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
      not
        file.parse_eml func_call "file.parse_eml(.).sender.email.domain.root_domain in $org_domains"
      not
        regex.imatch func_call "regex.imatch(file.parse_eml(.).subject.subject,\n                             \"(undeliverable|read:).*\"\n        )"
      not
        strings.like func_call "strings.like(file.parse_eml(.).sender.email.local_part,\n                             \"*postmaster*\",\n                             \"*mailer-daemon*\",\n                             \"*administrator*\"\n        )"
      not
         macro "any(file.parse_eml(.).attachments,\n                    .content_type == \"message/delivery-status\"\n        )"
      attachments.file_type eq "unknown"
      file.parse_eml func_call "file.parse_eml(.).sender.email.email not in $recipient_emails"
      length func_call "(0) < (length(file.parse_eml(.).body.links))"
      length func_call "(length(file.parse_eml(.).body.links)) < (10)"
      regex.contains func_call "regex.contains(file.parse_eml(.).subject.subject,\n                           '(shared.{0,30}with you|View Document)'\n        )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    and
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
       macro "(\n      any(distinct(headers.hops, .authentication_results.dmarc is not null),\n          strings.ilike(.authentication_results.dmarc, \"*fail\")\n      )\n    )"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Attachment: RFP/RFQ impersonating government entities

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

Attached RFP/RFQ impersonates a U.S. government department or entity to commit fraudulent transactions.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesImpersonation: Brand, PDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and length(attachments) == 1
and all(attachments,
        .file_extension in~ $file_extensions_macros or .file_type == "pdf"
)
and regex.icontains(body.current_thread.text, "department of|office of")
and (
  regex.icontains(subject.subject,
                  '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)'
  )
  or any(attachments,
         regex.icontains(.file_name,
                         '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)'
         )
  )
)
and strings.icontains(sender.email.domain.domain, "gov")
and (
  any(ml.nlu_classifier(body.current_thread.text).tags,
      .name == "purchase_order"
  )
  and any(attachments,
          any(file.explode(.),
              any(ml.nlu_classifier(.scan.ocr.raw).entities,
                  regex.icontains(.text, "department of|office of")
              )
          )
  )
)

Detection Logic

Scope: inbound message.

Attached RFP/RFQ impersonates a U.S. government department or entity to commit fraudulent transactions.

  1. inbound message
  2. length(attachments) == 1
  3. all of attachments where any holds:
    • .file_extension in $file_extensions_macros
    • .file_type is 'pdf'
  4. body.current_thread.text matches 'department of|office of'
  5. any of:
    • subject.subject matches '(request for (purchase|quot(e|ation))|\\bRFQ\\b|\\bRFP\\b)'
    • any of attachments where:
      • .file_name matches '(request for (purchase|quot(e|ation))|\\bRFQ\\b|\\bRFP\\b)'
  6. sender.email.domain.domain contains 'gov'
  7. all of:
    • any(ml.nlu_classifier(body.current_thread.text).tags, .name == "purchase_order" )
    • any of attachments where:
      • any(file.explode(.), any(ml.nlu_classifier(.scan.ocr.raw).entities, regex.icontains(.text, "department of|office of") ) )

Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, body.current_thread.text, sender.email.domain.domain, subject.subject, type.inbound. Sensors: file.explode, ml.nlu_classifier, regex.icontains, strings.icontains. Reference lists: $file_extensions_macros.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalspdf
regex.icontainsregexdepartment of|office of
regex.icontainsregex(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)
strings.icontainssubstringgov
ml.nlu_classifier(body.current_thread.text).tags[].nameequalspurchase_order

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      attachments.file_name regex_match "(request for (purchase|quot(e|ation))|\\bRFQ\\b|\\bRFP\\b)"
    subject.subject regex_match "(request for (purchase|quot(e|ation))|\\bRFQ\\b|\\bRFP\\b)"
  any(attachments)
     macro "any(file.explode(.),\n              any(ml.nlu_classifier(.scan.ocr.raw).entities,\n                  regex.icontains(.text, \"department of|office of\")\n              )\n          )"
  attachments length_compare "1"
  body.current_thread.text regex_match "department of|office of"
  sender.email.domain.domain contains "gov"
  type.inbound eq "true"
   macro "all(attachments,\n        .file_extension in~ $file_extensions_macros or .file_type == \"pdf\"\n)"
   macro "any(ml.nlu_classifier(body.current_thread.text).tags,\n      .name == \"purchase_order\"\n  )"

Indicators

These rows show field, operator, and value matches.

Attachment: Romance scam with image lure and advance-fee or suspicious link indicators

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

Detects inbound messages that are not replies, forwards, or mailing list communications, and contain image attachments (JPG or PNG) alongside body text classified as romantic or sexually explicit in nature. The messages either include links to known redirector or free hosting domains (such as geno.link or sites.google.com), or exhibit advance-fee fraud intent while routing replies to a free email provider despite originating from a corporate-looking sender domain. Senders observed span spoofed government and business addresses as well as free webmail accounts, with subject lines using romantic or personal connection lures.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Spam
Tactics and techniquesSocial engineering, Image as content, Free email provider, Free file host, Out of band pivot

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.links
  • headers
  • headers.hops
  • headers.reply_to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and not subject.is_reply
and not subject.is_forward
and not any(headers.hops,
            any(.fields,
                strings.ilike(.name, "List-Id")
                or strings.ilike(.name, "List-Unsubscribe")
            )
)
and any(attachments, .file_type in ("jpg", "png"))
and any(ml.nlu_classifier(body.current_thread.text).topics,
        .name in ("Romance", "Sexually Explicit Messages")
        and .confidence != 'low'
)
and (
  any(body.links, .href_url.domain.domain in ("geno.link", "sites.google.com"))
  or (
    any(headers.reply_to, .email.domain.root_domain in $free_email_providers)
    and sender.email.domain.root_domain not in $free_email_providers
    and any(ml.nlu_classifier(body.current_thread.text).intents,
            .name == "advance_fee" and .confidence != 'low'
    )
  )
)

Detection Logic

Scope: inbound message.

Detects inbound messages that are not replies, forwards, or mailing list communications, and contain image attachments (JPG or PNG) alongside body text classified as romantic or sexually explicit in nature. The messages either include links to known redirector or free hosting domains (such as geno.link or sites.google.com), or exhibit advance-fee fraud intent while routing replies to a free email provider despite originating from a corporate-looking sender domain. Senders observed span spoofed government and business addresses as well as free webmail accounts, with subject lines using romantic or personal connection lures.

  1. inbound message
  2. not:
    • subject.is_reply
  3. not:
    • subject.is_forward
  4. not:
    • any of headers.hops where:
      • any of .fields where any holds:
        • .name matches 'List-Id'
        • .name matches 'List-Unsubscribe'
  5. any of attachments where:
    • .file_type in ('jpg', 'png')
  6. any(ml.nlu_classifier(body.current_thread.text).topics, .name in ("Romance", "Sexually Explicit Messages") and .confidence != 'low' )
  7. any of:
    • any of body.links where:
      • .href_url.domain.domain in ('geno.link', 'sites.google.com')
    • all of:
      • any of headers.reply_to where:
        • .email.domain.root_domain in $free_email_providers
      • sender.email.domain.root_domain not in $free_email_providers
      • any(ml.nlu_classifier(body.current_thread.text).intents, .name == "advance_fee" and .confidence != 'low' )

Inspects: attachments[].file_type, body.current_thread.text, body.links, body.links[].href_url.domain.domain, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, headers.reply_to, headers.reply_to[].email.domain.root_domain, sender.email.domain.root_domain, subject.is_forward, subject.is_reply, type.inbound. Sensors: ml.nlu_classifier, strings.ilike. Reference lists: $free_email_providers.

Indicators Matched (7)

FieldMatchValue
attachments[].file_typememberjpg
attachments[].file_typememberpng
ml.nlu_classifier(body.current_thread.text).topics[].namememberRomance
ml.nlu_classifier(body.current_thread.text).topics[].namememberSexually Explicit Messages
body.links[].href_url.domain.domainmembergeno.link
body.links[].href_url.domain.domainmembersites.google.com
ml.nlu_classifier(body.current_thread.text).intents[].nameequalsadvance_fee

Stages and Predicates

Stage 1: mql_rule

and
  not
    any(headers.hops)
      any(headers.hops.fields)
        or
          headers.hops.fields[].name eq "List-Id"
          headers.hops.fields[].name eq "List-Unsubscribe"
  or
    and
      any(headers.reply_to)
        headers.reply_to.email.domain.root_domain macro "headers.reply_to[].email.domain.root_domain in free_email_providers"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain not in free_email_providers"
       macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n            .name == \"advance_fee\" and .confidence != 'low'\n    )"
    any(body.links)
      body.links.href_url.domain.domain in ["geno.link", "sites.google.com"]
  any(attachments)
    attachments.file_type in ["jpg", "png"]
  not
    subject.is_forward eq "true"
  not
    subject.is_reply eq "true"
  type.inbound eq "true"
   macro "any(ml.nlu_classifier(body.current_thread.text).topics,\n        .name in (\"Romance\", \"Sexually Explicit Messages\")\n        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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops
subject.is_forwardeqtrueexcludes:subject.is_forward field:"subject.is_forward" value:"true"
subject.is_replyeqtrueexcludes:subject.is_reply field:"subject.is_reply" value:"true"

Attachment: RTF file with suspicious link

#

Attachment: RTF with embedded content

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

RTF files can contain embedded content similar to OLE files (Microsoft Office documents.)

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type == "rtf"
        and any(file.explode(.),
                .flavors.mime in~ (
                  "application/x-dosexec",
                  "text/x-msdos-batch",
                  "application/octet-stream"
                )
                or any(.flavors.yara, . == 'base64_pe')
                or .file_extension in~ ("bat", "exe", "vbs")
        )
)

Detection Logic

Scope: inbound message.

RTF files can contain embedded content similar to OLE files (Microsoft Office documents.)

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'rtf'
    • any(file.explode(.), .flavors.mime in~ ( "application/x-dosexec", "text/x-msdos-batch", "application/octet-stream" ) or any(.flavors.yara, . == 'base64_pe') or .file_extension in~ ("bat", "exe", "vbs") )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (8)

FieldMatchValue
attachments[].file_typeequalsrtf
file.explode(attachments[])[].flavors.mimememberapplication/x-dosexec
file.explode(attachments[])[].flavors.mimemembertext/x-msdos-batch
file.explode(attachments[])[].flavors.mimememberapplication/octet-stream
file.explode(attachments[])[].flavors.yara[]equalsbase64_pe
file.explode(attachments[])[].file_extensionmemberbat
file.explode(attachments[])[].file_extensionmemberexe
file.explode(attachments[])[].file_extensionmembervbs

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type eq "rtf"
       macro "any(file.explode(.),\n                .flavors.mime in~ (\n                  \"application/x-dosexec\",\n                  \"text/x-msdos-batch\",\n                  \"application/octet-stream\"\n                )\n                or any(.flavors.yara, . == 'base64_pe')\n                or .file_extension in~ (\"bat\", \"exe\", \"vbs\")\n        )"
  type.inbound eq "true"

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"

Attachment: RTF with link to free-hosted Cloudflare Pages

#

Attachment: Self-sender PDF with minimal content and view prompt

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

Detects messages where the sender and recipient are the same address with a PDF attachment containing only 'VIEW PDF' text and a standardized body message requesting to view the attachment.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesPDF, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • recipients
  • recipients.to[0]
  • sender.email
  • type

Rule Body

type.inbound
// self sender
and length(recipients.to) == 1
and (
  sender.email.email == recipients.to[0].email.email
  or recipients.to[0].email.domain.valid == false
)
and strings.starts_with(body.current_thread.text, 'Please see attached')
and any(filter(attachments, .file_type == 'pdf'),
        any(file.explode(.),
            .scan.strings.strings[0] == 'VIEW PDF'
            and length(.scan.strings.strings) == 1
        )
)

Detection Logic

Scope: inbound message.

Detects messages where the sender and recipient are the same address with a PDF attachment containing only 'VIEW PDF' text and a standardized body message requesting to view the attachment.

  1. inbound message
  2. length(recipients.to) == 1
  3. any of:
    • sender.email.email is recipients.to[0].email.email
    • recipients.to[0].email.domain.valid is False
  4. body.current_thread.text starts with 'Please see attached'
  5. any(filter(attachments, .file_type == 'pdf'), any(file.explode(.), .scan.strings.strings[0] == 'VIEW PDF' and length(.scan.strings.strings) == 1 ) )

Inspects: attachments[].file_type, body.current_thread.text, recipients.to, recipients.to[0].email.domain.valid, recipients.to[0].email.email, sender.email.email, type.inbound. Sensors: file.explode, strings.starts_with.

Indicators Matched (3)

FieldMatchValue
strings.starts_withprefixPlease see attached
attachments[].file_typeequalspdf
file.explode(filter(attachments)[])[].scan.strings.strings[0]equalsVIEW PDF

Stages and Predicates

Stage 1: mql_rule

and
  or
    recipients.to[0].email.domain.valid eq "false"
    sender.email.email cross_field_compare "recipients.to[0].email.email"
  body.current_thread.text starts_with "Please see attached"
  recipients.to length_compare "1"
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == 'pdf'),\n        any(file.explode(.),\n            .scan.strings.strings[0] == 'VIEW PDF'\n            and length(.scan.strings.strings) == 1\n        )\n)"

Indicators

These rows show field, operator, and value matches.

Attachment: SFX archive containing commands

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

Attachment is an SFX archive that contains commands that will execute when opened. This can be used to run malicious commands, and has been observed in the wild.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in~ ("exe", "sfx")
        and any(file.explode(.),
                any(.scan.strings.strings,
                    strings.ilike(.,
                                  'CMT;The comment below contains SFX script commands'
                    )
                )
                and any(.scan.strings.strings, strings.ilike(., 'Setup=*'))
        )
)

Detection Logic

Scope: inbound message.

Attachment is an SFX archive that contains commands that will execute when opened. This can be used to run malicious commands, and has been observed in the wild.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in ('exe', 'sfx')
    • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., 'CMT;The comment below contains SFX script commands' ) ) and any(.scan.strings.strings, strings.ilike(., 'Setup=*')) )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, strings.ilike.

Indicators Matched (4)

FieldMatchValue
attachments[].file_extensionmemberexe
attachments[].file_extensionmembersfx
strings.ilikesubstringCMT;The comment below contains SFX script commands
strings.ilikesubstringSetup=*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension in ["exe", "sfx"]
       macro "any(file.explode(.),\n                any(.scan.strings.strings,\n                    strings.ilike(.,\n                                  'CMT;The comment below contains SFX script commands'\n                    )\n                )\n                and any(.scan.strings.strings, strings.ilike(., 'Setup=*'))\n        )"
  type.inbound eq "true"

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"

Attachment: Single-page PDF with S3-hosted HTML link

#

Attachment: Small text file with link containing recipient email address

#

Attachment: Soda PDF producer with encryption themes

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

Detects an observed TTP of using Soda PDF (which offers a free trial) to produce PDFs which OCR output contains references to encryption and mentions a PDF. The PDF contains a single link which has been observed linking to a credential phishing page.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension == "pdf"
        // observed producer
        and any(file.explode(.), .scan.exiftool.producer == "Soda PDF")
        and any(file.explode(.),
                // OCR contains "encryption" themes
                (
                  strings.icontains(.scan.ocr.raw, "has been encrypted")
                  or strings.icontains(.scan.ocr.raw, "encrypted pdf file")
                  or strings.icontains(.scan.ocr.raw, "is secured by")
                )
                // mentions a PDF 
                and strings.contains(.scan.ocr.raw, "PDF")
        )
)

Detection Logic

Scope: inbound message.

Detects an observed TTP of using Soda PDF (which offers a free trial) to produce PDFs which OCR output contains references to encryption and mentions a PDF. The PDF contains a single link which has been observed linking to a credential phishing page.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any(file.explode(.), .scan.exiftool.producer == "Soda PDF")
    • any(file.explode(.), // OCR contains "encryption" themes ( strings.icontains(.scan.ocr.raw, "has been encrypted") or strings.icontains(.scan.ocr.raw, "encrypted pdf file") or strings.icontains(.scan.ocr.raw, "is secured by") ) // mentions a PDF and strings.contains(.scan.ocr.raw, "PDF") )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode, strings.contains, strings.icontains.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionequalspdf
file.explode(attachments[])[].scan.exiftool.producerequalsSoda PDF
strings.icontainssubstringhas been encrypted
strings.icontainssubstringencrypted pdf file
strings.icontainssubstringis secured by
strings.containssubstringPDF

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension eq "pdf"
       macro "any(file.explode(.), .scan.exiftool.producer == \"Soda PDF\")"
       macro "any(file.explode(.),\n                // OCR contains \"encryption\" themes\n                (\n                  strings.icontains(.scan.ocr.raw, \"has been encrypted\")\n                  or strings.icontains(.scan.ocr.raw, \"encrypted pdf file\")\n                  or strings.icontains(.scan.ocr.raw, \"is secured by\")\n                )\n                // mentions a PDF \n                and strings.contains(.scan.ocr.raw, \"PDF\")\n        )"
  type.inbound eq "true"

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"

Attachment: Suspicious employee policy update document lure

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

Inbound message containing subject line and attachments related to handbook, compensation, or policy updates. Attachments are limited to Microsoft Word documents and match similar update-related terminology. This pattern has been observed used to delivery credential phishing via QR codes.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Social engineering, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
// NOTE: This rule is designed for these values to match/sync subject.base and file names
and (
  // the subject contains pay related items
  (
    strings.icontains(subject.base, 'salary')
    or regex.icontains(subject.base, '\bpay(?:out|roll|\b)')
    or strings.icontains(subject.base, 'remuneration')
    or strings.icontains(subject.base, 'bonus')
    or strings.icontains(subject.base, 'incentive')
    or strings.icontains(subject.base, 'merit\b')
    or strings.icontains(subject.base, 'handbook')
    or strings.icontains(subject.base, 'benefits')
    or strings.icontains(subject.base, 'earnings')
    or strings.icontains(subject.base, 'contract')
    or regex.icontains(subject.base, 'empl[o0]yment')
  )
  and (
    strings.icontains(subject.base, 'review')
    or strings.icontains(subject.base, 'breakdown')
    or strings.icontains(subject.base, 'Access Your')
    or strings.icontains(subject.base, 'evaluation')
    or regex.icontains(subject.base, 'eval\b')
    or strings.icontains(subject.base, 'assessment')
    or strings.icontains(subject.base, 'appraisal')
    or strings.icontains(subject.base, 'feedback')
    or strings.icontains(subject.base, 'performance')
    or strings.icontains(subject.base, 'adjustment')
    or strings.icontains(subject.base, 'qualification')
    or strings.icontains(subject.base, 'increase')
    or strings.icontains(subject.base, 'raise')
    or strings.icontains(subject.base, 'change')
    or strings.icontains(subject.base, 'modification')
    or strings.icontains(subject.base, 'distribution')
    or strings.icontains(subject.base, 'details')
    or regex.icontains(subject.base, 'revis(?:ed|ion)')
    or regex.icontains(subject.base, 'amend(?:ed|ment)')
    or regex.icontains(subject.base, 'update(?:d| to)')
    or strings.icontains(subject.base, 'plan')
    or strings.icontains(subject.base, 'notification')
  )
)
and 0 < length(attachments) <= 3
and any(attachments,
        .file_extension in ("doc", "docx", "docm", "pdf", "pptx")
        and (
          strings.icontains(.file_name, 'salary')
          or strings.icontains(.file_name, 'compensation')
          or regex.icontains(.file_name, '\bpay(?:roll|\b)')
          or strings.icontains(.file_name, 'bonus')
          or strings.icontains(.file_name, 'incentive')
          or strings.icontains(.file_name, 'merit\b')
          or strings.icontains(.file_name, 'handbook')
          or strings.icontains(.file_name, 'benefits')
          or regex.icontains(.file_name, 'empl[o0]yment')
        )
        and (
          strings.icontains(.file_name, 'review')
          or strings.icontains(.file_name, 'evaluation')
          or regex.icontains(.file_name, 'eval\b')
          or strings.icontains(.file_name, 'assessment')
          or strings.icontains(.file_name, 'appraisal')
          or strings.icontains(.file_name, 'feedback')
          or strings.icontains(.file_name, 'performance')
          or strings.icontains(.file_name, 'adjustment')
          or strings.icontains(.file_name, 'increase')
          or strings.icontains(.file_name, 'increment')
          or strings.icontains(.file_name, 'raise')
          or strings.icontains(.file_name, 'change')
          or strings.icontains(.file_name, 'modification')
          or strings.icontains(.file_name, 'distribution')
          or strings.icontains(.file_name, 'statement')
          or regex.icontains(.file_name, 'revis(?:ed|ion)')
          or regex.icontains(.file_name, 'amend(?:ed|ment)')
          or regex.icontains(.file_name, 'adjust(?:ed|ment)')
          or regex.icontains(.file_name, 'update(?:d| to)')
          or regex.icontains(.file_name,
                             '(January|February|March|April|May|June|July|August|September|October|November|December)\s20[2,3]{1}\d{1}'
          )
          or strings.icontains(.file_name, 'contract')
          or (
            // file name contains recipient's email
            any(recipients.to,
                strings.icontains(..file_name, .email.email)
                and .email.domain.valid
            )
          )
        )
)
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.

Inbound message containing subject line and attachments related to handbook, compensation, or policy updates. Attachments are limited to Microsoft Word documents and match similar update-related terminology. This pattern has been observed used to delivery credential phishing via QR codes.

  1. inbound message
  2. all of:
    • any of:
      • subject.base contains 'salary'
      • subject.base matches '\\bpay(?:out|roll|\\b)'
      • subject.base contains 'remuneration'
      • subject.base contains 'bonus'
      • subject.base contains 'incentive'
      • subject.base contains 'merit\\b'
      • subject.base contains 'handbook'
      • subject.base contains 'benefits'
      • subject.base contains 'earnings'
      • subject.base contains 'contract'
      • subject.base matches 'empl[o0]yment'
    • any of:
      • subject.base contains 'review'
      • subject.base contains 'breakdown'
      • subject.base contains 'Access Your'
      • subject.base contains 'evaluation'
      • subject.base matches 'eval\\b'
      • subject.base contains 'assessment'
      • subject.base contains 'appraisal'
      • subject.base contains 'feedback'
      • subject.base contains 'performance'
      • subject.base contains 'adjustment'
      • subject.base contains 'qualification'
      • subject.base contains 'increase'
      • subject.base contains 'raise'
      • subject.base contains 'change'
      • subject.base contains 'modification'
      • subject.base contains 'distribution'
      • subject.base contains 'details'
      • subject.base matches 'revis(?:ed|ion)'
      • subject.base matches 'amend(?:ed|ment)'
      • subject.base matches 'update(?:d| to)'
      • subject.base contains 'plan'
      • subject.base contains 'notification'
  3. all of:
    • (0) < (length(attachments))
    • (length(attachments)) <= (3)
  4. any of attachments where all hold:
    • .file_extension in ('doc', 'docx', 'docm', 'pdf', 'pptx')
    • any of:
      • .file_name contains 'salary'
      • .file_name contains 'compensation'
      • .file_name matches '\\bpay(?:roll|\\b)'
      • .file_name contains 'bonus'
      • .file_name contains 'incentive'
      • .file_name contains 'merit\\b'
      • .file_name contains 'handbook'
      • .file_name contains 'benefits'
      • .file_name matches 'empl[o0]yment'
    • any of:
      • .file_name contains 'review'
      • .file_name contains 'evaluation'
      • .file_name matches 'eval\\b'
      • .file_name contains 'assessment'
      • .file_name contains 'appraisal'
      • .file_name contains 'feedback'
      • .file_name contains 'performance'
      • .file_name contains 'adjustment'
      • .file_name contains 'increase'
      • .file_name contains 'increment'
      • .file_name contains 'raise'
      • .file_name contains 'change'
      • .file_name contains 'modification'
      • .file_name contains 'distribution'
      • .file_name contains 'statement'
      • .file_name matches 'revis(?:ed|ion)'
      • .file_name matches 'amend(?:ed|ment)'
      • .file_name matches 'adjust(?:ed|ment)'
      • .file_name matches 'update(?:d| to)'
      • .file_name matches '(January|February|March|April|May|June|July|August|September|October|November|December)\\s20[2,3]{1}\\d{1}'
      • .file_name contains 'contract'
      • any of recipients.to where all hold:
        • strings.icontains(..file_name, .email.email)
        • .email.domain.valid
  5. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass, false)

Inspects: attachments[].file_extension, attachments[].file_name, headers.auth_summary.dmarc.pass, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, sender.email.domain.root_domain, subject.base, type.inbound. Sensors: regex.icontains, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (44)

FieldMatchValue
strings.icontainssubstringsalary
regex.icontainsregex\bpay(?:out|roll|\b)
strings.icontainssubstringremuneration
strings.icontainssubstringbonus
strings.icontainssubstringincentive
strings.icontainssubstringmerit\b
strings.icontainssubstringhandbook
strings.icontainssubstringbenefits
strings.icontainssubstringearnings
strings.icontainssubstringcontract
regex.icontainsregexempl[o0]yment
strings.icontainssubstringreview
32 more
strings.icontainssubstringbreakdown
strings.icontainssubstringAccess Your
strings.icontainssubstringevaluation
regex.icontainsregexeval\b
strings.icontainssubstringassessment
strings.icontainssubstringappraisal
strings.icontainssubstringfeedback
strings.icontainssubstringperformance
strings.icontainssubstringadjustment
strings.icontainssubstringqualification
strings.icontainssubstringincrease
strings.icontainssubstringraise
strings.icontainssubstringchange
strings.icontainssubstringmodification
strings.icontainssubstringdistribution
strings.icontainssubstringdetails
regex.icontainsregexrevis(?:ed|ion)
regex.icontainsregexamend(?:ed|ment)
regex.icontainsregexupdate(?:d| to)
strings.icontainssubstringplan
strings.icontainssubstringnotification
attachments[].file_extensionmemberdoc
attachments[].file_extensionmemberdocx
attachments[].file_extensionmemberdocm
attachments[].file_extensionmemberpdf
attachments[].file_extensionmemberpptx
strings.icontainssubstringcompensation
regex.icontainsregex\bpay(?:roll|\b)
strings.icontainssubstringincrement
strings.icontainssubstringstatement
regex.icontainsregexadjust(?:ed|ment)
regex.icontainsregex(January|February|March|April|May|June|July|August|September|October|November|December)\s20[2,3]{1}\d{1}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        any(recipients.to)
          and
            recipients.to.email.domain.valid eq "true"
            strings.icontains func_call "strings.icontains(..file_name, .email.email)"
        attachments.file_name contains "adjustment"
        attachments.file_name contains "appraisal"
        attachments.file_name contains "assessment"
        attachments.file_name contains "change"
        attachments.file_name contains "contract"
        attachments.file_name contains "distribution"
        attachments.file_name contains "evaluation"
        attachments.file_name contains "feedback"
        attachments.file_name contains "increase"
        attachments.file_name contains "increment"
        attachments.file_name contains "modification"
        attachments.file_name contains "performance"
        attachments.file_name contains "raise"
        attachments.file_name contains "review"
        attachments.file_name contains "statement"
        attachments.file_name regex_match "(January|February|March|April|May|June|July|August|September|October|November|December)\\s20[2,3]{1}\\d{1}"
        attachments.file_name regex_match "adjust(?:ed|ment)"
        attachments.file_name regex_match "amend(?:ed|ment)"
        attachments.file_name regex_match "eval\\b"
        attachments.file_name regex_match "revis(?:ed|ion)"
        attachments.file_name regex_match "update(?:d| to)"
      or
        attachments.file_name contains "benefits"
        attachments.file_name contains "bonus"
        attachments.file_name contains "compensation"
        attachments.file_name contains "handbook"
        attachments.file_name contains "incentive"
        attachments.file_name contains "merit\\b"
        attachments.file_name contains "salary"
        attachments.file_name regex_match "\\bpay(?:roll|\\b)"
        attachments.file_name regex_match "empl[o0]yment"
      attachments.file_extension in ["doc", "docm", "docx", "pdf", "pptx"]
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  or
    subject.base contains "Access Your"
    subject.base contains "adjustment"
    subject.base contains "appraisal"
    subject.base contains "assessment"
    subject.base contains "breakdown"
    subject.base contains "change"
    subject.base contains "details"
    subject.base contains "distribution"
    subject.base contains "evaluation"
    subject.base contains "feedback"
    subject.base contains "increase"
    subject.base contains "modification"
    subject.base contains "notification"
    subject.base contains "performance"
    subject.base contains "plan"
    subject.base contains "qualification"
    subject.base contains "raise"
    subject.base contains "review"
    subject.base regex_match "amend(?:ed|ment)"
    subject.base regex_match "eval\\b"
    subject.base regex_match "revis(?:ed|ion)"
    subject.base regex_match "update(?:d| to)"
  or
    subject.base contains "benefits"
    subject.base contains "bonus"
    subject.base contains "contract"
    subject.base contains "earnings"
    subject.base contains "handbook"
    subject.base contains "incentive"
    subject.base contains "merit\\b"
    subject.base contains "remuneration"
    subject.base contains "salary"
    subject.base regex_match "\\bpay(?:out|roll|\\b)"
    subject.base regex_match "empl[o0]yment"
  attachments length_compare "0"
  attachments length_compare "3"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
subject.basecontains
  • Access Your
  • adjustment
  • appraisal
  • assessment
  • benefits
  • bonus
  • breakdown
  • change
  • contract
  • details
  • distribution
  • earnings
  • evaluation
  • feedback
  • handbook
  • incentive
  • increase
  • merit\b
  • modification
  • notification
  • performance
  • plan
  • qualification
  • raise
  • remuneration
  • review
  • salary
field:"subject.base" kind:contains
subject.baseregex_match
  • \bpay(?:out|roll|\b)
  • amend(?:ed|ment)
  • empl[o0]yment
  • eval\b
  • revis(?:ed|ion)
  • update(?:d| to)
field:"subject.base" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.dmarc.passis_not_null(no value, null check)excludes:headers.auth_summary.dmarc.pass

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

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

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
                     // exclude sources of potential FPs
                     and .domain.root_domain not in ("atlassian.net")
              )
          )
        )
      )
      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(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 // exclude sources of potential FPs and .domain.root_domain not in ("atlassian.net") ) ) ) ) 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 ') ) ) )
    • 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 ') ) ) ) )

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

Stages and Predicates

Stage 1: mql_rule

and
  or
     macro "any(filter(attachments, .file_type == \"pdf\"),\n      (\n        // table of contents detection\n        (\n          any(file.explode(.),\n              strings.contains(.scan.ocr.raw, 'TABLE OF CONTEN')\n          )\n          // the Table of contents can be on another page\n          and any(file.explode(.),\n                  regex.icontains(.scan.ocr.raw,\n                                  '(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction'\n                  )\n                  or strings.icontains(.scan.ocr.raw, 'marked in red')\n          )\n        )\n        or (\n          any(file.explode(.),\n              any(.scan.strings.strings,\n                  // heading of sections within observed documents\n                  any([\n                        'Employee Acknowledgement',\n                        'Document Summary',\n                        'appraisal overview',\n                        'accessing full appraisal',\n                      ],\n                      .. =~ .\n                  )\n              )\n              // or links to free subdomain host\n              or any(.scan.url.urls,\n                     .domain.root_domain in $free_subdomain_hosts\n                     and .domain.subdomain is not null\n                     // exclude sources of potential FPs\n                     and .domain.root_domain not in (\"atlassian.net\")\n              )\n          )\n        )\n      )\n      and (\n        (\n          (\n            strings.icontains(beta.parse_exif(.).creator, 'HeadlessChrome')\n            or strings.icontains(beta.parse_exif(.).creator, 'Chromium')\n          )\n          and strings.icontains(beta.parse_exif(.).producer, 'Skia/PDF')\n        )\n        or (\n          any(beta.parse_exif(.).fields,\n              .key == \"Creator\"\n              and (.value == \"\" or strings.istarts_with(.value, 'wkhtmltopdf'))\n          )\n          and any(beta.parse_exif(.).fields,\n                  .key == \"Title\"\n                  and (\n                    .value == \"\"\n                    // company handbook\n                    or .value in ('Company HandBook')\n                    // appraisal themes\n                    or strings.icontains(.value,\n                                         'Employee Performance Appraisal'\n                    )\n                  )\n          )\n          and strings.istarts_with(beta.parse_exif(.).producer, 'QT ')\n        )\n      )\n  )"
     macro "any(filter(attachments,\n                .content_type == \"message/rfc822\" or .file_extension == \"eml\"\n         ),\n         any(filter(file.parse_eml(.).attachments, .file_type == \"pdf\"),\n             (\n               // table of contents detection\n               (\n                 any(file.explode(.),\n                     strings.contains(.scan.ocr.raw, 'TABLE OF CONTEN')\n                 )\n                 // the Table of contents can be on another page\n                 and any(file.explode(.),\n                         regex.icontains(.scan.ocr.raw,\n                                         '(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction'\n                         )\n                         or strings.icontains(.scan.ocr.raw, 'marked in red')\n                 )\n               )\n               or (\n                 any(file.explode(.),\n                     any(.scan.strings.strings,\n                         // heading of sections within observed documents\n                         any([\n                               'Employee Acknowledgement',\n                               'Document Summary',\n                               'appraisal overview',\n                               'accessing full appraisal',\n                             ],\n                             .. =~ .\n                         )\n                     )\n                     // or links to free subdomain host\n                     or any(.scan.url.urls,\n                            .domain.root_domain in $free_subdomain_hosts\n                            and .domain.subdomain is not null\n                     )\n                 )\n               )\n             )\n             and (\n               (\n                 (\n                   strings.icontains(beta.parse_exif(.).creator,\n                                     'HeadlessChrome'\n                   )\n                   or strings.icontains(beta.parse_exif(.).creator, 'Chromium')\n                 )\n                 and strings.icontains(beta.parse_exif(.).producer, 'Skia/PDF')\n               )\n               or (\n                 any(beta.parse_exif(.).fields,\n                     .key == \"Creator\"\n                     and (\n                       .value == \"\"\n                       or strings.istarts_with(.value, 'wkhtmltopdf')\n                     )\n                 )\n                 and any(beta.parse_exif(.).fields,\n                         .key == \"Title\"\n                         and (\n                           .value == \"\"\n                           // company handbook\n                           or .value in ('Company HandBook')\n                           // appraisal themes\n                           or strings.icontains(.value,\n                                                'Employee Performance Appraisal'\n                           )\n                         )\n                 )\n                 and strings.istarts_with(beta.parse_exif(.).producer, 'QT ')\n               )\n             )\n         )\n  )"
  type.inbound eq "true"

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"

Attachment: SVG file execution

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

Detects file execution attempts in SVG files. ActiveXObject is used to invoke WScript.Shell and run a program.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesScripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension =~ "svg"
          or .file_extension in $file_extensions_common_archives
          or .file_type == "svg"
        )
        and any(file.explode(.),
                .file_extension == "svg"
                // Author Matt harr0ey @harr0ey
                // Topic: SVG file Execution
                // WScript inside SVG
                // <script language="JScript">
                // <![CDATA[
                // var r = new ActiveXObject("WScript.Shell").Run("calc.exe")
                // ]]>
                // </script>
                and any(.scan.strings.strings,
                        strings.icontains(., "ActiveXObject")
                )
                and any(.scan.strings.strings,
                        strings.icontains(., "WScript.Shell")
                )
                and any(.scan.strings.strings,
                        strings.like(., "*Run*", "*Execute*")
                )
        )
)

Detection Logic

Scope: inbound message.

Detects file execution attempts in SVG files. ActiveXObject is used to invoke WScript.Shell and run a program.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'svg'
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'svg'
    • any(file.explode(.), .file_extension == "svg" // Author Matt harr0ey @harr0ey // Topic: SVG file Execution // WScript inside SVG // <script language="JScript"> // <![CDATA[ // var r = new ActiveXObject("WScript.Shell").Run("calc.exe") // ]]> // </script> and any(.scan.strings.strings, strings.icontains(., "ActiveXObject") ) and any(.scan.strings.strings, strings.icontains(., "WScript.Shell") ) and any(.scan.strings.strings, strings.like(., "*Run*", "*Execute*") ) )

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, strings.icontains, strings.like. Reference lists: $file_extensions_common_archives.

Indicators Matched (7)

FieldMatchValue
attachments[].file_extensionequalssvg
attachments[].file_typeequalssvg
file.explode(attachments[])[].file_extensionequalssvg
strings.icontainssubstringActiveXObject
strings.icontainssubstringWScript.Shell
strings.likesubstring*Run*
strings.likesubstring*Execute*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_extension eq "svg"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
        attachments.file_type eq "svg"
       macro "any(file.explode(.),\n                .file_extension == \"svg\"\n                // Author Matt harr0ey @harr0ey\n                // Topic: SVG file Execution\n                // WScript inside SVG\n                // <script language=\"JScript\">\n                // <![CDATA[\n                // var r = new ActiveXObject(\"WScript.Shell\").Run(\"calc.exe\")\n                // ]]>\n                // </script>\n                and any(.scan.strings.strings,\n                        strings.icontains(., \"ActiveXObject\")\n                )\n                and any(.scan.strings.strings,\n                        strings.icontains(., \"WScript.Shell\")\n                )\n                and any(.scan.strings.strings,\n                        strings.like(., \"*Run*\", \"*Execute*\")\n                )\n        )"
  type.inbound eq "true"

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"

Attachment: SVG file with HTML entity encoded href attributes

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

Detects SVG file attachments containing href attributes with three or more consecutive HTML numeric entity references, a technique used to obfuscate malicious URLs and evade security scanning.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesEvasion, HTML smuggling

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension == "svg"
          or .content_type in ("image/svg+xml")
          or .file_type == "svg"
        )
        // href value starting with 3+ HTML numeric entity references
        and regex.icontains(file.parse_text(.,
                                            encodings=[
                                              "ascii",
                                              "utf8",
                                              "utf16-le"
                                            ]
                            ).text,
                            'href\s*=\s*["\x27]\s*(?:&#x?[0-9a-f]+;\s*){3,}'
        )
)

Detection Logic

Scope: inbound message.

Detects SVG file attachments containing href attributes with three or more consecutive HTML numeric entity references, a technique used to obfuscate malicious URLs and evade security scanning.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'svg'
      • .content_type in ('image/svg+xml')
      • .file_type is 'svg'
    • regex.icontains(file.parse_text(., encodings=[ "ascii", "utf8", "utf16-le" ] ).text, 'href\s*=\s*["\x27]\s*(?:&#x?[0-9a-f]+;\s*){3,}' )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.parse_text, regex.icontains.

Indicators Matched (4)

FieldMatchValue
attachments[].file_extensionequalssvg
attachments[].content_typememberimage/svg+xml
attachments[].file_typeequalssvg
regex.icontainsregexhref\s*=\s*["\x27]\s*(?:&#x?[0-9a-f]+;\s*){3,}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "image/svg+xml"
        attachments.file_extension eq "svg"
        attachments.file_type eq "svg"
      regex.icontains func_call "regex.icontains(file.parse_text(.,\n                                            encodings=[\n                                              \"ascii\",\n                                              \"utf8\",\n                                              \"utf16-le\"\n                                            ]\n                            ).text,\n                            'href\\s*=\\s*[\"\\x27]\\s*(?:&#x?[0-9a-f]+;\\s*){3,}'\n        )"
  type.inbound eq "true"

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"

Attachment: SVG file with hyperlinks and cursor styling

#

Attachment: SVG files with evasion elements

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

This rule identifies incoming SVG vector graphics files containing specific patterns: circle elements combined with either embedded images, hyperlinks, QR codes, or filenames that match recipient information. Limited to three attachments. SVG circle elements have been used to obfuscate QR codes and bypass automated QR code scanning methods.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesQR code, Image as content, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule Body

type.inbound
and length(attachments) < 4
and any(attachments,
        (
          .file_extension == "svg"
          or .content_type in ("image/svg+xml")
          or .file_type == "svg"
        )
        and any(file.explode(.),
                any(.scan.xml.tags, . == "circle")
                and 1 of (
                  any(.scan.xml.tags, . in ("image", "a")),
                  .scan.qr.data is not null,
                  any(recipients.to,
                      strings.icontains(..file_name, .email.local_part)
                  ),
                  any(recipients.to,
                      strings.icontains(..file_name, .email.domain.sld)
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

This rule identifies incoming SVG vector graphics files containing specific patterns: circle elements combined with either embedded images, hyperlinks, QR codes, or filenames that match recipient information. Limited to three attachments. SVG circle elements have been used to obfuscate QR codes and bypass automated QR code scanning methods.

  1. inbound message
  2. length(attachments) < 4
  3. any of attachments where all hold:
    • any of:
      • .file_extension is 'svg'
      • .content_type in ('image/svg+xml')
      • .file_type is 'svg'
    • any(file.explode(.), any(.scan.xml.tags, . == "circle") and 1 of ( any(.scan.xml.tags, . in ("image", "a")), .scan.qr.data is not null, any(recipients.to, strings.icontains(..file_name, .email.local_part) ), any(recipients.to, strings.icontains(..file_name, .email.domain.sld) ) ) )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, recipients.to, recipients.to[].email.domain.sld, recipients.to[].email.local_part, type.inbound. Sensors: file.explode, strings.icontains.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionequalssvg
attachments[].content_typememberimage/svg+xml
attachments[].file_typeequalssvg
file.explode(attachments[])[].scan.xml.tags[]equalscircle
file.explode(attachments[])[].scan.xml.tags[]memberimage
file.explode(attachments[])[].scan.xml.tags[]membera

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "image/svg+xml"
        attachments.file_extension eq "svg"
        attachments.file_type eq "svg"
       macro "any(file.explode(.),\n                any(.scan.xml.tags, . == \"circle\")\n                and 1 of (\n                  any(.scan.xml.tags, . in (\"image\", \"a\")),\n                  .scan.qr.data is not null,\n                  any(recipients.to,\n                      strings.icontains(..file_name, .email.local_part)\n                  ),\n                  any(recipients.to,\n                      strings.icontains(..file_name, .email.domain.sld)\n                  )\n                )\n        )"
  attachments length_compare "4"
  type.inbound eq "true"

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"

Attachment: TAR file with RAR type

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

Detects messages with TAR file extensions that are actually RAR file types. This mismatch between file extension and actual file type may indicate an evasion technique.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments, .file_extension =~ "tar" and .file_type =~ "rar")

Detection Logic

Scope: inbound message.

Detects messages with TAR file extensions that are actually RAR file types. This mismatch between file extension and actual file type may indicate an evasion technique.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension is 'tar'
    • .file_type is 'rar'

Inspects: attachments[].file_extension, attachments[].file_type, type.inbound.

Indicators Matched (2)

FieldMatchValue
attachments[].file_extensionequalstar
attachments[].file_typeequalsrar

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension eq "tar"
      attachments.file_type eq "rar"
  type.inbound eq "true"

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"

Attachment: Targeted DOCX with personalized recipient acknowledgement lure

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

Detects inbound messages with a DOCX attachment containing a quarterly date reference, specific STATUS and ACKNOWLEDGEMENT formatting patterns, and a personalized salutation where the recipient's name or local email part is dynamically embedded in the document XML.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesSocial engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "docx"),
        any(filter(file.explode(.), .file_name == "word/document.xml"),
            // doc xml has a QX 2026 type date
            regex.contains(.scan.strings.raw, '<w:t>Q[1-4]\S202[5-9]<\/w:t>')
            // and a couple of the terms we've seen in the document with specific spacing reqs
            and strings.contains(.scan.strings.raw,
                                 '<w:t xml:space="preserve">STATUS </w:t>'
            )
            and strings.contains(.scan.strings.raw,
                                 '<w:t xml:space="preserve">ACKNOWLEDGEMENT </w:t>'
            )
            // and doc xml has some reference to the user's name in there too?
            and any(regex.extract(.scan.strings.raw,
                                  '<w:t xml:space="preserve">Dear </w:t></w:r><w:r><w:rPr><w:b /><w:bCs /><w:color w:val="[a-f0-9]{6}" /><w:sz w:val="[0-9]{1,3}" /><w:szCs w:val="[0-9]{1,3}" /></w:rPr><w:t>(?P<name>.*?)</w:t></w:r>'
                    ),
                    any(recipients.to,
                        (
                          ..named_groups["name"] =~ .email.local_part
                          or ..named_groups["name"] =~ .display_name
                        )
                    )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages with a DOCX attachment containing a quarterly date reference, specific STATUS and ACKNOWLEDGEMENT formatting patterns, and a personalized salutation where the recipient's name or local email part is dynamically embedded in the document XML.

  1. inbound message
  2. any(filter(attachments, .file_type == "docx"), any(filter(file.explode(.), .file_name == "word/document.xml"), // doc xml has a QX 2026 type date regex.contains(.scan.strings.raw, '<w:t>Q[1-4]\S202[5-9]<\/w:t>') // and a couple of the terms we've seen in the document with specific spacing reqs and strings.contains(.scan.strings.raw, '<w:t xml:space="preserve">STATUS </w:t>' ) and strings.contains(.scan.strings.raw, '<w:t xml:space="preserve">ACKNOWLEDGEMENT </w:t>' ) // and doc xml has some reference to the user's name in there too? and any(regex.extract(.scan.strings.raw, '<w:t xml:space="preserve">Dear </w:t></w:r><w:r><w:rPr><w:b /><w:bCs /><w:color w:val="[a-f0-9]{6}" /><w:sz w:val="[0-9]{1,3}" /><w:szCs w:val="[0-9]{1,3}" /></w:rPr><w:t>(?P<name>.*?)</w:t></w:r>' ), any(recipients.to, ( ..named_groups["name"] =~ .email.local_part or ..named_groups["name"] =~ .display_name ) ) ) ) )

Inspects: attachments[].file_type, recipients.to, recipients.to[].display_name, recipients.to[].email.local_part, type.inbound. Sensors: file.explode, regex.contains, regex.extract, strings.contains.

Indicators Matched (6)

FieldMatchValue
attachments[].file_typeequalsdocx
file.explode(filter(attachments)[])[].file_nameequalsword/document.xml
regex.containsregex<w:t>Q[1-4]\S202[5-9]<\/w:t>
strings.containssubstring<w:t xml:space="preserve">STATUS </w:t>
strings.containssubstring<w:t xml:space="preserve">ACKNOWLEDGEMENT </w:t>
regex.extractregex<w:t xml:space="preserve">Dear </w:t></w:r><w:r><w:rPr><w:b /><w:bCs /><w:color w:val="[a-f0-9]{6}" /><w:sz w:val="[0-9]{1,3}" /><w:szCs w:val="[0-9]{1,3}" /></w:rPr><w:t>(?P<name>.*?)</w:t></w:r>

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"docx\"),\n        any(filter(file.explode(.), .file_name == \"word/document.xml\"),\n            // doc xml has a QX 2026 type date\n            regex.contains(.scan.strings.raw, '<w:t>Q[1-4]\\S202[5-9]<\\/w:t>')\n            // and a couple of the terms we've seen in the document with specific spacing reqs\n            and strings.contains(.scan.strings.raw,\n                                 '<w:t xml:space=\"preserve\">STATUS </w:t>'\n            )\n            and strings.contains(.scan.strings.raw,\n                                 '<w:t xml:space=\"preserve\">ACKNOWLEDGEMENT </w:t>'\n            )\n            // and doc xml has some reference to the user's name in there too?\n            and any(regex.extract(.scan.strings.raw,\n                                  '<w:t xml:space=\"preserve\">Dear </w:t></w:r><w:r><w:rPr><w:b /><w:bCs /><w:color w:val=\"[a-f0-9]{6}\" /><w:sz w:val=\"[0-9]{1,3}\" /><w:szCs w:val=\"[0-9]{1,3}\" /></w:rPr><w:t>(?P<name>.*?)</w:t></w:r>'\n                    ),\n                    any(recipients.to,\n                        (\n                          ..named_groups[\"name\"] =~ .email.local_part\n                          or ..named_groups[\"name\"] =~ .display_name\n                        )\n                    )\n            )\n        )\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"

Attachment: Uncommon compressed file

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

Use if passing compressed or archive files is not typical behavior in your organization. This behavior has been observed in a number of phishing campaigns.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in ('tar', 'iso', 'img', 'cab', 'gadget', 'uue')
)

Detection Logic

Scope: inbound message.

Use if passing compressed or archive files is not typical behavior in your organization. This behavior has been observed in a number of phishing campaigns.

  1. inbound message
  2. any of attachments where:
    • .file_extension in ('tar', 'iso', 'img', 'cab', 'gadget', 'uue')

Inspects: attachments[].file_extension, type.inbound.

Indicators Matched (6)

FieldMatchValue
attachments[].file_extensionmembertar
attachments[].file_extensionmemberiso
attachments[].file_extensionmemberimg
attachments[].file_extensionmembercab
attachments[].file_extensionmembergadget
attachments[].file_extensionmemberuue

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    attachments.file_extension in ["cab", "gadget", "img", "iso", "tar", "uue"]
  type.inbound eq "true"

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"

Attachment: USDA bid invitation impersonation

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

Detects messages claiming to be from USDA containing bid invitations with macro-enabled attachments or PDFs. Validates USDA-related content through OCR and natural language analysis.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesImpersonation: Brand, PDF, Macros, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and length(attachments) == 1
and all(attachments,
        (.file_extension in~ $file_extensions_macros or .file_type == "pdf")
        and any(file.explode(.),
                any(ml.nlu_classifier(.scan.ocr.raw).entities,
                    strings.icontains(.text, "Agriculture")
                )
        )
)
and strings.icontains(body.current_thread.text, "bid")
and (
  strings.icontains(subject.subject, 'invitation to bid')
  or any(attachments, strings.icontains(.file_name, 'usda'))
)
and strings.icontains(sender.email.domain.domain, "usda")
and any(ml.nlu_classifier(body.current_thread.text).entities,
        .text == "usda" and .name in ("sender", "org")
)

Detection Logic

Scope: inbound message.

Detects messages claiming to be from USDA containing bid invitations with macro-enabled attachments or PDFs. Validates USDA-related content through OCR and natural language analysis.

  1. inbound message
  2. length(attachments) == 1
  3. all of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_type is 'pdf'
    • any(file.explode(.), any(ml.nlu_classifier(.scan.ocr.raw).entities, strings.icontains(.text, "Agriculture") ) )
  4. body.current_thread.text contains 'bid'
  5. any of:
    • subject.subject contains 'invitation to bid'
    • any of attachments where:
      • .file_name contains 'usda'
  6. sender.email.domain.domain contains 'usda'
  7. any(ml.nlu_classifier(body.current_thread.text).entities, .text == "usda" and .name in ("sender", "org") )

Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, body.current_thread.text, sender.email.domain.domain, subject.subject, type.inbound. Sensors: file.explode, ml.nlu_classifier, strings.icontains. Reference lists: $file_extensions_macros.

Indicators Matched (8)

FieldMatchValue
attachments[].file_typeequalspdf
strings.icontainssubstringAgriculture
strings.icontainssubstringbid
strings.icontainssubstringinvitation to bid
strings.icontainssubstringusda
ml.nlu_classifier(body.current_thread.text).entities[].textequalsusda
ml.nlu_classifier(body.current_thread.text).entities[].namemembersender
ml.nlu_classifier(body.current_thread.text).entities[].namememberorg

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      attachments.file_name contains "usda"
    subject.subject contains "invitation to bid"
  attachments length_compare "1"
  body.current_thread.text contains "bid"
  sender.email.domain.domain contains "usda"
  type.inbound eq "true"
   macro "all(attachments,\n        (.file_extension in~ $file_extensions_macros or .file_type == \"pdf\")\n        and any(file.explode(.),\n                any(ml.nlu_classifier(.scan.ocr.raw).entities,\n                    strings.icontains(.text, \"Agriculture\")\n                )\n        )\n)"
   macro "any(ml.nlu_classifier(body.current_thread.text).entities,\n        .text == \"usda\" and .name in (\"sender\", \"org\")\n)"

Indicators

These rows show field, operator, and value matches.

Attachment: Web files with suspicious comments

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

Detects HTML or SVG files under 100KB that contain duplicate or padding text in the form of literary quotes or common sayings within code comments.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesHTML smuggling, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          (
            .file_type in ("html", "svg")
            or .file_extension in ("html", "xhtml", "mhtml", "svg")
            or .content_type in ("text/html", "text/plain")
          )
          and .size < 100000
        )
        and (
          (
            // targeting comments that pad the file with quotes from literature
            // examples: "// Echoes of the past linger in silence.", "// The wind whispered secrets unknown.", "// Shadows tell stories in the dark."

            // count all HTML code comments that match our pattern
            regex.count(file.parse_text(.).text, '// [A-Z][ a-z ]+\.') / 
            // divide by the count of all UNIQUE HTML code comments that match our pattern
            length(distinct(regex.extract(file.parse_text(.).text,
                                          '// [A-Z][ a-z ]+\.'
                            ),
                            .full_match
                   )
            ) 
            // at least 50% of the comments are duplicates
            >= 2
          )
          or (
            // targeting comments that pad the file with sayings
            // examples: "<!-- <span> No gain without pain. </span> -->", "<!-- <p> Beauty is only skin deep. </p> -->", "<!-- <span> Actions speak louder than words. </span> -->"
            regex.count(file.parse_text(.).text,
                        '<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\. (</[a-z]+>)? +-->'
            )
          ) > 2
          or (
            // targeting comments inside hidden HTML elements
            // example: "<h1 style="display:none;"> Self-confidence inspires others to believe in you. </h1>"
            regex.count(file.parse_text(.).text,
                        '<[a-z0-9]+ style="display:none;">(<[a-z]+>)? [A-Z].*\. </[a-z0-9]+>'
            )
          ) > 2
        )
)

Detection Logic

Scope: inbound message.

Detects HTML or SVG files under 100KB that contain duplicate or padding text in the form of literary quotes or common sayings within code comments.

  1. inbound message
  2. any of attachments where all hold:
    • all of:
      • any of:
        • .file_type in ('html', 'svg')
        • .file_extension in ('html', 'xhtml', 'mhtml', 'svg')
        • .content_type in ('text/html', 'text/plain')
      • .size < 100000
    • any of:
      • ( // targeting comments that pad the file with quotes from literature // examples: "// Echoes of the past linger in silence.", "// The wind whispered secrets unknown.", "// Shadows tell stories in the dark." // count all HTML code comments that match our pattern regex.count(file.parse_text(.).text, '// [A-Z][ a-z ]+\.') / // divide by the count of all UNIQUE HTML code comments that match our pattern length(distinct(regex.extract(file.parse_text(.).text, '// [A-Z][ a-z ]+\.' ), .full_match ) ) // at least 50% of the comments are duplicates >= 2 )
      • ( // targeting comments that pad the file with sayings // examples: "<!-- <span> No gain without pain. </span> -->", "<!-- <p> Beauty is only skin deep. </p> -->", "<!-- <span> Actions speak louder than words. </span> -->" regex.count(file.parse_text(.).text, '<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\. (</[a-z]+>)? +-->' ) ) > 2
      • ( // targeting comments inside hidden HTML elements // example: "<h1 style="display:none;"> Self-confidence inspires others to believe in you. </h1>" regex.count(file.parse_text(.).text, '<[a-z0-9]+ style="display:none;">(<[a-z]+>)? [A-Z].*\. </[a-z0-9]+>' ) ) > 2

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.parse_text, regex.count.

Indicators Matched (10)

FieldMatchValue
attachments[].file_typememberhtml
attachments[].file_typemembersvg
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberxhtml
attachments[].file_extensionmembermhtml
attachments[].file_extensionmembersvg
attachments[].content_typemembertext/html
attachments[].content_typemembertext/plain
regex.countregex<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\. (</[a-z]+>)? +-->
regex.countregex<[a-z0-9]+ style="display:none;">(<[a-z]+>)? [A-Z].*\. </[a-z0-9]+>

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type in ["text/html", "text/plain"]
        attachments.file_extension in ["html", "mhtml", "svg", "xhtml"]
        attachments.file_type in ["html", "svg"]
      or
        regex.count func_call "(\n            // targeting comments inside hidden HTML elements\n            // example: \"<h1 style=\"display:none;\"> Self-confidence inspires others to believe in you. </h1>\"\n            regex.count(file.parse_text(.).text,\n                        '<[a-z0-9]+ style=\"display:none;\">(<[a-z]+>)? [A-Z].*\\. </[a-z0-9]+>'\n            )\n          ) > 2"
        regex.count func_call "(\n            // targeting comments that pad the file with sayings\n            // examples: \"<!-- <span> No gain without pain. </span> -->\", \"<!-- <p> Beauty is only skin deep. </p> -->\", \"<!-- <span> Actions speak louder than words. </span> -->\"\n            regex.count(file.parse_text(.).text,\n                        '<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\\. (</[a-z]+>)? +-->'\n            )\n          ) > 2"
         macro "(\n            // targeting comments that pad the file with quotes from literature\n            // examples: \"// Echoes of the past linger in silence.\", \"// The wind whispered secrets unknown.\", \"// Shadows tell stories in the dark.\"\n\n            // count all HTML code comments that match our pattern\n            regex.count(file.parse_text(.).text, '// [A-Z][ a-z ]+\\.') / \n            // divide by the count of all UNIQUE HTML code comments that match our pattern\n            length(distinct(regex.extract(file.parse_text(.).text,\n                                          '// [A-Z][ a-z ]+\\.'\n                            ),\n                            .full_match\n                   )\n            ) \n            // at least 50% of the comments are duplicates\n            >= 2\n          )"
      attachments.size lt "100000"
  type.inbound eq "true"

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"

Attachment: WinRAR CVE-2025-8088 exploitation

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

Detects attempts to exploit CVE-2025-8088 via attached RAR files

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesExploit, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        // its a rar file
        (
          .content_type == "application/x-rar-compressed"
          or .file_extension == "rar"
          or .file_type == "rar"
        )
        // less than 10 meg
        and .size < 10000000
        // explode it
        and any(file.explode(.),
                // contains a yara match
                any(.scan.yara.matches, .name == "WinRAR_CVE_2025_8088")
        )
)

Detection Logic

Scope: inbound message.

Detects attempts to exploit CVE-2025-8088 via attached RAR files

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .content_type is 'application/x-rar-compressed'
      • .file_extension is 'rar'
      • .file_type is 'rar'
    • .size < 10000000
    • any(file.explode(.), // contains a yara match any(.scan.yara.matches, .name == "WinRAR_CVE_2025_8088") )

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.explode.

Indicators Matched (4)

FieldMatchValue
attachments[].content_typeequalsapplication/x-rar-compressed
attachments[].file_extensionequalsrar
attachments[].file_typeequalsrar
file.explode(attachments[])[].scan.yara.matches[].nameequalsWinRAR_CVE_2025_8088

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "application/x-rar-compressed"
        attachments.file_extension eq "rar"
        attachments.file_type eq "rar"
      attachments.size lt "10000000"
       macro "any(file.explode(.),\n                // contains a yara match\n                any(.scan.yara.matches, .name == \"WinRAR_CVE_2025_8088\")\n        )"
  type.inbound eq "true"

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"

Attachment: XLSX file with suspicious print titles metadata

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

Detects XLSX attachments containing EXIF metadata with suspicious TitlesOfParts fields that follow a specific pattern combining 'Company_Name' with extracted values and 'Print_Titles', potentially indicating malicious document preparation.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Macros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "xlsx"),
        // get the TitleOfParts (Excel Docs this is Worksheet names)
        // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oi29500/de32de14-9573-46f3-9f38-19659e3a8d9a
        any(filter(beta.parse_exif(.).fields, .key == "TitlesOfParts"),
            // extract the first sheet name
            any(regex.iextract(.value, '^\[\"(?P<first_sheet>[^\"]+)\"'),
                // check that the first sheet name is observed in the last sheet name with !print_title and comes after a sheet named "Company_Name"
                strings.ends_with(..value,
                                  strings.concat("Company_Name\",\"",
                                                 .named_groups["first_sheet"],
                                                 '!Print_Titles"]'
                                  )
                )
            )
        )
)

Detection Logic

Scope: inbound message.

Detects XLSX attachments containing EXIF metadata with suspicious TitlesOfParts fields that follow a specific pattern combining 'Company_Name' with extracted values and 'Print_Titles', potentially indicating malicious document preparation.

  1. inbound message
  2. any(filter(attachments, .file_type == "xlsx"), // get the TitleOfParts (Excel Docs this is Worksheet names) // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oi29500/de32de14-9573-46f3-9f38-19659e3a8d9a any(filter(beta.parse_exif(.).fields, .key == "TitlesOfParts"), // extract the first sheet name any(regex.iextract(.value, '^\[\"(?P<first_sheet>[^\"]+)\"'), // check that the first sheet name is observed in the last sheet name with !print_title and comes after a sheet named "Company_Name" strings.ends_with(..value, strings.concat("Company_Name\",\"", .named_groups["first_sheet"], '!Print_Titles"]' ) ) ) ) )

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif, regex.iextract, strings.concat, strings.ends_with.

Indicators Matched (3)

FieldMatchValue
attachments[].file_typeequalsxlsx
beta.parse_exif(filter(attachments)[]).fields[].keyequalsTitlesOfParts
regex.iextractregex^\[\"(?P<first_sheet>[^\"]+)\"

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"xlsx\"),\n        // get the TitleOfParts (Excel Docs this is Worksheet names)\n        // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oi29500/de32de14-9573-46f3-9f38-19659e3a8d9a\n        any(filter(beta.parse_exif(.).fields, .key == \"TitlesOfParts\"),\n            // extract the first sheet name\n            any(regex.iextract(.value, '^\\[\\\"(?P<first_sheet>[^\\\"]+)\\\"'),\n                // check that the first sheet name is observed in the last sheet name with !print_title and comes after a sheet named \"Company_Name\"\n                strings.ends_with(..value,\n                                  strings.concat(\"Company_Name\\\",\\\"\",\n                                                 .named_groups[\"first_sheet\"],\n                                                 '!Print_Titles\"]'\n                                  )\n                )\n            )\n        )\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"

Attachment: ZIP containing Office binary with embedded DLL

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

Detects inbound messages with a ZIP attachment that contains an office binary and an unknown DLL.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "zip"),
        any(file.explode(.),
            any(.scan.yara.matches, .name == "zip_office_bin_dll")
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages with a ZIP attachment that contains an office binary and an unknown DLL.

  1. inbound message
  2. any(filter(attachments, .file_type == "zip"), any(file.explode(.), any(.scan.yara.matches, .name == "zip_office_bin_dll") ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalszip
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalszip_office_bin_dll

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"zip\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name == \"zip_office_bin_dll\")\n        )\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"

Attachment: Zip exploiting CVE-2023-38831 (unsolicited)

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

A Zip attachment that exhibits attributes required to exploit CVE-2023-38831, a vulnerability in WinRAR (prior to 6.23).

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
    .file_extension in $file_extensions_common_archives and
    any(file.explode(.), 
        (
            .depth == 0 and 
            any(.scan.zip.all_paths, 
                regex.match(., 
                // zip contains a path with spaces and file extensions 
                // lure.pdf /lure.pdf .cmd
                // 
                //  /= Initial file name (including any spaces)
                //  |
                //  |       /= Space
                //  |       |
                //  |       | /= Folder
                //  |       | |
                //  |       | | /= Repeated file name
                //  |       | | |
                //  |       | | |      /= Space
                //  |       | | |      |   
                //  |       | | |      |   /= Real script ending
                //  |       | | |      |   |
                    '.+\.\w+\s\/.+\.\w+\s\.\w+'
                )
            )
        ) and 
        (
            // One file name is present in another, e.g.
            //     delivrto.pdf 
            //     delivrto.pdf /delivrto.pdf .cmd
            any(.scan.zip.all_paths, 
                any(..scan.zip.all_paths,
                    . != .. and 
                    strings.starts_with(., ..)
                )
            )
        )
    )
)
and (
    (
        sender.email.domain.root_domain in $free_email_providers
        and sender.email.email not in $recipient_emails
    )
    or (
        sender.email.domain.root_domain not in $free_email_providers
        and sender.email.domain.domain not in $recipient_domains
    )
)

Detection Logic

Scope: inbound message.

A Zip attachment that exhibits attributes required to exploit CVE-2023-38831, a vulnerability in WinRAR (prior to 6.23).

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), ( .depth == 0 and any(.scan.zip.all_paths, regex.match(., // zip contains a path with spaces and file extensions // lure.pdf /lure.pdf .cmd // // /= Initial file name (including any spaces) // | // | /= Space // | | // | | /= Folder // | | | // | | | /= Repeated file name // | | | | // | | | | /= Space // | | | | | // | | | | | /= Real script ending // | | | | | | '.+\.\w+\s\/.+\.\w+\s\.\w+' ) ) ) and ( // One file name is present in another, e.g. // delivrto.pdf // delivrto.pdf /delivrto.pdf .cmd any(.scan.zip.all_paths, any(..scan.zip.all_paths, . != .. and strings.starts_with(., ..) ) ) ) )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $free_email_providers
      • sender.email.email not in $recipient_emails
    • all of:
      • sender.email.domain.root_domain not in $free_email_providers
      • sender.email.domain.domain not in $recipient_domains

Inspects: attachments[].file_extension, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.email, type.inbound. Sensors: file.explode, regex.match, strings.starts_with. Reference lists: $file_extensions_common_archives, $free_email_providers, $recipient_domains, $recipient_emails.

Indicators Matched (1)

FieldMatchValue
regex.matchregex.+\.\w+\s\/.+\.\w+\s\.\w+

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.), \n        (\n            .depth == 0 and \n            any(.scan.zip.all_paths, \n                regex.match(., \n                // zip contains a path with spaces and file extensions \n                // lure.pdf /lure.pdf .cmd\n                // \n                //  /= Initial file name (including any spaces)\n                //  |\n                //  |       /= Space\n                //  |       |\n                //  |       | /= Folder\n                //  |       | |\n                //  |       | | /= Repeated file name\n                //  |       | | |\n                //  |       | | |      /= Space\n                //  |       | | |      |   \n                //  |       | | |      |   /= Real script ending\n                //  |       | | |      |   |\n                    '.+\\.\\w+\\s\\/.+\\.\\w+\\s\\.\\w+'\n                )\n            )\n        ) and \n        (\n            // One file name is present in another, e.g.\n            //     delivrto.pdf \n            //     delivrto.pdf /delivrto.pdf .cmd\n            any(.scan.zip.all_paths, \n                any(..scan.zip.all_paths,\n                    . != .. and \n                    strings.starts_with(., ..)\n                )\n            )\n        )\n    )"
  or
    and
      sender.email.domain.domain macro "sender.email.domain.domain not in recipient_domains"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain not in free_email_providers"
    and
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in free_email_providers"
      sender.email.email macro "sender.email.email not in recipient_emails"
  type.inbound eq "true"

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"

Attachment: ZIP file with CVE-2026-0866 exploit

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

Detects ZIP attachments containing exploits targeting CVE-2026-0866 vulnerability through YARA signature matching.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesExploit, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments

Rule Body

any(filter(attachments, .file_type == "zip"),
    any(file.explode(.),
        any(.scan.yara.matches, .name in ("zip_cve_2026_0866"))
    )
)

Detection Logic

Detects ZIP attachments containing exploits targeting CVE-2026-0866 vulnerability through YARA signature matching.

any(filter(attachments, .file_type == "zip"), any(file.explode(.), any(.scan.yara.matches, .name in ("zip_cve_2026_0866")) ) )

Inspects: attachments[].file_type. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalszip
file.explode(filter(attachments)[])[].scan.yara.matches[].namememberzip_cve_2026_0866

Stages and Predicates

Stage 1: mql_rule

 macro "any(filter(attachments, .file_type == \"zip\"),\n    any(file.explode(.),\n        any(.scan.yara.matches, .name in (\"zip_cve_2026_0866\"))\n    )\n)"

Attachment: ZIP filename mismatch

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

Detects inbound messages with ZIP attachments that exhibit a mismatch between the filename stored in the local file header and the filename in the central directory.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(filter(attachments, .file_type == "zip"),
        any(file.explode(.),
            any(.scan.yara.matches, .name == "zip_pklfh_cd_fname_mismatch")
        )
)

Detection Logic

Scope: inbound message.

Detects inbound messages with ZIP attachments that exhibit a mismatch between the filename stored in the local file header and the filename in the central directory.

  1. inbound message
  2. any(filter(attachments, .file_type == "zip"), any(file.explode(.), any(.scan.yara.matches, .name == "zip_pklfh_cd_fname_mismatch") ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalszip
file.explode(filter(attachments)[])[].scan.yara.matches[].nameequalszip_pklfh_cd_fname_mismatch

Stages and Predicates

Stage 1: mql_rule

and
  type.inbound eq "true"
   macro "any(filter(attachments, .file_type == \"zip\"),\n        any(file.explode(.),\n            any(.scan.yara.matches, .name == \"zip_pklfh_cd_fname_mismatch\")\n        )\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"

Brand impersonation: Adobe (QR code)

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

Detects messages using Adobe image based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, PDF, QR code

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.auth_summary
  • headers.hops
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and (
  any(attachments,
      (.file_type in $file_types_images or .file_type == "pdf")
      and (
        any(ml.logo_detect(.).brands,
            .name == "Adobe" and .confidence in ("medium", "high")
        )
        or any(ml.logo_detect(file.message_screenshot()).brands,
               .name == "Adobe"
        )
        or any(file.explode(.),
               any(.scan.strings.strings,
                   regex.icontains(., "adobe (acrobat|sign)")
                   // negate PDF data, like "xmp:CreatorTool>Adobe Acrobat Pro (64-bit) 24.4.20272</xmp:CreatorTool>"
                   and not regex.icontains(.,
                                           "(creatortool|producer|creator).{1,5}adobe acrobat"
                   )
               )
        )
      )
  )
  or any(attachments,
         .file_extension in $file_extensions_macros
         and any(file.explode(.), .depth == 0 and .scan.docx.image_count > 0)
         and any(file.explode(.),
                 any(.scan.strings.strings, strings.ilike(., "*adobe*"))
         )
  )
)
and any(attachments,
        (
          .file_type in $file_types_images
          or .file_type == "pdf"
          or .file_type in $file_extensions_macros
        )
        and (
          any(file.explode(.),
              regex.icontains(.scan.ocr.raw, 'scan|camera')
              and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode')
          )
          or (
            any(file.explode(.),
                .scan.qr.type == "url"
                // recipient email address is present in the URL, a common tactic used in credential phishing attacks
                and (
                  any(recipients.to,
                      (
                        (
                          .email.domain.valid
                          and (
                            strings.icontains(..scan.qr.data, .email.email)
                            or any(strings.scan_base64(..scan.qr.data,
                                                       format="url"
                                   ),
                                   strings.icontains(., ..email.email)
                            )
                          )
                        )
                        or strings.icontains(.display_name, "undisclosed")
                      )
                  )

                  // the recipients sld is in the senders display name
                  or any(recipients.to,
                         strings.icontains(sender.display_name,
                                           .email.domain.sld
                         )
                  )

                  // the recipient local is in the body
                  or any(recipients.to,
                         strings.icontains(body.current_thread.text,
                                           .email.local_part
                         )
                  )

                  // or the body is null
                  or body.current_thread.text is null
                  or body.current_thread.text == ""

                  // or the subject contains authentication/urgency verbiage
                  or regex.contains(subject.subject,
                                    "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)"
                  )

                  // high confidence cred theft in body
                  or any(ml.nlu_classifier(body.current_thread.text).intents,
                         .name == "cred_theft" and .confidence in ("high")
                  )
                )
            )
          )
        )
)
and (
  not sender.email.domain.root_domain in (
    "acrobat.com",
    "adobecc.com",
    "adobecces.com",
    "adobeccstatic.com",
    "adobe.com",
    "adobeexchange.com",
    "adobe-identity.com",
    "adobe.io",
    "adobejanus.com",
    "adobelogin.com",
    "adobe.net",
    "adobeprojectm.com",
    "adoberesources.net",
    "adobesc.com",
    "adobesign.com",
    "adobestock.com",
    "createjs.com",
    "licensingstack.com",
    "myportfolio.com",
    "photoshop.com",
    "typekit.com",
    "typekit.net"
  )
  or not any(headers.hops,
             .authentication_results.compauth.verdict is not null
             and .authentication_results.compauth.verdict == "pass"
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects messages using Adobe image based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

  1. inbound message
  2. any of:
    • any of attachments where all hold:
      • any of:
        • .file_type in $file_types_images
        • .file_type is 'pdf'
      • any of:
        • any(ml.logo_detect(.).brands, .name == "Adobe" and .confidence in ("medium", "high") )
        • any(ml.logo_detect(file.message_screenshot()).brands, .name == "Adobe" )
        • any(file.explode(.), any(.scan.strings.strings, regex.icontains(., "adobe (acrobat|sign)") // negate PDF data, like "xmp:CreatorTool>Adobe Acrobat Pro (64-bit) 24.4.20272</xmp:CreatorTool>" and not regex.icontains(., "(creatortool|producer|creator).{1,5}adobe acrobat" ) ) )
    • any of attachments where all hold:
      • .file_extension in $file_extensions_macros
      • any(file.explode(.), .depth == 0 and .scan.docx.image_count > 0)
      • any(file.explode(.), any(.scan.strings.strings, strings.ilike(., "*adobe*")) )
  3. any of attachments where all hold:
    • any of:
      • .file_type in $file_types_images
      • .file_type is 'pdf'
      • .file_type in $file_extensions_macros
    • any of:
      • any(file.explode(.), regex.icontains(.scan.ocr.raw, 'scan|camera') and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode') )
      • ( any(file.explode(.), .scan.qr.type == "url" // recipient email address is present in the URL, a common tactic used in credential phishing attacks and ( any(recipients.to, ( ( .email.domain.valid and ( strings.icontains(..scan.qr.data, .email.email) or any(strings.scan_base64(..scan.qr.data, format="url" ), strings.icontains(., ..email.email) ) ) ) or strings.icontains(.display_name, "undisclosed") ) ) // the recipients sld is in the senders display name or any(recipients.to, strings.icontains(sender.display_name, .email.domain.sld ) ) // the recipient local is in the body or any(recipients.to, strings.icontains(body.current_thread.text, .email.local_part ) ) // or the body is null or body.current_thread.text is null or body.current_thread.text == "" // or the subject contains authentication/urgency verbiage or regex.contains(subject.subject, "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)" ) // high confidence cred theft in body or any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence in ("high") ) ) ) )
  4. any of:
    • not:
      • sender.email.domain.root_domain in ('acrobat.com', 'adobecc.com', 'adobecces.com', 'adobeccstatic.com', 'adobe.com', 'adobeexchange.com', 'adobe-identity.com', 'adobe.io', 'adobejanus.com', 'adobelogin.com', 'adobe.net', 'adobeprojectm.com', 'adoberesources.net', 'adobesc.com', 'adobesign.com', 'adobestock.com', 'createjs.com', 'licensingstack.com', 'myportfolio.com', 'photoshop.com', 'typekit.com', 'typekit.net')
    • not:
      • any of headers.hops where all hold:
        • .authentication_results.compauth.verdict is set
        • .authentication_results.compauth.verdict is 'pass'
  5. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].file_extension, attachments[].file_type, body.current_thread.text, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].authentication_results.compauth.verdict, recipients.to, recipients.to[].display_name, recipients.to[].email.domain.sld, recipients.to[].email.domain.valid, recipients.to[].email.email, recipients.to[].email.local_part, sender.display_name, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, file.message_screenshot, ml.logo_detect, ml.nlu_classifier, regex.contains, regex.icontains, strings.icontains, strings.ilike, strings.scan_base64. Reference lists: $file_extensions_macros, $file_types_images, $high_trust_sender_root_domains.

Indicators Matched (15)

FieldMatchValue
attachments[].file_typeequalspdf
ml.logo_detect(attachments[]).brands[].nameequalsAdobe
ml.logo_detect(attachments[]).brands[].confidencemembermedium
ml.logo_detect(attachments[]).brands[].confidencememberhigh
ml.logo_detect(file.message_screenshot()).brands[].nameequalsAdobe
regex.icontainsregexadobe (acrobat|sign)
strings.ilikesubstring*adobe*
regex.icontainsregexscan|camera
regex.icontainsregex\bQR\b|Q\.R\.|barcode
file.explode(attachments[])[].scan.qr.typeequalsurl
strings.icontainssubstringundisclosed
body.current_thread.textequals
3 more
regex.containsregex(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)
ml.nlu_classifier(body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(body.current_thread.text).intents[].confidencememberhigh

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        or
          attachments.file_type eq "pdf"
          attachments.file_type macro "attachments[].file_type in file_types_images"
        or
           macro "any(file.explode(.),\n               any(.scan.strings.strings,\n                   regex.icontains(., \"adobe (acrobat|sign)\")\n                   // negate PDF data, like \"xmp:CreatorTool>Adobe Acrobat Pro (64-bit) 24.4.20272</xmp:CreatorTool>\"\n                   and not regex.icontains(.,\n                                           \"(creatortool|producer|creator).{1,5}adobe acrobat\"\n                   )\n               )\n        )"
           macro "any(ml.logo_detect(.).brands,\n            .name == \"Adobe\" and .confidence in (\"medium\", \"high\")\n        )"
           macro "any(ml.logo_detect(file.message_screenshot()).brands,\n               .name == \"Adobe\"\n        )"
    any(attachments)
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
         macro "any(file.explode(.), .depth == 0 and .scan.docx.image_count > 0)"
         macro "any(file.explode(.),\n                 any(.scan.strings.strings, strings.ilike(., \"*adobe*\"))\n         )"
  or
    not
      any(headers.hops)
        and
          headers.hops.authentication_results.compauth.verdict eq "pass"
          headers.hops.authentication_results.compauth.verdict is_not_null
    not
      sender.email.domain.root_domain in ["acrobat.com", "adobe-identity.com", "adobe.com", "adobe.io", "adobe.net", "adobecc.com", "adobecces.com", "adobeccstatic.com", "adobeexchange.com", "adobejanus.com", "adobelogin.com", "adobeprojectm.com", "adoberesources.net", "adobesc.com", "adobesign.com", "adobestock.com", "createjs.com", "licensingstack.com", "myportfolio.com", "photoshop.com", "typekit.com", "typekit.net"]
  any(attachments)
    and
      or
        attachments.file_type eq "pdf"
        attachments.file_type macro "attachments[].file_type in file_extensions_macros"
        attachments.file_type macro "attachments[].file_type in file_types_images"
      or
         macro "(\n            any(file.explode(.),\n                .scan.qr.type == \"url\"\n                // recipient email address is present in the URL, a common tactic used in credential phishing attacks\n                and (\n                  any(recipients.to,\n                      (\n                        (\n                          .email.domain.valid\n                          and (\n                            strings.icontains(..scan.qr.data, .email.email)\n                            or any(strings.scan_base64(..scan.qr.data,\n                                                       format=\"url\"\n                                   ),\n                                   strings.icontains(., ..email.email)\n                            )\n                          )\n                        )\n                        or strings.icontains(.display_name, \"undisclosed\")\n                      )\n                  )\n\n                  // the recipients sld is in the senders display name\n                  or any(recipients.to,\n                         strings.icontains(sender.display_name,\n                                           .email.domain.sld\n                         )\n                  )\n\n                  // the recipient local is in the body\n                  or any(recipients.to,\n                         strings.icontains(body.current_thread.text,\n                                           .email.local_part\n                         )\n                  )\n\n                  // or the body is null\n                  or body.current_thread.text is null\n                  or body.current_thread.text == \"\"\n\n                  // or the subject contains authentication/urgency verbiage\n                  or regex.contains(subject.subject,\n                                    \"(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)\"\n                  )\n\n                  // high confidence cred theft in body\n                  or any(ml.nlu_classifier(body.current_thread.text).intents,\n                         .name == \"cred_theft\" and .confidence in (\"high\")\n                  )\n                )\n            )\n          )"
         macro "any(file.explode(.),\n              regex.icontains(.scan.ocr.raw, 'scan|camera')\n              and regex.icontains(.scan.ocr.raw, '\\bQR\\b|Q\\.R\\.|barcode')\n          )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  type.inbound eq "true"

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"

Brand impersonation: DocuSign (QR code)

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

Detects messages using DocuSign image based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, PDF, QR code, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (.file_type in $file_types_images or .file_type == "pdf")
        and (
          any(ml.logo_detect(.).brands,
              .name == "DocuSign" and .confidence in ("medium", "high")
          )
          or any(ml.logo_detect(file.message_screenshot()).brands,
                 .name == "DocuSign"
          )
        )
        and (
          any(file.explode(.),
              (
                (
                  .scan.qr.type is not null
                  and regex.contains(.scan.qr.data, '\.')
                )
                or 
                // QR code language
                (
                  regex.icontains(.scan.ocr.raw, 'scan|camera')
                  and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode')
                )
              )

              // exclude images taken with mobile cameras and screenshots from android
              and not any(.scan.exiftool.fields,
                          .key == "Model"
                          or (
                            .key == "Software"
                            and strings.starts_with(.value, "Android")
                          )
              )
              // exclude images taken with mobile cameras and screenshots from Apple
              and not any(.scan.exiftool.fields,
                          .key == "DeviceManufacturer"
                          and .value == "Apple Computer Inc."
              )
          )
        )
)
and not (
  sender.email.domain.root_domain in ("docusign.net", "docusign.com")
  and headers.auth_summary.dmarc.pass
)

Detection Logic

Scope: inbound message.

Detects messages using DocuSign image based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_type in $file_types_images
      • .file_type is 'pdf'
    • any of:
      • any(ml.logo_detect(.).brands, .name == "DocuSign" and .confidence in ("medium", "high") )
      • any(ml.logo_detect(file.message_screenshot()).brands, .name == "DocuSign" )
    • ( any(file.explode(.), ( ( .scan.qr.type is not null and regex.contains(.scan.qr.data, '\.') ) or // QR code language ( regex.icontains(.scan.ocr.raw, 'scan|camera') and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode') ) ) // exclude images taken with mobile cameras and screenshots from android and not any(.scan.exiftool.fields, .key == "Model" or ( .key == "Software" and strings.starts_with(.value, "Android") ) ) // exclude images taken with mobile cameras and screenshots from Apple and not any(.scan.exiftool.fields, .key == "DeviceManufacturer" and .value == "Apple Computer Inc." ) ) )
  3. not:
    • all of:
      • sender.email.domain.root_domain in ('docusign.net', 'docusign.com')
      • headers.auth_summary.dmarc.pass

Inspects: attachments[].file_type, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, file.message_screenshot, ml.logo_detect, regex.contains, regex.icontains, strings.starts_with. Reference lists: $file_types_images.

Indicators Matched (8)

FieldMatchValue
attachments[].file_typeequalspdf
ml.logo_detect(attachments[]).brands[].nameequalsDocuSign
ml.logo_detect(attachments[]).brands[].confidencemembermedium
ml.logo_detect(attachments[]).brands[].confidencememberhigh
ml.logo_detect(file.message_screenshot()).brands[].nameequalsDocuSign
regex.containsregex\.
regex.icontainsregexscan|camera
regex.icontainsregex\bQR\b|Q\.R\.|barcode

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.file_type eq "pdf"
        attachments.file_type macro "attachments[].file_type in file_types_images"
      or
         macro "any(ml.logo_detect(.).brands,\n              .name == \"DocuSign\" and .confidence in (\"medium\", \"high\")\n          )"
         macro "any(ml.logo_detect(file.message_screenshot()).brands,\n                 .name == \"DocuSign\"\n          )"
       macro "(\n          any(file.explode(.),\n              (\n                (\n                  .scan.qr.type is not null\n                  and regex.contains(.scan.qr.data, '\\.')\n                )\n                or \n                // QR code language\n                (\n                  regex.icontains(.scan.ocr.raw, 'scan|camera')\n                  and regex.icontains(.scan.ocr.raw, '\\bQR\\b|Q\\.R\\.|barcode')\n                )\n              )\n\n              // exclude images taken with mobile cameras and screenshots from android\n              and not any(.scan.exiftool.fields,\n                          .key == \"Model\"\n                          or (\n                            .key == \"Software\"\n                            and strings.starts_with(.value, \"Android\")\n                          )\n              )\n              // exclude images taken with mobile cameras and screenshots from Apple\n              and not any(.scan.exiftool.fields,\n                          .key == \"DeviceManufacturer\"\n                          and .value == \"Apple Computer Inc.\"\n              )\n          )\n        )"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain in ["docusign.com", "docusign.net"]
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

Brand impersonation: DocuSign branded attachment lure with no DocuSign links

#

Brand Impersonation: Google (QR Code)

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

Detects messages using Google based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, PDF, QR code

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • headers
  • headers.hops
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and length(body.current_thread.text) < 1000
and any([subject.subject, sender.display_name, body.current_thread.text],
        regex.icontains(.,
                        '(?:\b2fa\b|\bQ.?R\.?\s?\b|MFA|Muti[ -]?Factor|Auth(?:enticat|e|or|ion)?)'
        )
)
and (
  any(attachments,
      (
        .file_type in $file_types_images
        or .file_type == "pdf"
        or .file_type in~ $file_extensions_macros
      )
      and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Google"))
  )
  or any(ml.logo_detect(file.message_screenshot()).brands,
         strings.starts_with(.name, "Google")
  )
)
and any(attachments,
        (
          .file_type in $file_types_images
          or .file_type == "pdf"
          or .file_type in $file_extensions_macros
        )
        and (
          any(file.explode(.),
              regex.icontains(.scan.ocr.raw, 'scan|camera')
              and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode')
          )
          or any(file.explode(.),
                 .scan.qr.type is not null
                 and regex.contains(.scan.qr.data, '\.')
          )
          or (
            //
            // This rule makes use of a beta feature and is subject to change without notice
            // using the beta feature in custom rules is not suggested until it has been formally released
            //
            beta.parse_exif(file.message_screenshot()).image_height < 2000
            and beta.parse_exif(file.message_screenshot()).image_width < 2000
            and any(beta.scan_qr(file.message_screenshot()).items,
                    .type is not null and regex.contains(.data, '\.')
            )
          )
        )
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and (
      any(distinct(headers.hops, .authentication_results.dmarc is not null),
          strings.ilike(.authentication_results.dmarc, "*fail")
      )
    )
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects messages using Google based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

  1. inbound message
  2. length(body.current_thread.text) < 1000
  3. any([subject.subject, sender.display_name, body.current_thread.text], regex.icontains(., '(?:\b2fa\b|\bQ.?R\.?\s?\b|MFA|Muti[ -]?Factor|Auth(?:enticat|e|or|ion)?)' ) )
  4. any of:
    • any of attachments where all hold:
      • any of:
        • .file_type in $file_types_images
        • .file_type is 'pdf'
        • .file_type in $file_extensions_macros
      • any(ml.logo_detect(.).brands, strings.starts_with(.name, "Google"))
    • any(ml.logo_detect(file.message_screenshot()).brands, strings.starts_with(.name, "Google") )
  5. any of attachments where all hold:
    • any of:
      • .file_type in $file_types_images
      • .file_type is 'pdf'
      • .file_type in $file_extensions_macros
    • any of:
      • any(file.explode(.), regex.icontains(.scan.ocr.raw, 'scan|camera') and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode') )
      • any(file.explode(.), .scan.qr.type is not null and regex.contains(.scan.qr.data, '\.') )
      • all of:
        • beta.parse_exif(file.message_screenshot()).image_height < 2000
        • beta.parse_exif(file.message_screenshot()).image_width < 2000
        • any(beta.scan_qr(file.message_screenshot()).items, .type is not null and regex.contains(.data, '\.') )
  6. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  7. not:
    • profile.by_sender().any_messages_benign
  8. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • ( any(distinct(headers.hops, .authentication_results.dmarc is not null), strings.ilike(.authentication_results.dmarc, "*fail") ) )
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].file_type, body.current_thread.text, headers.hops, headers.hops[].authentication_results.dmarc, sender.display_name, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: beta.parse_exif, beta.scan_qr, file.explode, file.message_screenshot, ml.logo_detect, profile.by_sender, regex.contains, regex.icontains, strings.ilike, strings.starts_with. Reference lists: $file_extensions_macros, $file_types_images, $high_trust_sender_root_domains.

Indicators Matched (7)

FieldMatchValue
regex.icontainsregex(?:\b2fa\b|\bQ.?R\.?\s?\b|MFA|Muti[ -]?Factor|Auth(?:enticat|e|or|ion)?)
attachments[].file_typeequalspdf
strings.starts_withprefixGoogle
regex.icontainsregexscan|camera
regex.icontainsregex\bQR\b|Q\.R\.|barcode
regex.containsregex\.
strings.ilikesubstring*fail

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        or
          attachments.file_type eq "pdf"
          attachments.file_type macro "attachments[].file_type in file_extensions_macros"
          attachments.file_type macro "attachments[].file_type in file_types_images"
         macro "any(ml.logo_detect(.).brands, strings.starts_with(.name, \"Google\"))"
     macro "any(ml.logo_detect(file.message_screenshot()).brands,\n         strings.starts_with(.name, \"Google\")\n  )"
  any(attachments)
    and
      or
        and
          beta.parse_exif func_call "beta.parse_exif(file.message_screenshot()).image_height < 2000"
          beta.parse_exif func_call "beta.parse_exif(file.message_screenshot()).image_width < 2000"
           macro "any(beta.scan_qr(file.message_screenshot()).items,\n                    .type is not null and regex.contains(.data, '\\.')\n            )"
         macro "any(file.explode(.),\n                 .scan.qr.type is not null\n                 and regex.contains(.scan.qr.data, '\\.')\n          )"
         macro "any(file.explode(.),\n              regex.icontains(.scan.ocr.raw, 'scan|camera')\n              and regex.icontains(.scan.ocr.raw, '\\bQR\\b|Q\\.R\\.|barcode')\n          )"
      or
        attachments.file_type eq "pdf"
        attachments.file_type macro "attachments[].file_type in file_extensions_macros"
        attachments.file_type macro "attachments[].file_type in file_types_images"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    and
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
       macro "(\n      any(distinct(headers.hops, .authentication_results.dmarc is not null),\n          strings.ilike(.authentication_results.dmarc, \"*fail\")\n      )\n    )"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  body.current_thread.text length_compare "1000"
  type.inbound eq "true"
   macro "any([subject.subject, sender.display_name, body.current_thread.text],\n        regex.icontains(.,\n                        '(?:\\b2fa\\b|\\bQ.?R\\.?\\s?\\b|MFA|Muti[ -]?Factor|Auth(?:enticat|e|or|ion)?)'\n        )\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"

Brand impersonation: Microsoft (QR code)

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

Detects messages using Microsoft image based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, PDF, QR code, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.html
  • headers
  • headers.hops
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and (
  any(attachments,
      (
        .file_type in $file_types_images
        or .file_type == "pdf"
        or .file_type in~ $file_extensions_macros
      )
      and (
        any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft"))
        or any(file.explode(.),
               // for Office documents
               .flavors.mime == "text/xml"
               and any(.scan.strings.strings,
                       regex.icontains(.,
                                       'Microsoft\s*(?:\w+(?:\s*\w+)?|[[:punct:]]+|\s+){0,3}\s*(?:Authenticat(?:e|or|ion)|2fa|Multi.Factor|(?:qr|bar).code|action.require|alert|Att(?:n|ention))'
                       )
               )
        )
      )
  )
  or any(ml.logo_detect(file.message_screenshot()).brands,
         strings.starts_with(.name, "Microsoft")
  )
  or (
    // limited body length
    length(body.current_thread.text) < 300
    and any(filter(attachments,
                   .file_type in $file_types_images
                   // image attachments that are displayed in the body
                   // when the content-id is corrected, this will be much more simple
                   and (
                     any(regex.extract(.content_id, '^<(?P<cid>[^\>]+)\>$'),
                         strings.icontains(body.html.raw, .named_groups["cid"])
                     )
                     or strings.icontains(body.html.raw, .content_id)
                   )
            ),
            // those images contain the wording
            any(file.explode(.),
                regex.icontains(.scan.ocr.raw,
                                'Microsoft\s*(?:\w+(?:\s*\w+)?|[[:punct:]]+|\s+){0,3}\s*(?:Authenticat(?:e|or|ion)|2fa|Multi.Factor|(?:qr|bar).code|action.require|alert|Att(?:n|ention))'
                )
            )
    )
  )
)
and any(attachments,
        (
          .file_type in $file_types_images
          or .file_type == "pdf"
          or .file_type in $file_extensions_macros
        )
        and (
          any(file.explode(.),
              regex.icontains(.scan.ocr.raw, 'scan|camera')
              and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode')
          )
          or (
            any(file.explode(.),
                .scan.qr.type == "url"
                // recipient email address is present in the URL, a common tactic used in credential phishing attacks
                and any(recipients.to,
                        (
                          (strings.icontains(..scan.qr.data, .email.email))

                          // the recipients sld is in the senders display name
                          or any(recipients.to,
                                 strings.icontains(sender.display_name,
                                                   .email.domain.sld
                                 )
                          )

                          // the recipient local is in the body
                          or any(recipients.to,
                                 strings.icontains(body.current_thread.text,
                                                   .email.local_part
                                 )
                          )

                          // or the body is null
                          or body.current_thread.text is null
                          or body.current_thread.text == ""

                          // or the subject contains authentication/urgency verbiage
                          or regex.contains(subject.subject,
                                            "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)"
                          )
                        )
                        and (
                          .email.domain.valid
                          or strings.icontains(.display_name, "undisclosed")
                        )
                )
            )
          )
        )
)
and (
  not sender.email.domain.domain == "microsoft.com"
  or not any(headers.hops,
             .authentication_results.compauth.verdict is not null
             and .authentication_results.compauth.verdict == "pass"
  )
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

Detects messages using Microsoft image based lures, referencing or including a QR code from an Unsolicited sender. These messages often lead users to phishing sites or initiate unwanted downloads.

  1. inbound message
  2. any of:
    • any of attachments where all hold:
      • any of:
        • .file_type in $file_types_images
        • .file_type is 'pdf'
        • .file_type in $file_extensions_macros
      • any of:
        • any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft"))
        • any(file.explode(.), // for Office documents .flavors.mime == "text/xml" and any(.scan.strings.strings, regex.icontains(., 'Microsoft\s*(?:\w+(?:\s*\w+)?|[[:punct:]]+|\s+){0,3}\s*(?:Authenticat(?:e|or|ion)|2fa|Multi.Factor|(?:qr|bar).code|action.require|alert|Att(?:n|ention))' ) ) )
    • any(ml.logo_detect(file.message_screenshot()).brands, strings.starts_with(.name, "Microsoft") )
    • all of:
      • length(body.current_thread.text) < 300
      • any(filter(attachments, .file_type in $file_types_images // image attachments that are displayed in the body // when the content-id is corrected, this will be much more simple and ( any(regex.extract(.content_id, '^<(?P<cid>[^\>]+)\>$'), strings.icontains(body.html.raw, .named_groups["cid"]) ) or strings.icontains(body.html.raw, .content_id) ) ), // those images contain the wording any(file.explode(.), regex.icontains(.scan.ocr.raw, 'Microsoft\s*(?:\w+(?:\s*\w+)?|[[:punct:]]+|\s+){0,3}\s*(?:Authenticat(?:e|or|ion)|2fa|Multi.Factor|(?:qr|bar).code|action.require|alert|Att(?:n|ention))' ) ) )
  3. any of attachments where all hold:
    • any of:
      • .file_type in $file_types_images
      • .file_type is 'pdf'
      • .file_type in $file_extensions_macros
    • any of:
      • any(file.explode(.), regex.icontains(.scan.ocr.raw, 'scan|camera') and regex.icontains(.scan.ocr.raw, '\bQR\b|Q\.R\.|barcode') )
      • ( any(file.explode(.), .scan.qr.type == "url" // recipient email address is present in the URL, a common tactic used in credential phishing attacks and any(recipients.to, ( (strings.icontains(..scan.qr.data, .email.email)) // the recipients sld is in the senders display name or any(recipients.to, strings.icontains(sender.display_name, .email.domain.sld ) ) // the recipient local is in the body or any(recipients.to, strings.icontains(body.current_thread.text, .email.local_part ) ) // or the body is null or body.current_thread.text is null or body.current_thread.text == "" // or the subject contains authentication/urgency verbiage or regex.contains(subject.subject, "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)" ) ) and ( .email.domain.valid or strings.icontains(.display_name, "undisclosed") ) ) ) )
  4. any of:
    • not:
      • sender.email.domain.domain is 'microsoft.com'
    • not:
      • any of headers.hops where all hold:
        • .authentication_results.compauth.verdict is set
        • .authentication_results.compauth.verdict is 'pass'
  5. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  6. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_id, attachments[].file_type, body.current_thread.text, body.html.raw, headers.hops, headers.hops[].authentication_results.compauth.verdict, recipients.to, recipients.to[].display_name, recipients.to[].email.domain.sld, recipients.to[].email.domain.valid, recipients.to[].email.email, recipients.to[].email.local_part, sender.display_name, sender.email.domain.domain, subject.subject, type.inbound. Sensors: file.explode, file.message_screenshot, ml.logo_detect, profile.by_sender, regex.contains, regex.extract, regex.icontains, strings.icontains, strings.starts_with. Reference lists: $file_extensions_macros, $file_types_images.

Indicators Matched (11)

FieldMatchValue
attachments[].file_typeequalspdf
strings.starts_withprefixMicrosoft
file.explode(attachments[])[].flavors.mimeequalstext/xml
regex.icontainsregexMicrosoft\s*(?:\w+(?:\s*\w+)?|[[:punct:]]+|\s+){0,3}\s*(?:Authenticat(?:e|or|ion)|2fa|Multi.Factor|(?:qr|bar).code|action.require|alert|Att(?:n|ention))
regex.extractregex^<(?P<cid>[^\>]+)\>$
regex.icontainsregexscan|camera
regex.icontainsregex\bQR\b|Q\.R\.|barcode
file.explode(attachments[])[].scan.qr.typeequalsurl
body.current_thread.textequals
regex.containsregex(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)
strings.icontainssubstringundisclosed

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        or
          attachments.file_type eq "pdf"
          attachments.file_type macro "attachments[].file_type in file_extensions_macros"
          attachments.file_type macro "attachments[].file_type in file_types_images"
        or
           macro "any(file.explode(.),\n               // for Office documents\n               .flavors.mime == \"text/xml\"\n               and any(.scan.strings.strings,\n                       regex.icontains(.,\n                                       'Microsoft\\s*(?:\\w+(?:\\s*\\w+)?|[[:punct:]]+|\\s+){0,3}\\s*(?:Authenticat(?:e|or|ion)|2fa|Multi.Factor|(?:qr|bar).code|action.require|alert|Att(?:n|ention))'\n                       )\n               )\n        )"
           macro "any(ml.logo_detect(.).brands, strings.starts_with(.name, \"Microsoft\"))"
    and
      body.current_thread.text length_compare "300"
       macro "any(filter(attachments,\n                   .file_type in $file_types_images\n                   // image attachments that are displayed in the body\n                   // when the content-id is corrected, this will be much more simple\n                   and (\n                     any(regex.extract(.content_id, '^<(?P<cid>[^\\>]+)\\>$'),\n                         strings.icontains(body.html.raw, .named_groups[\"cid\"])\n                     )\n                     or strings.icontains(body.html.raw, .content_id)\n                   )\n            ),\n            // those images contain the wording\n            any(file.explode(.),\n                regex.icontains(.scan.ocr.raw,\n                                'Microsoft\\s*(?:\\w+(?:\\s*\\w+)?|[[:punct:]]+|\\s+){0,3}\\s*(?:Authenticat(?:e|or|ion)|2fa|Multi.Factor|(?:qr|bar).code|action.require|alert|Att(?:n|ention))'\n                )\n            )\n    )"
     macro "any(ml.logo_detect(file.message_screenshot()).brands,\n         strings.starts_with(.name, \"Microsoft\")\n  )"
  or
    not
      any(headers.hops)
        and
          headers.hops.authentication_results.compauth.verdict eq "pass"
          headers.hops.authentication_results.compauth.verdict is_not_null
    not
      sender.email.domain.domain eq "microsoft.com"
  any(attachments)
    and
      or
        attachments.file_type eq "pdf"
        attachments.file_type macro "attachments[].file_type in file_extensions_macros"
        attachments.file_type macro "attachments[].file_type in file_types_images"
      or
         macro "(\n            any(file.explode(.),\n                .scan.qr.type == \"url\"\n                // recipient email address is present in the URL, a common tactic used in credential phishing attacks\n                and any(recipients.to,\n                        (\n                          (strings.icontains(..scan.qr.data, .email.email))\n\n                          // the recipients sld is in the senders display name\n                          or any(recipients.to,\n                                 strings.icontains(sender.display_name,\n                                                   .email.domain.sld\n                                 )\n                          )\n\n                          // the recipient local is in the body\n                          or any(recipients.to,\n                                 strings.icontains(body.current_thread.text,\n                                                   .email.local_part\n                                 )\n                          )\n\n                          // or the body is null\n                          or body.current_thread.text is null\n                          or body.current_thread.text == \"\"\n\n                          // or the subject contains authentication/urgency verbiage\n                          or regex.contains(subject.subject,\n                                            \"(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)\"\n                          )\n                        )\n                        and (\n                          .email.domain.valid\n                          or strings.icontains(.display_name, \"undisclosed\")\n                        )\n                )\n            )\n          )"
         macro "any(file.explode(.),\n              regex.icontains(.scan.ocr.raw, 'scan|camera')\n              and regex.icontains(.scan.ocr.raw, '\\bQR\\b|Q\\.R\\.|barcode')\n          )"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

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"

Credential phishing: Image as content, short or no body contents

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

This rule identifies incoming messages with minimal links, all image attachments and either empty, brief or the body text is only a warning banner/disclaimer. It also checks for truncated PNG images or logos in addition to high-confidence credit theft intentions.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Image as content

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • sender.email
  • type

Rule Body

type.inbound
and length(body.links) < 2
and 0 < (length(attachments)) < 3
and (
  // body text is very short
  (
    0 <= (length(body.current_thread.text)) < 10
    or body.current_thread.text is null
  )
  or (
    length(body.current_thread.text) < 900
    // or body is most likely all warning banner (text contains the sender and common warning banner language)
    and (
      (
        strings.contains(body.current_thread.text, sender.email.email)
        and strings.contains(body.current_thread.text, 'caution')
      )
      or regex.icontains(body.current_thread.text,
                         "intended recipient's use only|external email|sent from outside|you don't often"
      )
    )
  )
)
and (
  all(attachments,
      (.file_type in $file_types_images)
      and (
        any(file.explode(.),
            any(.scan.exiftool.fields, .value == "Truncated PNG image")
            or (
              any(ml.logo_detect(..).brands, .name is not null)
              and any(ml.nlu_classifier(.scan.ocr.raw).intents,
                      .name == "cred_theft" and .confidence == "high"
              )
            )
        )
      )
  )
)

Detection Logic

Scope: inbound message.

This rule identifies incoming messages with minimal links, all image attachments and either empty, brief or the body text is only a warning banner/disclaimer. It also checks for truncated PNG images or logos in addition to high-confidence credit theft intentions.

  1. inbound message
  2. length(body.links) < 2
  3. all of:
    • (0) < ((length(attachments)))
    • ((length(attachments))) < (3)
  4. any of:
    • any of:
      • all of:
        • (0) <= ((length(body.current_thread.text)))
        • ((length(body.current_thread.text))) < (10)
      • body.current_thread.text is missing
    • all of:
      • length(body.current_thread.text) < 900
      • any of:
        • all of:
          • strings.contains(body.current_thread.text, sender.email.email)
          • body.current_thread.text contains 'caution'
        • body.current_thread.text matches "intended recipient's use only|external email|sent from outside|you don't often"
  5. all of attachments where all hold:
    • .file_type in $file_types_images
    • ( any(file.explode(.), any(.scan.exiftool.fields, .value == "Truncated PNG image") or ( any(ml.logo_detect(..).brands, .name is not null) and any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence == "high" ) ) ) )

Inspects: attachments[].file_type, body.current_thread.text, body.links, sender.email.email, type.inbound. Sensors: file.explode, ml.logo_detect, ml.nlu_classifier, regex.icontains, strings.contains. Reference lists: $file_types_images.

Indicators Matched (5)

FieldMatchValue
strings.containssubstringcaution
regex.icontainsregexintended recipient's use only|external email|sent from outside|you don't often
file.explode(attachments[])[].scan.exiftool.fields[].valueequalsTruncated PNG image
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      or
        and
          body.current_thread.text contains "caution"
          strings.contains func_call "strings.contains(body.current_thread.text, sender.email.email)"
        body.current_thread.text regex_match "intended recipient's use only|external email|sent from outside|you don't often"
      body.current_thread.text length_compare "900"
    and
      body.current_thread.text length_compare "0"
      body.current_thread.text length_compare "10"
    body.current_thread.text is_null
  attachments length_compare "0"
  attachments length_compare "3"
  body.links length_compare "2"
  type.inbound eq "true"
   macro "(\n  all(attachments,\n      (.file_type in $file_types_images)\n      and (\n        any(file.explode(.),\n            any(.scan.exiftool.fields, .value == \"Truncated PNG image\")\n            or (\n              any(ml.logo_detect(..).brands, .name is not null)\n              and any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                      .name == \"cred_theft\" and .confidence == \"high\"\n              )\n            )\n        )\n      )\n  )\n)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textcontains
  • caution corpus 3 (mql 3)
field:"body.current_thread.text" kind:contains value:"caution"
body.current_thread.textis_null
  • (no value, null check)
field:"body.current_thread.text" kind:is_null
body.current_thread.textregex_match
    • intended recipient's use only
    • external email
    • sent from outside
    • you don't often
field:"body.current_thread.text" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

EML attachment with credential theft language (unknown sender)

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

Identifies EML attachments that use credential theft language from unknown senders.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.html
  • headers
  • headers.auth_summary
  • headers.domains
  • recipients
  • recipients.to
  • sender.email
  • subject
  • type

Rule Body

type.inbound
// we don't look for links because it could be a QR code
and any(attachments,
        (.content_type == "message/rfc822" or .file_extension =~ "eml")
        and (
          // credential theft language in the attached EML
          any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents,
              .name == "cred_theft" and .confidence == "high"
          )
          // credential theft language in an attachment in the attached EML
          or any(file.parse_eml(.).attachments,
                 any(ml.nlu_classifier(beta.ocr(.).text).intents,
                     .name == "cred_theft" and .confidence == "high"
                 )
          )
        )
        and not strings.like(file.parse_eml(.).sender.email.local_part,
                             "*postmaster*",
                             "*mailer-daemon*",
                             "*administrator*"
        )
        // some systems attach the bounceback this way
        and not any(file.parse_eml(.).attachments,
                    .content_type in (
                      "message/delivery-status",
                      "message/feedback-report"
                    )
        )
        // negate Microsoft Dynamic Delivery
        and not (
          length(file.parse_eml(.).attachments) == 0
          and strings.icontains(file.parse_eml(.).body.current_thread.text,
                                "Your attachments are currently being scanned by Safe Attachments"
          )
        )
        // Mimecast Protection attached EMLs when replacing attachments
        and not (
          (
            strings.iends_with(.file_name, 'was removed from this message')
            or .file_name == "We found suspicious links"
            or .file_name == 'We sent you safe versions of your files'
          )
          and length(file.parse_eml(.).headers.hops) == 1
          and any(file.parse_eml(.).headers.hops[0].fields,
                  .name == "X-MC-System"
          )
          and any(file.parse_eml(.).headers.hops[0].fields,
                  .name == "Content-Type"
                  and strings.contains(.value, '; boundary="MCBoundary=_')
          )
        )
)
// exclude bounce backs & read receipts
and not strings.like(sender.email.local_part,
                     "*postmaster*",
                     "*mailer-daemon*",
                     "*administrator*"
)
and not regex.icontains(subject.subject, "^(undelivered|undeliverable|read:)")
and not any(attachments,
            .content_type in (
              "message/delivery-status",
              "message/feedback-report"
            )
)
// if the "References" is in the body of the message, it's probably a bounce
and not any(headers.references, strings.contains(body.html.display_text, .))
and (
  not profile.by_sender_email().solicited
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
  // sender address listed as a recipient
  or (
    length(recipients.to) == 1
    and sender.email.email in map(recipients.to, .email.email)
  )
)
and not profile.by_sender_email().any_messages_benign
// negate instances where proofpoint sends a review of a reported message via analyzer
and not (
  sender.email.email == "analyzer@analyzer.securityeducation.com"
  and any(headers.domains, .root_domain == "pphosted.com")
  and headers.auth_summary.spf.pass
  and headers.auth_summary.dmarc.pass
)

Detection Logic

Scope: inbound message.

Identifies EML attachments that use credential theft language from unknown senders.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension is 'eml'
    • any of:
      • any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents, .name == "cred_theft" and .confidence == "high" )
      • any(file.parse_eml(.).attachments, any(ml.nlu_classifier(beta.ocr(.).text).intents, .name == "cred_theft" and .confidence == "high" ) )
    • not:
      • strings.like(file.parse_eml(.).sender.email.local_part, "*postmaster*", "*mailer-daemon*", "*administrator*" )
    • not:
      • any(file.parse_eml(.).attachments, .content_type in ( "message/delivery-status", "message/feedback-report" ) )
    • not:
      • all of:
        • length(file.parse_eml(.).attachments) == 0
        • strings.icontains(file.parse_eml(.).body.current_thread.text, "Your attachments are currently being scanned by Safe Attachments" )
    • not:
      • all of:
        • any of:
          • .file_name ends with 'was removed from this message'
          • .file_name is 'We found suspicious links'
          • .file_name is 'We sent you safe versions of your files'
        • length(file.parse_eml(.).headers.hops) == 1
        • any(file.parse_eml(.).headers.hops[0].fields, .name == "X-MC-System" )
        • any(file.parse_eml(.).headers.hops[0].fields, .name == "Content-Type" and strings.contains(.value, '; boundary="MCBoundary=_') )
  3. not:
    • sender.email.local_part matches any of 3 patterns
      • *postmaster*
      • *mailer-daemon*
      • *administrator*
  4. not:
    • subject.subject matches '^(undelivered|undeliverable|read:)'
  5. not:
    • any of attachments where:
      • .content_type in ('message/delivery-status', 'message/feedback-report')
  6. not:
    • any of headers.references where:
      • strings.contains(body.html.display_text, .)
  7. any of:
    • not:
      • profile.by_sender_email().solicited
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
    • all of:
      • length(recipients.to) == 1
      • sender.email.email in map(recipients.to, .email.email)
  8. not:
    • profile.by_sender_email().any_messages_benign
  9. not:
    • all of:
      • sender.email.email is 'analyzer@analyzer.securityeducation.com'
      • any of headers.domains where:
        • .root_domain is 'pphosted.com'
      • headers.auth_summary.spf.pass
      • headers.auth_summary.dmarc.pass

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_name, body.html.display_text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, headers.domains, headers.domains[].root_domain, headers.references, recipients.to, recipients.to[].email.email, sender.email.email, sender.email.local_part, subject.subject, type.inbound. Sensors: beta.ocr, file.parse_eml, ml.nlu_classifier, profile.by_sender_email, regex.icontains, strings.contains, strings.icontains, strings.iends_with, strings.like.

Indicators Matched (6)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionequalseml
ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].nameequalscred_theft
ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].confidenceequalshigh
ml.nlu_classifier(beta.ocr(file.parse_eml(attachments[]).attachments[]).text).intents[].nameequalscred_theft
ml.nlu_classifier(beta.ocr(file.parse_eml(attachments[]).attachments[]).text).intents[].confidenceequalshigh

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      not
        and
          or
            attachments.file_name ends_with "was removed from this message"
            attachments.file_name eq "We found suspicious links"
            attachments.file_name eq "We sent you safe versions of your files"
          length func_call "length(file.parse_eml(.).headers.hops) == 1"
           macro "any(file.parse_eml(.).headers.hops[0].fields,\n                  .name == \"Content-Type\"\n                  and strings.contains(.value, '; boundary=\"MCBoundary=_')\n          )"
           macro "any(file.parse_eml(.).headers.hops[0].fields,\n                  .name == \"X-MC-System\"\n          )"
      not
        and
          length func_call "length(file.parse_eml(.).attachments) == 0"
          strings.icontains func_call "strings.icontains(file.parse_eml(.).body.current_thread.text,\n                                \"Your attachments are currently being scanned by Safe Attachments\"\n          )"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
      not
        strings.like func_call "strings.like(file.parse_eml(.).sender.email.local_part,\n                             \"*postmaster*\",\n                             \"*mailer-daemon*\",\n                             \"*administrator*\"\n        )"
      not
         macro "any(file.parse_eml(.).attachments,\n                    .content_type in (\n                      \"message/delivery-status\",\n                      \"message/feedback-report\"\n                    )\n        )"
      or
         macro "any(file.parse_eml(.).attachments,\n                 any(ml.nlu_classifier(beta.ocr(.).text).intents,\n                     .name == \"cred_theft\" and .confidence == \"high\"\n                 )\n          )"
         macro "any(ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents,\n              .name == \"cred_theft\" and .confidence == \"high\"\n          )"
  not
    and
      any(headers.domains)
        headers.domains.root_domain eq "pphosted.com"
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.spf.pass eq "true"
      sender.email.email eq "analyzer@analyzer.securityeducation.com"
  or
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    not
      profile.by_sender_email func_call "profile.by_sender_email().solicited"
    and
      recipients.to length_compare "1"
      sender.email.email macro "sender.email.email in map(recipients.to, .email.email)"
  not
    any(attachments)
      attachments.content_type in ["message/delivery-status", "message/feedback-report"]
  not
    or
      sender.email.local_part match "administrator"
      sender.email.local_part match "mailer-daemon"
      sender.email.local_part match "postmaster"
  not
    any(headers.references)
      strings.contains func_call "strings.contains(body.html.display_text, .)"
  not
    profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
  not
    subject.subject regex_match "^(undelivered|undeliverable|read:)"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.domainsarray_any(no value, null check)excludes:headers.domains
headers.auth_summary.dmarc.passeqtrueexcludes:headers.auth_summary.dmarc.pass field:"headers.auth_summary.dmarc.pass" value:"true"
headers.auth_summary.spf.passeqtrueexcludes:headers.auth_summary.spf.pass field:"headers.auth_summary.spf.pass" value:"true"
sender.email.emaileqanalyzer@analyzer.securityeducation.comexcludes:sender.email.email field:"sender.email.email" value:"analyzer@analyzer.securityeducation.com"
attachmentsarray_any(no value, null check)excludes:attachments
sender.email.local_partmatchadministratorexcludes:sender.email.local_part field:"sender.email.local_part" value:"administrator"
sender.email.local_partmatchmailer-daemonexcludes:sender.email.local_part field:"sender.email.local_part" value:"mailer-daemon"
sender.email.local_partmatchpostmasterexcludes:sender.email.local_part field:"sender.email.local_part" value:"postmaster"
headers.referencesarray_any(no value, null check)excludes:headers.references
subject.subjectregex_match^(undelivered|undeliverable|read:)excludes:subject.subject field:"subject.subject" value:"^(undelivered|undeliverable|read:)"

Encrypted Microsoft Office files from untrusted sender

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

Detects encrypted Microsoft Office document attachments (Word, Excel, PowerPoint, Access) from untrusted senders or high-trust senders failing DMARC authentication, which may indicate an effort to bypass security scanning.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud, Callback Phishing, Credential Phishing, Extortion, Malware/Ransomware, Spam
Tactics and techniquesEncryption, Evasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.hops
  • sender.email
  • type

Rule Body

type.inbound
and any(attachments,
        (
          // Word documents
          strings.iends_with(.file_name, ".doc")
          or strings.iends_with(.file_name, ".docx")
          or strings.iends_with(.file_name, ".docm")
          or .content_type == "application/msword"
          or .content_type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
          or .file_type in ("doc", "docx")
          or 

          // Excel documents
          strings.iends_with(.file_name, ".xls")
          or strings.iends_with(.file_name, ".xlsx")
          or strings.iends_with(.file_name, ".xlsm")
          or .content_type == "application/vnd.ms-excel"
          or .content_type == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
          or .file_type in ("xls", "xlsx")
          or 

          // PowerPoint documents
          strings.iends_with(.file_name, ".ppt")
          or strings.iends_with(.file_name, ".pptx")
          or strings.iends_with(.file_name, ".pptm")
          or .content_type == "application/vnd.ms-powerpoint"
          or .content_type == "application/vnd.openxmlformats-officedocument.presentationml.presentation"
          or .file_type in ("ppt", "pptx")
          or 

          // Access documents
          strings.iends_with(.file_name, ".accdb")
          or strings.iends_with(.file_name, ".mdb")
          or .content_type == "application/msaccess"
          or .content_type == "application/x-msaccess"
          or .content_type == "application/vnd.ms-access"
        )
        and any(file.explode(.),
                any(.scan.yara.matches, .name == 'aes_encryption_keywords')
        )
)
// Negating high-trust sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and (
      any(distinct(headers.hops, .authentication_results.dmarc is not null),
          strings.ilike(.authentication_results.dmarc, "*fail")
      )
    )
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

Detects encrypted Microsoft Office document attachments (Word, Excel, PowerPoint, Access) from untrusted senders or high-trust senders failing DMARC authentication, which may indicate an effort to bypass security scanning.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_name ends with '.doc'
      • .file_name ends with '.docx'
      • .file_name ends with '.docm'
      • .content_type is 'application/msword'
      • .content_type is 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
      • .file_type in ('doc', 'docx')
      • .file_name ends with '.xls'
      • .file_name ends with '.xlsx'
      • .file_name ends with '.xlsm'
      • .content_type is 'application/vnd.ms-excel'
      • .content_type is 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      • .file_type in ('xls', 'xlsx')
      • .file_name ends with '.ppt'
      • .file_name ends with '.pptx'
      • .file_name ends with '.pptm'
      • .content_type is 'application/vnd.ms-powerpoint'
      • .content_type is 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
      • .file_type in ('ppt', 'pptx')
      • .file_name ends with '.accdb'
      • .file_name ends with '.mdb'
      • .content_type is 'application/msaccess'
      • .content_type is 'application/x-msaccess'
      • .content_type is 'application/vnd.ms-access'
    • any(file.explode(.), any(.scan.yara.matches, .name == 'aes_encryption_keywords') )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • ( any(distinct(headers.hops, .authentication_results.dmarc is not null), strings.ilike(.authentication_results.dmarc, "*fail") ) )
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_type, attachments[].file_name, attachments[].file_type, headers.hops, headers.hops[].authentication_results.dmarc, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, strings.iends_with, strings.ilike. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (28)

FieldMatchValue
strings.iends_withsuffix.doc
strings.iends_withsuffix.docx
strings.iends_withsuffix.docm
attachments[].content_typeequalsapplication/msword
attachments[].content_typeequalsapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
attachments[].file_typememberdoc
attachments[].file_typememberdocx
strings.iends_withsuffix.xls
strings.iends_withsuffix.xlsx
strings.iends_withsuffix.xlsm
attachments[].content_typeequalsapplication/vnd.ms-excel
attachments[].content_typeequalsapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
16 more
attachments[].file_typememberxls
attachments[].file_typememberxlsx
strings.iends_withsuffix.ppt
strings.iends_withsuffix.pptx
strings.iends_withsuffix.pptm
attachments[].content_typeequalsapplication/vnd.ms-powerpoint
attachments[].content_typeequalsapplication/vnd.openxmlformats-officedocument.presentationml.presentation
attachments[].file_typememberppt
attachments[].file_typememberpptx
strings.iends_withsuffix.accdb
strings.iends_withsuffix.mdb
attachments[].content_typeequalsapplication/msaccess
attachments[].content_typeequalsapplication/x-msaccess
attachments[].content_typeequalsapplication/vnd.ms-access
file.explode(attachments[])[].scan.yara.matches[].nameequalsaes_encryption_keywords
strings.ilikesubstring*fail

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "application/msaccess"
        attachments.content_type eq "application/msword"
        attachments.content_type eq "application/vnd.ms-access"
        attachments.content_type eq "application/vnd.ms-excel"
        attachments.content_type eq "application/vnd.ms-powerpoint"
        attachments.content_type eq "application/vnd.openxmlformats-officedocument.presentationml.presentation"
        attachments.content_type eq "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        attachments.content_type eq "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        attachments.content_type eq "application/x-msaccess"
        attachments.file_name ends_with ".accdb"
        attachments.file_name ends_with ".doc"
        attachments.file_name ends_with ".docm"
        attachments.file_name ends_with ".docx"
        attachments.file_name ends_with ".mdb"
        attachments.file_name ends_with ".ppt"
        attachments.file_name ends_with ".pptm"
        attachments.file_name ends_with ".pptx"
        attachments.file_name ends_with ".xls"
        attachments.file_name ends_with ".xlsm"
        attachments.file_name ends_with ".xlsx"
        attachments.file_type in ["doc", "docx"]
        attachments.file_type in ["ppt", "pptx"]
        attachments.file_type in ["xls", "xlsx"]
       macro "any(file.explode(.),\n                any(.scan.yara.matches, .name == 'aes_encryption_keywords')\n        )"
  or
    and
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
       macro "(\n      any(distinct(headers.hops, .authentication_results.dmarc is not null),\n          strings.ilike(.authentication_results.dmarc, \"*fail\")\n      )\n    )"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  type.inbound eq "true"

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"

Extortion / Sextortion - PDF attachment leveraging breach data from freemail sender

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

Detects sextortion attempts leveraging breach data, including names, addresses, phone numbers and frequently using Google Maps/Bing Maps streetview images to bolster confidence and fear.

Threat Classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesFree email provider, PDF, Social engineering, QR code

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • sender.email
  • subject
  • type

Rule Body

type.inbound

// sender is a freemail domain
and sender.email.domain.root_domain in $free_email_providers

// attachment filename is the same as the subject
and any(attachments,
        (
          strings.ilevenshtein(strings.concat(subject.subject,
                                              ".",
                                              .file_extension
                               ),
                               .file_name
          ) <= 1
        )
        or strings.contains(.file_name, subject.subject)
)

// body contains a US address, or the body is the subject
and (
  regex.icontains(body.current_thread.text,
                  '\d+\s[\w\s.]+(?:\n)?[\w\s]+\s[A-Z]{2}\s\d{5}(?:-\d{4})?(?:\n)?|\d+\s[\w\s.]+(?:Street|St|Avenue|Ave|Boulevard|Blvd|Road|Rd|Drive|Dr|Lane|Ln|Court|Ct|Way|Place|Pl|Terrace|Ter|Circle|Cir|Parkway|Pkwy|Trail|Trl|Highway|Hwy|Loop)\b\.?',
                  // a Canadian address
                  '\d+\s[\w\s.]+(?:\n)?[\w\s]+\s((?:Ontario|ON)|(?:Quebec|QC)|(?:Nova Scotia|NS)|(?:New Brunswick|NB)|(?:Manitoba|MB)|(?:British Columbia|BC)|(?:Prince Edward Island|PEI?)|(?:Saskatchewan|SK)|(?:Alberta|AB)|(?:Newfoundland and Labrador|NL)|(?:Yukon|YT)|(?:Northwest Territories|NT)|(?:Nunavut|NU))\s*[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d'
  )
  or subject.subject == body.current_thread.text
)

// there's a PDF attachment with an image at a depth of one, measuring 148x148 and containing a QR code that is a BTC address
and any(attachments,
        .file_type == "pdf"
        and any(file.explode(.),
                (
                  (.depth == 1 and .flavors.mime == "image/jpeg")
                  and (
                    .scan.exiftool.image_height == 148
                    and .scan.exiftool.image_width == 148
                    and regex.match(.scan.qr.data,
                                    '(1[a-km-zA-HJ-NP-Z1-9]{25,34}|3[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qp-z0-9]{39,59})'
                    )
                  )
                )
                or (
                  any(.scan.strings.strings,
                      regex.icontains(.,
                                      'Amount(?:\s*\w+){0,3}\s*:?\s*(?:USD\s*)?(?:\$\s?\d+|\d+\s?\$?)'
                      )
                  )
                  and any(.scan.strings.strings,
                          regex.icontains(.,
                                          '(\bBITCOIN\b|\bBTC\b|\bLTC\b|Wallet)'
                          )
                  )
                )
        )
)

Detection Logic

Scope: inbound message.

Detects sextortion attempts leveraging breach data, including names, addresses, phone numbers and frequently using Google Maps/Bing Maps streetview images to bolster confidence and fear.

  1. inbound message
  2. sender.email.domain.root_domain in $free_email_providers
  3. any of attachments where any holds:
    • ( strings.ilevenshtein(strings.concat(subject.subject, ".", .file_extension ), .file_name ) <= 1 )
    • strings.contains(.file_name, subject.subject)
  4. any of:
    • body.current_thread.text matches any of 2 patterns
      • \d+\s[\w\s.]+(?:\n)?[\w\s]+\s[A-Z]{2}\s\d{5}(?:-\d{4})?(?:\n)?|\d+\s[\w\s.]+(?:Street|St|Avenue|Ave|Boulevard|Blvd|Road|Rd|Drive|Dr|Lane|Ln|Court|Ct|Way|Place|Pl|Terrace|Ter|Circle|Cir|Parkway|Pkwy|Trail|Trl|Highway|Hwy|Loop)\b\.?
      • \d+\s[\w\s.]+(?:\n)?[\w\s]+\s((?:Ontario|ON)|(?:Quebec|QC)|(?:Nova Scotia|NS)|(?:New Brunswick|NB)|(?:Manitoba|MB)|(?:British Columbia|BC)|(?:Prince Edward Island|PEI?)|(?:Saskatchewan|SK)|(?:Alberta|AB)|(?:Newfoundland and Labrador|NL)|(?:Yukon|YT)|(?:Northwest Territories|NT)|(?:Nunavut|NU))\s*[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d
    • subject.subject is body.current_thread.text
  5. any of attachments where all hold:
    • .file_type is 'pdf'
    • any(file.explode(.), ( (.depth == 1 and .flavors.mime == "image/jpeg") and ( .scan.exiftool.image_height == 148 and .scan.exiftool.image_width == 148 and regex.match(.scan.qr.data, '(1[a-km-zA-HJ-NP-Z1-9]{25,34}|3[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qp-z0-9]{39,59})' ) ) ) or ( any(.scan.strings.strings, regex.icontains(., 'Amount(?:\s*\w+){0,3}\s*:?\s*(?:USD\s*)?(?:\$\s?\d+|\d+\s?\$?)' ) ) and any(.scan.strings.strings, regex.icontains(., '(\bBITCOIN\b|\bBTC\b|\bLTC\b|Wallet)' ) ) ) )

Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, body.current_thread.text, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, regex.icontains, regex.match, strings.concat, strings.contains, strings.ilevenshtein. Reference lists: $free_email_providers.

Indicators Matched (7)

FieldMatchValue
regex.icontainsregex\d+\s[\w\s.]+(?:\n)?[\w\s]+\s[A-Z]{2}\s\d{5}(?:-\d{4})?(?:\n)?|\d+\s[\w\s.]+(?:Street|St|Avenue|Ave|Boulevard|Blvd|Road|Rd|Drive|Dr|Lane|Ln|Court|Ct|Way|Place|Pl|Terrace|Ter|Circle|Cir|Parkway|Pkwy|Trail|Trl|Highway|Hwy|Loop)\b\.?
regex.icontainsregex\d+\s[\w\s.]+(?:\n)?[\w\s]+\s((?:Ontario|ON)|(?:Quebec|QC)|(?:Nova Scotia|NS)|(?:New Brunswick|NB)|(?:Manitoba|MB)|(?:British Columbia|BC)|(?:Prince Edward Island|PEI?)|(?:Saskatchewan|SK)|(?:Alberta|AB)|(?:Newfoundland and Labrador|NL)|(?:Yukon|YT)|(?:Northwest Territories|NT)|(?:Nunavut|NU))\s*[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d
attachments[].file_typeequalspdf
file.explode(attachments[])[].flavors.mimeequalsimage/jpeg
regex.matchregex(1[a-km-zA-HJ-NP-Z1-9]{25,34}|3[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qp-z0-9]{39,59})
regex.icontainsregexAmount(?:\s*\w+){0,3}\s*:?\s*(?:USD\s*)?(?:\$\s?\d+|\d+\s?\$?)
regex.icontainsregex(\bBITCOIN\b|\bBTC\b|\bLTC\b|Wallet)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type eq "pdf"
       macro "any(file.explode(.),\n                (\n                  (.depth == 1 and .flavors.mime == \"image/jpeg\")\n                  and (\n                    .scan.exiftool.image_height == 148\n                    and .scan.exiftool.image_width == 148\n                    and regex.match(.scan.qr.data,\n                                    '(1[a-km-zA-HJ-NP-Z1-9]{25,34}|3[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qp-z0-9]{39,59})'\n                    )\n                  )\n                )\n                or (\n                  any(.scan.strings.strings,\n                      regex.icontains(.,\n                                      'Amount(?:\\s*\\w+){0,3}\\s*:?\\s*(?:USD\\s*)?(?:\\$\\s?\\d+|\\d+\\s?\\$?)'\n                      )\n                  )\n                  and any(.scan.strings.strings,\n                          regex.icontains(.,\n                                          '(\\bBITCOIN\\b|\\bBTC\\b|\\bLTC\\b|Wallet)'\n                          )\n                  )\n                )\n        )"
  any(attachments)
    or
      strings.contains func_call "strings.contains(.file_name, subject.subject)"
      strings.ilevenshtein func_call "(\n          strings.ilevenshtein(strings.concat(subject.subject,\n                                              \".\",\n                                              .file_extension\n                               ),\n                               .file_name\n          ) <= 1\n        )"
  or
    body.current_thread.text regex_match "\\d+\\s[\\w\\s.]+(?:\\n)?[\\w\\s]+\\s((?:Ontario|ON)|(?:Quebec|QC)|(?:Nova Scotia|NS)|(?:New Brunswick|NB)|(?:Manitoba|MB)|(?:British Columbia|BC)|(?:Prince Edward Island|PEI?)|(?:Saskatchewan|SK)|(?:Alberta|AB)|(?:Newfoundland and Labrador|NL)|(?:Yukon|YT)|(?:Northwest Territories|NT)|(?:Nunavut|NU))\\s*[ABCEGHJ-NPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z][ -]?\\d[ABCEGHJ-NPRSTV-Z]\\d"
    body.current_thread.text regex_match "\\d+\\s[\\w\\s.]+(?:\\n)?[\\w\\s]+\\s[A-Z]{2}\\s\\d{5}(?:-\\d{4})?(?:\\n)?|\\d+\\s[\\w\\s.]+(?:Street|St|Avenue|Ave|Boulevard|Blvd|Road|Rd|Drive|Dr|Lane|Ln|Court|Ct|Way|Place|Pl|Terrace|Ter|Circle|Cir|Parkway|Pkwy|Trail|Trl|Highway|Hwy|Loop)\\b\\.?"
    subject.subject cross_field_compare "body.current_thread.text"
  sender.email.domain.root_domain macro "sender.email.domain.root_domain in free_email_providers"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.current_thread.textregex_match
  • \d+\s[\w\s.]+(?:\n)?[\w\s]+\s((?:Ontario|ON)|(?:Quebec|QC)|(?:Nova Scotia|NS)|(?:New Brunswick|NB)|(?:Manitoba|MB)|(?:British Columbia|BC)|(?:Prince Edward Island|PEI?)|(?:Saskatchewan|SK)|(?:Alberta|AB)|(?:Newfoundland and Labrador|NL)|(?:Yukon|YT)|(?:Northwest Territories|NT)|(?:Nunavut|NU))\s*[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d
    • \d+\s[\w\s.]+(?:\n)?[\w\s]+\s[A-Z]{2}\s\d{5}(?:-\d{4})?(?:\n)?
    • \d+\s[\w\s.]+(?:Street|St|Avenue|Ave|Boulevard|Blvd|Road|Rd|Drive|Dr|Lane|Ln|Court|Ct|Way|Place|Pl|Terrace|Ter|Circle|Cir|Parkway|Pkwy|Trail|Trl|Highway|Hwy|Loop)\b.?
field:"body.current_thread.text" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Extortion / sextortion in attachment from untrusted sender

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

Detects extortion and sextortion attempts by analyzing attachment text from an untrusted sender.

Threat Classification

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

CategoryValues
Attack typesExtortion
Tactics and techniquesSocial engineering, Spoofing

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.current_thread
  • body.html
  • body.links
  • headers
  • headers.hops
  • sender.email
  • type

Rule Body

type.inbound
and length(attachments) < 2
and (
  length(body.current_thread.text) < 500
  or (
    length(ml.nlu_classifier(body.current_thread.text).intents) > 0
    and any(ml.nlu_classifier(body.current_thread.text).intents,
            .name != "benign"
    )
  )
  or regex.icontains(body.html.raw, '<img[^>]+src="cid:')
)
and any(attachments,
        // use ocr output from file.explode on pdfs/images
        (
          (.file_type in $file_types_images or .file_type == "pdf")
          and any(filter(file.explode(.), .scan.ocr.raw is not null),
                  (
                    any(ml.nlu_classifier(.scan.ocr.raw).intents,
                        .name == "extortion" and .confidence == "high"
                    )
                    and any(ml.nlu_classifier(.scan.ocr.raw).entities,
                            .name == "financial"
                    )
                  )
                  or 3 of (
                    // malware terms
                    regex.icontains(.scan.ocr.raw,
                                    "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))"
                    ),
                    // actions recorded
                    regex.icontains(.scan.ocr.raw,
                                    "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off"
                    ),
                    regex.icontains(.scan.ocr.raw,
                                    "pervert|perversion|masturbat"
                    ),
                    // a timeframe to pay
                    regex.icontains(.scan.ocr.raw,
                                    '\d\d hours',
                                    '(?:one|two|three) days?'
                    ),
                    // a promise from the actor
                    regex.icontains(.scan.ocr.raw,
                                    'permanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)'
                    ),
                    // a threat from the actor
                    regex.icontains(.scan.ocr.raw,
                                    'sen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)'
                    ),
                    // bitcoin
                    (
                      regex.icontains(.scan.ocr.raw,
                                      'bitcoin|\bbtc\b|blockchain'
                      )
                      // negate cryptocurrency newsletters
                      and not (
                        any(body.links,
                            strings.icontains(.display_text, "unsubscribe")
                            and (
                              strings.icontains(.href_url.path, "unsubscribe")
                              // handle mimecast URL rewrites
                              or (
                                .href_url.domain.root_domain == 'mimecastprotect.com'
                                and strings.icontains(.href_url.query_params,
                                                      sender.email.domain.root_domain
                                )
                              )
                            )
                        )
                      )
                    ),
                    // bitcoin wallet address + threat
                    (
                      strings.icontains(.scan.ocr.raw, "contact the police")
                      and regex.icontains(.scan.ocr.raw,
                                          '(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\b)|\bX[1-9A-HJ-NP-Za-km-z]{33}\b|\b(0x[a-fA-F0-9]{40})\b|\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\b|\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\b'
                      )
                    ),
                    regex.icontains(.scan.ocr.raw, 'bc1q.{0,50}\b')
                  )
          )
        )
        or 
        // use file.parse_text on plain text files
        (
          (
            .file_extension in ("txt")
            and (
              (
                any(ml.nlu_classifier(file.parse_text(.).text).intents,
                    .name == "extortion" and .confidence == "high"
                )
                and any(ml.nlu_classifier(file.parse_text(.).text).entities,
                        .name == "financial"
                )
              )
              or 3 of (
                // malware terms
                regex.icontains(file.parse_text(.).text,
                                "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))"
                ),
                // actions recorded
                regex.icontains(file.parse_text(.).text,
                                "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off"
                ),
                regex.icontains(file.parse_text(.).text,
                                "pervert|perversion|masturbat"
                ),
                // a timeframe to pay
                regex.icontains(file.parse_text(.).text,
                                '\d\d hours',
                                '(?:one|two|three) days?'
                ),
                // a promise from the actor
                regex.icontains(file.parse_text(.).text,
                                'permanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)'
                ),
                // a threat from the actor
                regex.icontains(file.parse_text(.).text,
                                'sen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)'
                ),
                // bitcoin
                (
                  regex.icontains(file.parse_text(.).text,
                                  'bitcoin|\bbtc\b|blockchain'
                  )
                  // negate cryptocurrency newsletters
                  and not (
                    any(body.links,
                        strings.icontains(.display_text, "unsubscribe")
                        and (
                          strings.icontains(.href_url.path, "unsubscribe")
                          // handle mimecast URL rewrites
                          or (
                            .href_url.domain.root_domain == 'mimecastprotect.com'
                            and strings.icontains(.href_url.query_params,
                                                  sender.email.domain.root_domain
                            )
                          )
                        )
                    )
                  )
                ),
                // bitcoin wallet address + threat
                (
                  strings.icontains(file.parse_text(.).text,
                                    "contact the police"
                  )
                  and regex.icontains(file.parse_text(.).text,
                                      '(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\b)|\bX[1-9A-HJ-NP-Za-km-z]{33}\b|\b(0x[a-fA-F0-9]{40})\b|\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\b|\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\b'
                  )
                ),
                regex.icontains(file.parse_text(.).text, 'bc1q.{0,50}\b')
              )
            )
          )
        )
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
  or any(headers.hops, any(.fields, .name == "X-Google-Group-Id"))

  // many extortion emails spoof sender domains and fail sender authentication
  or any(headers.hops,
         .authentication_results.dmarc == "fail"
         or .authentication_results.compauth.verdict not in ("pass", "softpass")
  )
)

Detection Logic

Scope: inbound message.

Detects extortion and sextortion attempts by analyzing attachment text from an untrusted sender.

  1. inbound message
  2. length(attachments) < 2
  3. any of:
    • length(body.current_thread.text) < 500
    • all of:
      • length(ml.nlu_classifier(body.current_thread.text).intents) > 0
      • any(ml.nlu_classifier(body.current_thread.text).intents, .name != "benign" )
    • body.html.raw matches '<img[^>]+src="cid:'
  4. any of attachments where any holds:
    • all of:
      • any of:
        • .file_type in $file_types_images
        • .file_type is 'pdf'
      • any(filter(file.explode(.), .scan.ocr.raw is not null), ( any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "extortion" and .confidence == "high" ) and any(ml.nlu_classifier(.scan.ocr.raw).entities, .name == "financial" ) ) or 3 of ( // malware terms regex.icontains(.scan.ocr.raw, "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))" ), // actions recorded regex.icontains(.scan.ocr.raw, "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off" ), regex.icontains(.scan.ocr.raw, "pervert|perversion|masturbat" ), // a timeframe to pay regex.icontains(.scan.ocr.raw, '\d\d hours', '(?:one|two|three) days?' ), // a promise from the actor regex.icontains(.scan.ocr.raw, 'permanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)' ), // a threat from the actor regex.icontains(.scan.ocr.raw, 'sen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)' ), // bitcoin ( regex.icontains(.scan.ocr.raw, 'bitcoin|\bbtc\b|blockchain' ) // negate cryptocurrency newsletters and not ( any(body.links, strings.icontains(.display_text, "unsubscribe") and ( strings.icontains(.href_url.path, "unsubscribe") // handle mimecast URL rewrites or ( .href_url.domain.root_domain == 'mimecastprotect.com' and strings.icontains(.href_url.query_params, sender.email.domain.root_domain ) ) ) ) ) ), // bitcoin wallet address + threat ( strings.icontains(.scan.ocr.raw, "contact the police") and regex.icontains(.scan.ocr.raw, '(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\b)|\bX[1-9A-HJ-NP-Za-km-z]{33}\b|\b(0x[a-fA-F0-9]{40})\b|\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\b|\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\b' ) ), regex.icontains(.scan.ocr.raw, 'bc1q.{0,50}\b') ) )
    • all of:
      • .file_extension in ('txt')
      • any of:
        • all of:
          • any(ml.nlu_classifier(file.parse_text(.).text).intents, .name == "extortion" and .confidence == "high" )
          • any(ml.nlu_classifier(file.parse_text(.).text).entities, .name == "financial" )
        • at least 3 of:
          • regex.icontains(file.parse_text(.).text, "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))" )
          • regex.icontains(file.parse_text(.).text, "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off" )
          • regex.icontains(file.parse_text(.).text, "pervert|perversion|masturbat" )
          • regex.icontains(file.parse_text(.).text, '\d\d hours', '(?:one|two|three) days?' )
          • regex.icontains(file.parse_text(.).text, 'permanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)' )
          • regex.icontains(file.parse_text(.).text, 'sen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)' )
          • all of:
            • regex.icontains(file.parse_text(.).text, 'bitcoin|\bbtc\b|blockchain' )
            • not:
              • any of body.links where all hold:
                • .display_text contains 'unsubscribe'
                • any of:
                  • .href_url.path contains 'unsubscribe'
                  • all of:
                    • .href_url.domain.root_domain is 'mimecastprotect.com'
                    • strings.icontains(.href_url.query_params, sender.email.domain.root_domain )
          • all of:
            • strings.icontains(file.parse_text(.).text, "contact the police" )
            • regex.icontains(file.parse_text(.).text, '(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\b)|\bX[1-9A-HJ-NP-Za-km-z]{33}\b|\b(0x[a-fA-F0-9]{40})\b|\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\b|\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\b' )
          • regex.icontains(file.parse_text(.).text, 'bc1q.{0,50}\b')
  5. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
    • any of headers.hops where:
      • any of .fields where:
        • .name is 'X-Google-Group-Id'
    • any of headers.hops where any holds:
      • .authentication_results.dmarc is 'fail'
      • .authentication_results.compauth.verdict not in ('pass', 'softpass')

Inspects: attachments[].file_extension, attachments[].file_type, body.current_thread.text, body.html.raw, body.links, body.links[].display_text, body.links[].href_url.domain.root_domain, body.links[].href_url.path, body.links[].href_url.query_params, headers.hops, headers.hops[].authentication_results.compauth.verdict, headers.hops[].authentication_results.dmarc, headers.hops[].fields, headers.hops[].fields[].name, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, file.parse_text, ml.nlu_classifier, profile.by_sender, regex.icontains, strings.icontains. Reference lists: $file_types_images.

Indicators Matched (22)

FieldMatchValue
regex.icontainsregex<img[^>]+src="cid:
attachments[].file_typeequalspdf
ml.nlu_classifier(filter(...)[].scan.ocr.raw).intents[].nameequalsextortion
ml.nlu_classifier(filter(...)[].scan.ocr.raw).intents[].confidenceequalshigh
ml.nlu_classifier(filter(...)[].scan.ocr.raw).entities[].nameequalsfinancial
regex.icontainsregex((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))
regex.icontainsregexporn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off
regex.icontainsregexpervert|perversion|masturbat
regex.icontainsregex\d\d hours
regex.icontainsregex(?:one|two|three) days?
regex.icontainsregexpermanently delete|destroy (?:\w+\s*){0,4} (?:data|evidence|videos?)
regex.icontainsregexsen[dt]\s*(?:\w+\s*){0,2}\s*to\s*(?:\w+\s*){0,3}\s*.{0,10}(contacts|media|family|friends)
10 more
regex.icontainsregexbitcoin|\bbtc\b|blockchain
strings.icontainssubstringcontact the police
regex.icontainsregex(\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\b)|\bX[1-9A-HJ-NP-Za-km-z]{33}\b|\b(0x[a-fA-F0-9]{40})\b|\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\b|\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\b
regex.icontainsregexbc1q.{0,50}\b
attachments[].file_extensionmembertxt
ml.nlu_classifier(file.parse_text(attachments[]).text).intents[].nameequalsextortion
ml.nlu_classifier(file.parse_text(attachments[]).text).intents[].confidenceequalshigh
ml.nlu_classifier(file.parse_text(attachments[]).text).entities[].nameequalsfinancial
headers.hops[].fields[].nameequalsX-Google-Group-Id
headers.hops[].authentication_results.dmarcequalsfail

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    or
      and
        or
          and
             macro "any(ml.nlu_classifier(file.parse_text(.).text).entities,\n                        .name == \"financial\"\n                )"
             macro "any(ml.nlu_classifier(file.parse_text(.).text).intents,\n                    .name == \"extortion\" and .confidence == \"high\"\n                )"
           macro "3 of (\n                // malware terms\n                regex.icontains(file.parse_text(.).text,\n                                \"((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))\"\n                ),\n                // actions recorded\n                regex.icontains(file.parse_text(.).text,\n                                \"porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off\"\n                ),\n                regex.icontains(file.parse_text(.).text,\n                                \"pervert|perversion|masturbat\"\n                ),\n                // a timeframe to pay\n                regex.icontains(file.parse_text(.).text,\n                                '\\d\\d hours',\n                                '(?:one|two|three) days?'\n                ),\n                // a promise from the actor\n                regex.icontains(file.parse_text(.).text,\n                                'permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)'\n                ),\n                // a threat from the actor\n                regex.icontains(file.parse_text(.).text,\n                                'sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)'\n                ),\n                // bitcoin\n                (\n                  regex.icontains(file.parse_text(.).text,\n                                  'bitcoin|\\bbtc\\b|blockchain'\n                  )\n                  // negate cryptocurrency newsletters\n                  and not (\n                    any(body.links,\n                        strings.icontains(.display_text, \"unsubscribe\")\n                        and (\n                          strings.icontains(.href_url.path, \"unsubscribe\")\n                          // handle mimecast URL rewrites\n                          or (\n                            .href_url.domain.root_domain == 'mimecastprotect.com'\n                            and strings.icontains(.href_url.query_params,\n                                                  sender.email.domain.root_domain\n                            )\n                          )\n                        )\n                    )\n                  )\n                ),\n                // bitcoin wallet address + threat\n                (\n                  strings.icontains(file.parse_text(.).text,\n                                    \"contact the police\"\n                  )\n                  and regex.icontains(file.parse_text(.).text,\n                                      '(\\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\\b)|\\bX[1-9A-HJ-NP-Za-km-z]{33}\\b|\\b(0x[a-fA-F0-9]{40})\\b|\\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\\b|\\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\\b'\n                  )\n                ),\n                regex.icontains(file.parse_text(.).text, 'bc1q.{0,50}\\b')\n              )"
        attachments.file_extension eq "txt"
      and
        or
          attachments.file_type eq "pdf"
          attachments.file_type macro "attachments[].file_type in file_types_images"
         macro "any(filter(file.explode(.), .scan.ocr.raw is not null),\n                  (\n                    any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                        .name == \"extortion\" and .confidence == \"high\"\n                    )\n                    and any(ml.nlu_classifier(.scan.ocr.raw).entities,\n                            .name == \"financial\"\n                    )\n                  )\n                  or 3 of (\n                    // malware terms\n                    regex.icontains(.scan.ocr.raw,\n                                    \"((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))\"\n                    ),\n                    // actions recorded\n                    regex.icontains(.scan.ocr.raw,\n                                    \"porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off\"\n                    ),\n                    regex.icontains(.scan.ocr.raw,\n                                    \"pervert|perversion|masturbat\"\n                    ),\n                    // a timeframe to pay\n                    regex.icontains(.scan.ocr.raw,\n                                    '\\d\\d hours',\n                                    '(?:one|two|three) days?'\n                    ),\n                    // a promise from the actor\n                    regex.icontains(.scan.ocr.raw,\n                                    'permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)'\n                    ),\n                    // a threat from the actor\n                    regex.icontains(.scan.ocr.raw,\n                                    'sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)'\n                    ),\n                    // bitcoin\n                    (\n                      regex.icontains(.scan.ocr.raw,\n                                      'bitcoin|\\bbtc\\b|blockchain'\n                      )\n                      // negate cryptocurrency newsletters\n                      and not (\n                        any(body.links,\n                            strings.icontains(.display_text, \"unsubscribe\")\n                            and (\n                              strings.icontains(.href_url.path, \"unsubscribe\")\n                              // handle mimecast URL rewrites\n                              or (\n                                .href_url.domain.root_domain == 'mimecastprotect.com'\n                                and strings.icontains(.href_url.query_params,\n                                                      sender.email.domain.root_domain\n                                )\n                              )\n                            )\n                        )\n                      )\n                    ),\n                    // bitcoin wallet address + threat\n                    (\n                      strings.icontains(.scan.ocr.raw, \"contact the police\")\n                      and regex.icontains(.scan.ocr.raw,\n                                          '(\\b[13][a-km-zA-HJ-NP-Z0-9]{24,33}\\b)|\\bX[1-9A-HJ-NP-Za-km-z]{33}\\b|\\b(0x[a-fA-F0-9]{40})\\b|\\b[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}\\b|\\b[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}\\b'\n                      )\n                    ),\n                    regex.icontains(.scan.ocr.raw, 'bc1q.{0,50}\\b')\n                  )\n          )"
  or
    any(headers.hops)
      or
        not
          headers.hops.authentication_results.compauth.verdict in ["pass", "softpass"]
        headers.hops.authentication_results.dmarc eq "fail"
    any(headers.hops)
      any(headers.hops.fields)
        headers.hops.fields.name eq "X-Google-Group-Id"
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  or
    and
      length func_call "length(ml.nlu_classifier(body.current_thread.text).intents) > 0"
       macro "any(ml.nlu_classifier(body.current_thread.text).intents,\n            .name != \"benign\"\n    )"
    body.current_thread.text length_compare "500"
    body.html.raw regex_match "<img[^>]+src=\"cid:"
  attachments length_compare "2"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
body.html.rawregex_match
  • <img[^>]+src="cid:
field:"body.html.raw" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Free subdomain link with credential theft indicators

#

HTML smuggling containing recipient email address

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

HTML attachment (or HTML attachment in attached email) is small and contains a recipients email address.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, HTML smuggling, Scripting

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • headers.hops
  • recipients
  • recipients.to
  • sender.email
  • type

Rule Body

type.inbound
and (
  any(attachments,
      (
        .file_extension in~ ("html", "htm", "shtml", "dhtml")
        or .content_type == "message/rfc822"
        or .file_type == "html"
        or (.content_type == "text/html" or .file_extension in ('eml'))
      )
      and any(file.explode(.),
              .size < 10000
              and length(.scan.strings.strings) < 20
              and any(recipients.to,
                      any(..scan.strings.strings,
                          strings.icontains(., ..email.email)
                      )
                      and .email.domain.valid
              )
      )
  )
  or any(attachments,
         (.file_extension in~ $file_extensions_common_archives)
         and any(file.explode(.),
                 (
                   .file_extension in~ ("html", "htm", "shtml", "dhtml")
                   or ..file_type == "html"
                   or ..content_type == "text/html"
                 )
                 and .size < 10000
                 and length(.scan.strings.strings) < 20
                 and any(recipients.to,
                         any(..scan.strings.strings,
                             strings.icontains(., ..email.email)
                         )
                         and .email.domain.valid
                 )
         )
  )
)
and not any(attachments,
            any(file.parse_eml(.).attachments,
                .content_type == "message/delivery-status"
            )
)
// bounce-back negations
and not (
  any(attachments,
      .content_type in ("message/delivery-status", "text/calendar")
  )
)
// negate bouncebacks from proofpoint
and not (
  sender.display_name == "Mail Delivery Subsystem"
  and strings.ends_with(headers.message_id, "pphosted.com>")
  and any(headers.hops,
          .index == 0 and strings.contains(.received.server.raw, "pphosted.com")
  )
  and any(attachments, .content_type == "message/rfc822")
)
// unsolicited or fails authentation
and (
  (
    profile.by_sender_email().prevalence in ("new", "outlier")
    and not profile.by_sender_email().solicited
  )
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
  or (
    sender.email.domain.domain in $org_domains
    and not coalesce(headers.auth_summary.dmarc.pass, false)
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not coalesce(headers.auth_summary.dmarc.pass, false)
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

Detection Logic

Scope: inbound message.

HTML attachment (or HTML attachment in attached email) is small and contains a recipients email address.

  1. inbound message
  2. any of:
    • any of attachments where all hold:
      • any of:
        • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
        • .content_type is 'message/rfc822'
        • .file_type is 'html'
        • any of:
          • .content_type is 'text/html'
          • .file_extension in ('eml')
      • any(file.explode(.), .size < 10000 and length(.scan.strings.strings) < 20 and any(recipients.to, any(..scan.strings.strings, strings.icontains(., ..email.email) ) and .email.domain.valid ) )
    • any of attachments where all hold:
      • .file_extension in $file_extensions_common_archives
      • any(file.explode(.), ( .file_extension in~ ("html", "htm", "shtml", "dhtml") or ..file_type == "html" or ..content_type == "text/html" ) and .size < 10000 and length(.scan.strings.strings) < 20 and any(recipients.to, any(..scan.strings.strings, strings.icontains(., ..email.email) ) and .email.domain.valid ) )
  3. not:
    • any of attachments where:
      • any(file.parse_eml(.).attachments, .content_type == "message/delivery-status" )
  4. not:
    • any of attachments where:
      • .content_type in ('message/delivery-status', 'text/calendar')
  5. not:
    • all of:
      • sender.display_name is 'Mail Delivery Subsystem'
      • headers.message_id ends with 'pphosted.com>'
      • any of headers.hops where all hold:
        • .index is 0
        • .received.server.raw contains 'pphosted.com'
      • any of attachments where:
        • .content_type is 'message/rfc822'
  6. any of:
    • all of:
      • profile.by_sender_email().prevalence in ("new", "outlier")
      • not:
        • profile.by_sender_email().solicited
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
    • all of:
      • sender.email.domain.domain in $org_domains
      • not:
        • coalesce(headers.auth_summary.dmarc.pass, false)
  7. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • coalesce(headers.auth_summary.dmarc.pass, false)
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].index, headers.hops[].received.server.raw, headers.message_id, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, sender.display_name, sender.email.domain.domain, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, file.parse_eml, profile.by_sender_email, strings.contains, strings.ends_with, strings.icontains. Reference lists: $file_extensions_common_archives, $high_trust_sender_root_domains, $org_domains.

Indicators Matched (12)

FieldMatchValue
attachments[].file_extensionmemberhtml
attachments[].file_extensionmemberhtm
attachments[].file_extensionmembershtml
attachments[].file_extensionmemberdhtml
attachments[].content_typeequalsmessage/rfc822
attachments[].file_typeequalshtml
attachments[].content_typeequalstext/html
attachments[].file_extensionmembereml
file.explode(attachments[])[].file_extensionmemberhtml
file.explode(attachments[])[].file_extensionmemberhtm
file.explode(attachments[])[].file_extensionmembershtml
file.explode(attachments[])[].file_extensionmemberdhtml

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        or
          attachments.content_type eq "message/rfc822"
          attachments.content_type eq "text/html"
          attachments.file_extension eq "eml"
          attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
          attachments.file_type eq "html"
         macro "any(file.explode(.),\n              .size < 10000\n              and length(.scan.strings.strings) < 20\n              and any(recipients.to,\n                      any(..scan.strings.strings,\n                          strings.icontains(., ..email.email)\n                      )\n                      and .email.domain.valid\n              )\n      )"
    any(attachments)
      and
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
         macro "any(file.explode(.),\n                 (\n                   .file_extension in~ (\"html\", \"htm\", \"shtml\", \"dhtml\")\n                   or ..file_type == \"html\"\n                   or ..content_type == \"text/html\"\n                 )\n                 and .size < 10000\n                 and length(.scan.strings.strings) < 20\n                 and any(recipients.to,\n                         any(..scan.strings.strings,\n                             strings.icontains(., ..email.email)\n                         )\n                         and .email.domain.valid\n                 )\n         )"
  or
    and
      not
        and
          headers.auth_summary.dmarc.pass eq "true"
          headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.domain macro "sender.email.domain.domain in org_domains"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().solicited"
      profile.by_sender_email func_call "profile.by_sender_email().prevalence in (\"new\", \"outlier\")"
  or
    and
      not
        and
          headers.auth_summary.dmarc.pass eq "true"
          headers.auth_summary.dmarc.pass is_not_null
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    and
      any(headers.hops)
        and
          headers.hops.index eq "0"
          headers.hops.received.server.raw contains "pphosted.com"
      any(attachments)
        attachments.content_type eq "message/rfc822"
      headers.message_id ends_with "pphosted.com>"
      sender.display_name eq "Mail Delivery Subsystem"
  not
    any(attachments)
      attachments.content_type in ["message/delivery-status", "text/calendar"]
  not
    any(attachments)
       macro "any(file.parse_eml(.).attachments,\n                .content_type == \"message/delivery-status\"\n            )"
  type.inbound eq "true"

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"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops
attachmentsarray_any(no value, null check)excludes:attachments
headers.message_idends_withpphosted.com>excludes:headers.message_id field:"headers.message_id" value:"pphosted.com>"
sender.display_nameeqMail Delivery Subsystemexcludes:sender.display_name field:"sender.display_name" value:"Mail Delivery Subsystem"

Impersonation: Fake Gmail attachment

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

Message detects fake Gmail attachments by inspecting the body of a message for elements found within Gmail's user interface for attachment. In expected use, these elements only appears within the gmail WebUI and not within the body of message. The presence of this within message indicates a fake attachment.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • body
  • body.current_thread
  • body.html
  • body.links
  • body.plain
  • headers
  • headers.auth_summary
  • sender.email
  • type

Rule Body

type.inbound
and any([body.html.display_text, body.current_thread.text, body.plain.raw],
        length(.) < 2500
        and (
          strings.icontains(., 'Scanned by Gmail')
          or (
            0 < regex.icount(., '\.pdf|\.(doc|xls|ppt)x?') < 3
            and any(body.links,
                    regex.icontains(.display_text, 'd[ao0]wnl[ao0]{2}d all')
            )
            and length(body.links) < 4
          )
        )
        and regex.icontains(.,
                            '[KM]b\b'
        ) // file size
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
// if the sender has been marked as malicious, but has FPs, don't alert
and (
  (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
  or not profile.by_sender().any_messages_malicious_or_spam
)

Detection Logic

Scope: inbound message.

Message detects fake Gmail attachments by inspecting the body of a message for elements found within Gmail's user interface for attachment. In expected use, these elements only appears within the gmail WebUI and not within the body of message. The presence of this within message indicates a fake attachment.

  1. inbound message
  2. any([body.html.display_text, body.current_thread.text, body.plain.raw], length(.) < 2500 and ( strings.icontains(., 'Scanned by Gmail') or ( 0 < regex.icount(., '\.pdf|\.(doc|xls|ppt)x?') < 3 and any(body.links, regex.icontains(.display_text, 'd[ao0]wnl[ao0]{2}d all') ) and length(body.links) < 4 ) ) and regex.icontains(., '[KM]b\b' ) // file size )
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  4. any of:
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
    • not:
      • profile.by_sender().any_messages_malicious_or_spam

Inspects: body.current_thread.text, body.html.display_text, body.links, body.links[].display_text, body.plain.raw, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: profile.by_sender, regex.icontains, regex.icount, strings.icontains. Reference lists: $high_trust_sender_root_domains.

Indicators Matched (4)

FieldMatchValue
strings.icontainssubstringScanned by Gmail
regex.icountregex\.pdf|\.(doc|xls|ppt)x?
regex.icontainsregexd[ao0]wnl[ao0]{2}d all
regex.icontainsregex[KM]b\b

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
  type.inbound eq "true"
   macro "any([body.html.display_text, body.current_thread.text, body.plain.raw],\n        length(.) < 2500\n        and (\n          strings.icontains(., 'Scanned by Gmail')\n          or (\n            0 < regex.icount(., '\\.pdf|\\.(doc|xls|ppt)x?') < 3\n            and any(body.links,\n                    regex.icontains(.display_text, 'd[ao0]wnl[ao0]{2}d all')\n            )\n            and length(body.links) < 4\n          )\n        )\n        and regex.icontains(.,\n                            '[KM]b\\b'\n        ) // file size\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"

MalwareBazaar: Malicious attachment hash (trusted reporters)

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

Detects if an attachment's SHA256 hash matches a SHA256 hash reported as malware on MalwareBazaar by trusted reporters from untrusted senders.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .sha256 in $abuse_ch_malwarebazaar_sha256_trusted_reporters
)

Detection Logic

Scope: inbound message.

Detects if an attachment's SHA256 hash matches a SHA256 hash reported as malware on MalwareBazaar by trusted reporters from untrusted senders.

  1. inbound message
  2. any of attachments where:
    • .sha256 in $abuse_ch_malwarebazaar_sha256_trusted_reporters

Inspects: attachments[].sha256, type.inbound. Reference lists: $abuse_ch_malwarebazaar_sha256_trusted_reporters.

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    attachments.sha256 macro "attachments[].sha256 in abuse_ch_malwarebazaar_sha256_trusted_reporters"
  type.inbound eq "true"

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"

MalwareBazaar: Malicious attachment hash in archive (trusted reporters)

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

Detects if an arhive attachments contains a file that matches a SHA256 hash reported as malware on MalwareBazaar by trusted reporters.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesEvasion

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_extension in~ $file_extensions_common_archives
        and any(file.explode(.),
                .scan.hash.sha256 in $abuse_ch_malwarebazaar_sha256_trusted_reporters
        )
)

Detection Logic

Scope: inbound message.

Detects if an arhive attachments contains a file that matches a SHA256 hash reported as malware on MalwareBazaar by trusted reporters.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in $file_extensions_common_archives
    • any(file.explode(.), .scan.hash.sha256 in $abuse_ch_malwarebazaar_sha256_trusted_reporters )

Inspects: attachments[].file_extension, type.inbound. Sensors: file.explode. Reference lists: $abuse_ch_malwarebazaar_sha256_trusted_reporters, $file_extensions_common_archives.

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.),\n                .scan.hash.sha256 in $abuse_ch_malwarebazaar_sha256_trusted_reporters\n        )"
  type.inbound eq "true"

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"

Non-RFC compliant calendar files from unsolicited sender

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

Detects calendar (.ics) files that do not follow RFC standards by lacking required UID identifiers while containing specific calendar components (VTODO, VJOURNAL, VFREEBUSY, or VEVENT). Forged ICS calendar invites can be spoofed to seemingly originate from any sender.

Threat Classification

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

CategoryValues
Tactics and techniquesEvasion, ICS Phishing, Social engineering

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in $file_extensions_common_archives
          or .file_extension == "ics"
          or .content_type == "text/calendar"
        )
        and any(file.explode(.),
                (.file_extension == "ics" or .flavors.mime == "text/calendar")
                and any(.scan.ics.calendars,
                        any(.components,
                            .uid is null
                            and .type in (
                              'VEVENT',
                              'VJOURNAL',
                              'VFREEBUSY',
                              'VTODO'
                            )
                        )
                )
        )
)
and not profile.by_sender_email().any_messages_benign

Detection Logic

Scope: inbound message.

Detects calendar (.ics) files that do not follow RFC standards by lacking required UID identifiers while containing specific calendar components (VTODO, VJOURNAL, VFREEBUSY, or VEVENT). Forged ICS calendar invites can be spoofed to seemingly originate from any sender.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_common_archives
      • .file_extension is 'ics'
      • .content_type is 'text/calendar'
    • any(file.explode(.), (.file_extension == "ics" or .flavors.mime == "text/calendar") and any(.scan.ics.calendars, any(.components, .uid is null and .type in ( 'VEVENT', 'VJOURNAL', 'VFREEBUSY', 'VTODO' ) ) ) )
  3. not:
    • profile.by_sender_email().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: file.explode, profile.by_sender_email. Reference lists: $file_extensions_common_archives.

Indicators Matched (8)

FieldMatchValue
attachments[].file_extensionequalsics
attachments[].content_typeequalstext/calendar
file.explode(attachments[])[].file_extensionequalsics
file.explode(attachments[])[].flavors.mimeequalstext/calendar
file.explode(attachments[])[].scan.ics.calendars[].components[].typememberVEVENT
file.explode(attachments[])[].scan.ics.calendars[].components[].typememberVJOURNAL
file.explode(attachments[])[].scan.ics.calendars[].components[].typememberVFREEBUSY
file.explode(attachments[])[].scan.ics.calendars[].components[].typememberVTODO

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        attachments.content_type eq "text/calendar"
        attachments.file_extension eq "ics"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_common_archives"
       macro "any(file.explode(.),\n                (.file_extension == \"ics\" or .flavors.mime == \"text/calendar\")\n                and any(.scan.ics.calendars,\n                        any(.components,\n                            .uid is null\n                            and .type in (\n                              'VEVENT',\n                              'VJOURNAL',\n                              'VFREEBUSY',\n                              'VTODO'\n                            )\n                        )\n                )\n        )"
  not
    profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
  type.inbound eq "true"

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"

PDF attachment with Google (AE) redirecting to a php or zip file

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

Detects a PDF attachment with a link that contains a Google.ae redirect URL.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesOpen redirect, PDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        .file_type == "pdf"
        and any(file.explode(.),
                any(.scan.pdf.urls,
                    // url encoded q=http
                    strings.starts_with(.query_params, "q=%68%74%74%70")
                    // url encoded .php or .zip
                    and (
                      strings.contains(.query_params, ".%70%68%70")
                      or strings.contains(.query_params, "%2e%7a%69%70")
                    )
                    and .domain.root_domain == "google.ae"
                )
        )
)

Detection Logic

Scope: inbound message.

Detects a PDF attachment with a link that contains a Google.ae redirect URL.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • any(file.explode(.), any(.scan.pdf.urls, // url encoded q=http strings.starts_with(.query_params, "q=%68%74%74%70") // url encoded .php or .zip and ( strings.contains(.query_params, ".%70%68%70") or strings.contains(.query_params, "%2e%7a%69%70") ) and .domain.root_domain == "google.ae" ) )

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, strings.contains, strings.starts_with.

Indicators Matched (5)

FieldMatchValue
attachments[].file_typeequalspdf
strings.starts_withprefixq=%68%74%74%70
strings.containssubstring.%70%68%70
strings.containssubstring%2e%7a%69%70
file.explode(attachments[])[].scan.pdf.urls[].domain.root_domainequalsgoogle.ae

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      attachments.file_type eq "pdf"
       macro "any(file.explode(.),\n                any(.scan.pdf.urls,\n                    // url encoded q=http\n                    strings.starts_with(.query_params, \"q=%68%74%74%70\")\n                    // url encoded .php or .zip\n                    and (\n                      strings.contains(.query_params, \".%70%68%70\")\n                      or strings.contains(.query_params, \"%2e%7a%69%70\")\n                    )\n                    and .domain.root_domain == \"google.ae\"\n                )\n        )"
  type.inbound eq "true"

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"

Suspicious attachment with unscannable Cloudflare link

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

A PDF or Office document contains suspicious URLs that lead to Cloudflare-protected pages with turnstile CAPTCHA gates. The sender uses deceptive display names and subjects indicating urgency or authority.

Threat Classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, PDF, Social engineering, Impersonation: Employee, Impersonation: VIP

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • headers
  • headers.auth_summary
  • sender.email
  • subject
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in $file_extensions_macros
          or .file_extension == "pdf"
          or .file_type in ("pdf", "doc", "docx", "xls", "xlsx")
          or .content_type in ("application/pdf")
        )
        and any(file.explode(.),
                // few links
                0 < length(.scan.url.urls) < 20
                // fewer unique root domain links
                and length(distinct(.scan.url.urls, .domain.root_domain)) < 10
                // sender domain matches no body domains
                and all(.scan.url.urls,
                        .domain.root_domain != sender.email.domain.root_domain
                )
        )
)

// negate bouncebacks and undeliverables
and not any(attachments,
            .content_type in (
              "message/global-delivery-status",
              "message/delivery-status"
            )
)

// suspicious subject or display name
and (
  regex.icontains(subject.subject,
                  "termination.*notice",
                  "38417",
                  ":completed",
                  "[il1]{2}mit.*ma[il1]{2} ?bo?x",
                  "[il][il][il]egai[ -]",
                  "[li][li][li]ega[li] attempt",
                  "[ng]-?[io]n .*block",
                  "[ng]-?[io]n .*cancel",
                  "[ng]-?[io]n .*deactiv",
                  "[ng]-?[io]n .*disabl",
                  "action.*required",
                  "abandon.*package",
                  "about.your.account",
                  "acc(ou)?n?t (is )?on ho[li]d",
                  "acc(ou)?n?t.*terminat",
                  "acc(oun)?t.*[il1]{2}mitation",
                  "access.*limitation",
                  "account (will be )?block",
                  "account.*de-?activat",
                  "account.*locked",
                  "account.*re-verification",
                  "account.*security",
                  "account.*suspension",
                  "account.has.been",
                  "account.has.expired",
                  "account.will.be.blocked",
                  "account v[il]o[li]at",
                  "activity.*acc(oun)?t",
                  "almost.full",
                  "app[li]e.[il]d",
                  "authenticate.*account",
                  "been.*suspend",
                  "clos.*of.*account.*processed",
                  "confirm.your.account",
                  "courier.*able",
                  "crediential.*notif",
                  "deactivation.*in.*progress",
                  "delivery.*attempt.*failed",
                  "document.received",
                  "documented.*shared.*with.*you",
                  "dropbox.*document",
                  "e-?ma[il1]+ .{010}suspen",
                  "e-?ma[il1]{1} user",
                  "e-?ma[il1]{2} acc",
                  "e-?ma[il1]{2}.*up.?grade",
                  "e.?ma[il1]{2}.*server",
                  "e.?ma[il1]{2}.*suspend",
                  "email.update",
                  "faxed you",
                  "fraud(ulent)?.*charge",
                  "from.helpdesk",
                  "fu[il1]{2}.*ma[il1]+[ -]?box",
                  "has.been.*suspended",
                  "has.been.limited",
                  "have.locked",
                  "he[li]p ?desk upgrade",
                  "heipdesk",
                  "i[il]iega[il]",
                  "ii[il]ega[il]",
                  "incoming e?mail",
                  "incoming.*fax",
                  "lock.*security",
                  "ma[il1]{1}[ -]?box.*quo",
                  "ma[il1]{2}[ -]?box.*fu[il1]",
                  "ma[il1]{2}box.*[il1]{2}mit",
                  "ma[il1]{2}box stor",
                  "mail on.?hold",
                  "mail.*box.*migration",
                  "mail.*de-?activat",
                  "mail.update.required",
                  "mails.*pending",
                  "messages.*pending",
                  "missed.*shipping.*notification",
                  "missed.shipment.notification",
                  "must.update.your.account",
                  "new [sl][io]g?[nig][ -]?in from",
                  "new voice ?-?mail",
                  "notifications.*pending",
                  "office.*3.*6.*5.*suspend",
                  "office365",
                  "on google docs with you",
                  "online doc",
                  "password.*compromised",
                  "periodic maintenance",
                  "potential(ly)? unauthorized",
                  "refund not approved",
                  "report",
                  "revised.*policy",
                  "scam",
                  "scanned.?invoice",
                  "secured?.update",
                  "security breach",
                  "securlty",
                  "signed.*delivery",
                  "statement is ready",
                  "status of your .{314}? ?delivery",
                  "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty",
                  "suspicious.*sign.*[io]n",
                  "suspicious.activit",
                  "temporar(il)?y deactivate",
                  "temporar[il1]{2}y disab[li]ed",
                  "temporarily.*lock",
                  "un-?usua[li].activity",
                  "unable.*deliver",
                  "unauthorized.*activit",
                  "unauthorized.device",
                  "undelivered message",
                  "unread.*doc",
                  "unusual.activity",
                  "upgrade.*account",
                  "upgrade.notice",
                  "urgent message",
                  "urgent.verification",
                  "v[il1]o[li1]at[il1]on security",
                  "va[il1]{1}date.*ma[il1]{2}[ -]?box",
                  "verification ?-?require",
                  "verification( )?-?need",
                  "verify.your?.account",
                  "web ?-?ma[il1]{2}",
                  "web[ -]?ma[il1]{2}",
                  "will.be.suspended",
                  "your (customer )?account .as",
                  "your.office.365",
                  "your.online.access"
  )
  or any($suspicious_subjects, strings.icontains(subject.subject, .))
  or regex.icontains(sender.display_name,
                     "Admin",
                     "Administrator",
                     "Alert",
                     "Assistant",
                     "Billing",
                     "Benefits",
                     "Bonus",
                     "CEO",
                     "CFO",
                     "CIO",
                     "CTO",
                     "Chairman",
                     "Claim",
                     "Confirm",
                     "Critical",
                     "Customer Service",
                     "Deal",
                     "Discount",
                     "Director",
                     "Exclusive",
                     "Executive",
                     "Fax",
                     "Free",
                     "Gift",
                     "/bHR/b",
                     "Helpdesk",
                     "Human Resources",
                     "Immediate",
                     "Important",
                     "Info",
                     "Information",
                     "Invoice",
                     '\bIT\b',
                     "Legal",
                     "Lottery",
                     "Management",
                     "Manager",
                     "Member Services",
                     "Notification",
                     "Offer",
                     "Operations",
                     "Order",
                     "Partner",
                     "Payment",
                     "Payroll",
                     "President",
                     "Premium",
                     "Prize",
                     "Receipt",
                     "Refund",
                     "Registrar",
                     "Required",
                     "Reward",
                     "Sales",
                     "Secretary",
                     "Security",
                     "Service",
                     "Signature",
                     'SSA?\.gov',
                     "Storage",
                     "Support",
                     "Sweepstakes",
                     "System",
                     "Tax",
                     "Tech Support",
                     "Update",
                     "Upgrade",
                     "Urgent",
                     "Validate",
                     "Verify",
                     "VIP",
                     "Webmaster",
                     "Winner",
  )
  or any(attachments,
         (
           .file_extension in $file_extensions_macros
           or .file_extension == "pdf"
           or .file_type in ("pdf", "doc", "docx", "xls", "xlsx")
           or .content_type in ("application/pdf")
         )
         and any(file.explode(.),
                 any(.scan.url.urls, strings.ends_with(.url, ".exe"))
                 or any(ml.nlu_classifier(.scan.ocr.raw).intents,
                        .name == "cred_theft"
                 )
         )
  )
)
and any(attachments,
        (
          .file_extension in $file_extensions_macros
          or .file_extension == "pdf"
          or .file_type in ("pdf", "doc", "docx", "xls", "xlsx")
          or .content_type in ("application/pdf")
        )
        and any(file.explode(.),
                any(.scan.url.urls,
                    (
                      strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
                                        "cloudflare"
                      )
                      // includes the turnstile CAPTCHA
                      or (
                        strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
                                          'https://challenges.cloudflare.com/turnstile/'
                        )
                        // has a short body length indicating the page is gated behind the turnstile instead
                        // of just including the turnstile
                        and length((
                                     ml.link_analysis(., mode="aggressive").final_dom.display_text
                                   )
                        ) < 200
                      )
                    )
                    and not (
                      ( // a Cloudflare error page
                        strings.ilike(ml.link_analysis(., mode="aggressive").final_dom.display_text,
                                      "*error code*"
                        )
                        and any(ml.link_analysis(., mode="aggressive").final_dom.links,
                                strings.icontains(.href_url.query_params,
                                                  "utm_source=errorcode"
                                )
                        )
                      ) // a cookie warning mentioning Cloudflare
                      or regex.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
                                         "cookie.{0,50}Cloudflare"
                      )
                      or ml.link_analysis(., mode="aggressive").effective_url.domain.root_domain in (
                        "marketbeat.com"
                      )
                    )
                )
        )
)
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and not profile.by_sender().any_messages_benign

Detection Logic

Scope: inbound message.

A PDF or Office document contains suspicious URLs that lead to Cloudflare-protected pages with turnstile CAPTCHA gates. The sender uses deceptive display names and subjects indicating urgency or authority.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension is 'pdf'
      • .file_type in ('pdf', 'doc', 'docx', 'xls', 'xlsx')
      • .content_type in ('application/pdf')
    • any(file.explode(.), // few links 0 < length(.scan.url.urls) < 20 // fewer unique root domain links and length(distinct(.scan.url.urls, .domain.root_domain)) < 10 // sender domain matches no body domains and all(.scan.url.urls, .domain.root_domain != sender.email.domain.root_domain ) )
  3. not:
    • any of attachments where:
      • .content_type in ('message/global-delivery-status', 'message/delivery-status')
  4. any of:
    • subject.subject matches any of 124 patterns
      • termination.*notice
      • 38417
      • :completed
      • [il1]{2}mit.*ma[il1]{2} ?bo?x
      • [il][il][il]egai[ -]
      • [li][li][li]ega[li] attempt
      • [ng]-?[io]n .*block
      • [ng]-?[io]n .*cancel
      • [ng]-?[io]n .*deactiv
      • [ng]-?[io]n .*disabl
      • action.*required
      • abandon.*package
      • about.your.account
      • acc(ou)?n?t (is )?on ho[li]d
      • acc(ou)?n?t.*terminat
      • acc(oun)?t.*[il1]{2}mitation
      • access.*limitation
      • account (will be )?block
      • account.*de-?activat
      • account.*locked
      • account.*re-verification
      • account.*security
      • account.*suspension
      • account.has.been
      • account.has.expired
      • account.will.be.blocked
      • account v[il]o[li]at
      • activity.*acc(oun)?t
      • almost.full
      • app[li]e.[il]d
      • authenticate.*account
      • been.*suspend
      • clos.*of.*account.*processed
      • confirm.your.account
      • courier.*able
      • crediential.*notif
      • deactivation.*in.*progress
      • delivery.*attempt.*failed
      • document.received
      • documented.*shared.*with.*you
      • dropbox.*document
      • e-?ma[il1]+ .{010}suspen
      • e-?ma[il1]{1} user
      • e-?ma[il1]{2} acc
      • e-?ma[il1]{2}.*up.?grade
      • e.?ma[il1]{2}.*server
      • e.?ma[il1]{2}.*suspend
      • email.update
      • faxed you
      • fraud(ulent)?.*charge
      • from.helpdesk
      • fu[il1]{2}.*ma[il1]+[ -]?box
      • has.been.*suspended
      • has.been.limited
      • have.locked
      • he[li]p ?desk upgrade
      • heipdesk
      • i[il]iega[il]
      • ii[il]ega[il]
      • incoming e?mail
      • incoming.*fax
      • lock.*security
      • ma[il1]{1}[ -]?box.*quo
      • ma[il1]{2}[ -]?box.*fu[il1]
      • ma[il1]{2}box.*[il1]{2}mit
      • ma[il1]{2}box stor
      • mail on.?hold
      • mail.*box.*migration
      • mail.*de-?activat
      • mail.update.required
      • mails.*pending
      • messages.*pending
      • missed.*shipping.*notification
      • missed.shipment.notification
      • must.update.your.account
      • new [sl][io]g?[nig][ -]?in from
      • new voice ?-?mail
      • notifications.*pending
      • office.*3.*6.*5.*suspend
      • office365
      • on google docs with you
      • online doc
      • password.*compromised
      • periodic maintenance
      • potential(ly)? unauthorized
      • refund not approved
      • report
      • revised.*policy
      • scam
      • scanned.?invoice
      • secured?.update
      • security breach
      • securlty
      • signed.*delivery
      • statement is ready
      • status of your .{314}? ?delivery
      • susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty
      • suspicious.*sign.*[io]n
      • suspicious.activit
      • temporar(il)?y deactivate
      • temporar[il1]{2}y disab[li]ed
      • temporarily.*lock
      • un-?usua[li].activity
      • unable.*deliver
      • unauthorized.*activit
      • unauthorized.device
      • undelivered message
      • unread.*doc
      • unusual.activity
      • upgrade.*account
      • upgrade.notice
      • urgent message
      • urgent.verification
      • v[il1]o[li1]at[il1]on security
      • va[il1]{1}date.*ma[il1]{2}[ -]?box
      • verification ?-?require
      • verification( )?-?need
      • verify.your?.account
      • web ?-?ma[il1]{2}
      • web[ -]?ma[il1]{2}
      • will.be.suspended
      • your (customer )?account .as
      • your.office.365
      • your.online.access
    • any($suspicious_subjects, strings.icontains(subject.subject, .))
    • sender.display_name matches any of 73 patterns
      • Admin
      • Administrator
      • Alert
      • Assistant
      • Billing
      • Benefits
      • Bonus
      • CEO
      • CFO
      • CIO
      • CTO
      • Chairman
      • Claim
      • Confirm
      • Critical
      • Customer Service
      • Deal
      • Discount
      • Director
      • Exclusive
      • Executive
      • Fax
      • Free
      • Gift
      • /bHR/b
      • Helpdesk
      • Human Resources
      • Immediate
      • Important
      • Info
      • Information
      • Invoice
      • \bIT\b
      • Legal
      • Lottery
      • Management
      • Manager
      • Member Services
      • Notification
      • Offer
      • Operations
      • Order
      • Partner
      • Payment
      • Payroll
      • President
      • Premium
      • Prize
      • Receipt
      • Refund
      • Registrar
      • Required
      • Reward
      • Sales
      • Secretary
      • Security
      • Service
      • Signature
      • SSA?\.gov
      • Storage
      • Support
      • Sweepstakes
      • System
      • Tax
      • Tech Support
      • Update
      • Upgrade
      • Urgent
      • Validate
      • Verify
      • VIP
      • Webmaster
      • Winner
    • any of attachments where all hold:
      • any of:
        • .file_extension in $file_extensions_macros
        • .file_extension is 'pdf'
        • .file_type in ('pdf', 'doc', 'docx', 'xls', 'xlsx')
        • .content_type in ('application/pdf')
      • any(file.explode(.), any(.scan.url.urls, strings.ends_with(.url, ".exe")) or any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" ) )
  5. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_extension is 'pdf'
      • .file_type in ('pdf', 'doc', 'docx', 'xls', 'xlsx')
      • .content_type in ('application/pdf')
    • any(file.explode(.), any(.scan.url.urls, ( strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text, "cloudflare" ) // includes the turnstile CAPTCHA or ( strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw, 'https://challenges.cloudflare.com/turnstile/' ) // has a short body length indicating the page is gated behind the turnstile instead // of just including the turnstile and length(( ml.link_analysis(., mode="aggressive").final_dom.display_text ) ) < 200 ) ) and not ( ( // a Cloudflare error page strings.ilike(ml.link_analysis(., mode="aggressive").final_dom.display_text, "*error code*" ) and any(ml.link_analysis(., mode="aggressive").final_dom.links, strings.icontains(.href_url.query_params, "utm_source=errorcode" ) ) ) // a cookie warning mentioning Cloudflare or regex.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text, "cookie.{0,50}Cloudflare" ) or ml.link_analysis(., mode="aggressive").effective_url.domain.root_domain in ( "marketbeat.com" ) ) ) )
  6. any of:
    • not:
      • profile.by_sender().solicited
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign
  7. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  8. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, headers.auth_summary.dmarc.pass, sender.display_name, sender.email.domain.root_domain, subject.subject, type.inbound. Sensors: file.explode, ml.link_analysis, ml.nlu_classifier, profile.by_sender, regex.icontains, strings.ends_with, strings.icontains, strings.ilike. Reference lists: $file_extensions_macros, $high_trust_sender_root_domains, $suspicious_subjects.

Indicators Matched (208)

FieldMatchValue
attachments[].file_extensionequalspdf
attachments[].file_typememberpdf
attachments[].file_typememberdoc
attachments[].file_typememberdocx
attachments[].file_typememberxls
attachments[].file_typememberxlsx
attachments[].content_typememberapplication/pdf
regex.icontainsregextermination.*notice
regex.icontainsregex38417
regex.icontainsregex:completed
regex.icontainsregex[il1]{2}mit.*ma[il1]{2} ?bo?x
regex.icontainsregex[il][il][il]egai[ -]
196 more
regex.icontainsregex[li][li][li]ega[li] attempt
regex.icontainsregex[ng]-?[io]n .*block
regex.icontainsregex[ng]-?[io]n .*cancel
regex.icontainsregex[ng]-?[io]n .*deactiv
regex.icontainsregex[ng]-?[io]n .*disabl
regex.icontainsregexaction.*required
regex.icontainsregexabandon.*package
regex.icontainsregexabout.your.account
regex.icontainsregexacc(ou)?n?t (is )?on ho[li]d
regex.icontainsregexacc(ou)?n?t.*terminat
regex.icontainsregexacc(oun)?t.*[il1]{2}mitation
regex.icontainsregexaccess.*limitation
regex.icontainsregexaccount (will be )?block
regex.icontainsregexaccount.*de-?activat
regex.icontainsregexaccount.*locked
regex.icontainsregexaccount.*re-verification
regex.icontainsregexaccount.*security
regex.icontainsregexaccount.*suspension
regex.icontainsregexaccount.has.been
regex.icontainsregexaccount.has.expired
regex.icontainsregexaccount.will.be.blocked
regex.icontainsregexaccount v[il]o[li]at
regex.icontainsregexactivity.*acc(oun)?t
regex.icontainsregexalmost.full
regex.icontainsregexapp[li]e.[il]d
regex.icontainsregexauthenticate.*account
regex.icontainsregexbeen.*suspend
regex.icontainsregexclos.*of.*account.*processed
regex.icontainsregexconfirm.your.account
regex.icontainsregexcourier.*able
regex.icontainsregexcrediential.*notif
regex.icontainsregexdeactivation.*in.*progress
regex.icontainsregexdelivery.*attempt.*failed
regex.icontainsregexdocument.received
regex.icontainsregexdocumented.*shared.*with.*you
regex.icontainsregexdropbox.*document
regex.icontainsregexe-?ma[il1]+ .{010}suspen
regex.icontainsregexe-?ma[il1]{1} user
regex.icontainsregexe-?ma[il1]{2} acc
regex.icontainsregexe-?ma[il1]{2}.*up.?grade
regex.icontainsregexe.?ma[il1]{2}.*server
regex.icontainsregexe.?ma[il1]{2}.*suspend
regex.icontainsregexemail.update
regex.icontainsregexfaxed you
regex.icontainsregexfraud(ulent)?.*charge
regex.icontainsregexfrom.helpdesk
regex.icontainsregexfu[il1]{2}.*ma[il1]+[ -]?box
regex.icontainsregexhas.been.*suspended
regex.icontainsregexhas.been.limited
regex.icontainsregexhave.locked
regex.icontainsregexhe[li]p ?desk upgrade
regex.icontainsregexheipdesk
regex.icontainsregexi[il]iega[il]
regex.icontainsregexii[il]ega[il]
regex.icontainsregexincoming e?mail
regex.icontainsregexincoming.*fax
regex.icontainsregexlock.*security
regex.icontainsregexma[il1]{1}[ -]?box.*quo
regex.icontainsregexma[il1]{2}[ -]?box.*fu[il1]
regex.icontainsregexma[il1]{2}box.*[il1]{2}mit
regex.icontainsregexma[il1]{2}box stor
regex.icontainsregexmail on.?hold
regex.icontainsregexmail.*box.*migration
regex.icontainsregexmail.*de-?activat
regex.icontainsregexmail.update.required
regex.icontainsregexmails.*pending
regex.icontainsregexmessages.*pending
regex.icontainsregexmissed.*shipping.*notification
regex.icontainsregexmissed.shipment.notification
regex.icontainsregexmust.update.your.account
regex.icontainsregexnew [sl][io]g?[nig][ -]?in from
regex.icontainsregexnew voice ?-?mail
regex.icontainsregexnotifications.*pending
regex.icontainsregexoffice.*3.*6.*5.*suspend
regex.icontainsregexoffice365
regex.icontainsregexon google docs with you
regex.icontainsregexonline doc
regex.icontainsregexpassword.*compromised
regex.icontainsregexperiodic maintenance
regex.icontainsregexpotential(ly)? unauthorized
regex.icontainsregexrefund not approved
regex.icontainsregexreport
regex.icontainsregexrevised.*policy
regex.icontainsregexscam
regex.icontainsregexscanned.?invoice
regex.icontainsregexsecured?.update
regex.icontainsregexsecurity breach
regex.icontainsregexsecurlty
regex.icontainsregexsigned.*delivery
regex.icontainsregexstatement is ready
regex.icontainsregexstatus of your .{314}? ?delivery
regex.icontainsregexsusp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty
regex.icontainsregexsuspicious.*sign.*[io]n
regex.icontainsregexsuspicious.activit
regex.icontainsregextemporar(il)?y deactivate
regex.icontainsregextemporar[il1]{2}y disab[li]ed
regex.icontainsregextemporarily.*lock
regex.icontainsregexun-?usua[li].activity
regex.icontainsregexunable.*deliver
regex.icontainsregexunauthorized.*activit
regex.icontainsregexunauthorized.device
regex.icontainsregexundelivered message
regex.icontainsregexunread.*doc
regex.icontainsregexunusual.activity
regex.icontainsregexupgrade.*account
regex.icontainsregexupgrade.notice
regex.icontainsregexurgent message
regex.icontainsregexurgent.verification
regex.icontainsregexv[il1]o[li1]at[il1]on security
regex.icontainsregexva[il1]{1}date.*ma[il1]{2}[ -]?box
regex.icontainsregexverification ?-?require
regex.icontainsregexverification( )?-?need
regex.icontainsregexverify.your?.account
regex.icontainsregexweb ?-?ma[il1]{2}
regex.icontainsregexweb[ -]?ma[il1]{2}
regex.icontainsregexwill.be.suspended
regex.icontainsregexyour (customer )?account .as
regex.icontainsregexyour.office.365
regex.icontainsregexyour.online.access
regex.icontainsregexAdmin
regex.icontainsregexAdministrator
regex.icontainsregexAlert
regex.icontainsregexAssistant
regex.icontainsregexBilling
regex.icontainsregexBenefits
regex.icontainsregexBonus
regex.icontainsregexCEO
regex.icontainsregexCFO
regex.icontainsregexCIO
regex.icontainsregexCTO
regex.icontainsregexChairman
regex.icontainsregexClaim
regex.icontainsregexConfirm
regex.icontainsregexCritical
regex.icontainsregexCustomer Service
regex.icontainsregexDeal
regex.icontainsregexDiscount
regex.icontainsregexDirector
regex.icontainsregexExclusive
regex.icontainsregexExecutive
regex.icontainsregexFax
regex.icontainsregexFree
regex.icontainsregexGift
regex.icontainsregex/bHR/b
regex.icontainsregexHelpdesk
regex.icontainsregexHuman Resources
regex.icontainsregexImmediate
regex.icontainsregexImportant
regex.icontainsregexInfo
regex.icontainsregexInformation
regex.icontainsregexInvoice
regex.icontainsregex\bIT\b
regex.icontainsregexLegal
regex.icontainsregexLottery
regex.icontainsregexManagement
regex.icontainsregexManager
regex.icontainsregexMember Services
regex.icontainsregexNotification
regex.icontainsregexOffer
regex.icontainsregexOperations
regex.icontainsregexOrder
regex.icontainsregexPartner
regex.icontainsregexPayment
regex.icontainsregexPayroll
regex.icontainsregexPresident
regex.icontainsregexPremium
regex.icontainsregexPrize
regex.icontainsregexReceipt
regex.icontainsregexRefund
regex.icontainsregexRegistrar
regex.icontainsregexRequired
regex.icontainsregexReward
regex.icontainsregexSales
regex.icontainsregexSecretary
regex.icontainsregexSecurity
regex.icontainsregexService
regex.icontainsregexSignature
regex.icontainsregexSSA?\.gov
regex.icontainsregexStorage
regex.icontainsregexSupport
regex.icontainsregexSweepstakes
regex.icontainsregexSystem
regex.icontainsregexTax
regex.icontainsregexTech Support
regex.icontainsregexUpdate
regex.icontainsregexUpgrade
regex.icontainsregexUrgent
regex.icontainsregexValidate
regex.icontainsregexVerify
regex.icontainsregexVIP
regex.icontainsregexWebmaster
regex.icontainsregexWinner
strings.ends_withsuffix.exe
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].nameequalscred_theft
strings.icontainssubstringcloudflare
strings.icontainssubstringhttps://challenges.cloudflare.com/turnstile/

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        or
          attachments.content_type eq "application/pdf"
          attachments.file_extension eq "pdf"
          attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
          attachments.file_type in ["doc", "docx", "pdf", "xls", "xlsx"]
         macro "any(file.explode(.),\n                 any(.scan.url.urls, strings.ends_with(.url, \".exe\"))\n                 or any(ml.nlu_classifier(.scan.ocr.raw).intents,\n                        .name == \"cred_theft\"\n                 )\n         )"
    sender.display_name regex_match "/bHR/b"
    sender.display_name regex_match "Admin"
    sender.display_name regex_match "Administrator"
    sender.display_name regex_match "Alert"
    sender.display_name regex_match "Assistant"
    sender.display_name regex_match "Benefits"
    sender.display_name regex_match "Billing"
    sender.display_name regex_match "Bonus"
    sender.display_name regex_match "CEO"
    sender.display_name regex_match "CFO"
    sender.display_name regex_match "CIO"
    sender.display_name regex_match "CTO"
    sender.display_name regex_match "Chairman"
    sender.display_name regex_match "Claim"
    sender.display_name regex_match "Confirm"
    sender.display_name regex_match "Critical"
    sender.display_name regex_match "Customer Service"
    sender.display_name regex_match "Deal"
    sender.display_name regex_match "Director"
    sender.display_name regex_match "Discount"
    sender.display_name regex_match "Exclusive"
    sender.display_name regex_match "Executive"
    sender.display_name regex_match "Fax"
    sender.display_name regex_match "Free"
    sender.display_name regex_match "Gift"
    sender.display_name regex_match "Helpdesk"
    sender.display_name regex_match "Human Resources"
    sender.display_name regex_match "Immediate"
    sender.display_name regex_match "Important"
    sender.display_name regex_match "Info"
    sender.display_name regex_match "Information"
    sender.display_name regex_match "Invoice"
    sender.display_name regex_match "Legal"
    sender.display_name regex_match "Lottery"
    sender.display_name regex_match "Management"
    sender.display_name regex_match "Manager"
    sender.display_name regex_match "Member Services"
    sender.display_name regex_match "Notification"
    sender.display_name regex_match "Offer"
    sender.display_name regex_match "Operations"
    sender.display_name regex_match "Order"
    sender.display_name regex_match "Partner"
    sender.display_name regex_match "Payment"
    sender.display_name regex_match "Payroll"
    sender.display_name regex_match "Premium"
    sender.display_name regex_match "President"
    sender.display_name regex_match "Prize"
    sender.display_name regex_match "Receipt"
    sender.display_name regex_match "Refund"
    sender.display_name regex_match "Registrar"
    sender.display_name regex_match "Required"
    sender.display_name regex_match "Reward"
    sender.display_name regex_match "SSA?\\.gov"
    sender.display_name regex_match "Sales"
    sender.display_name regex_match "Secretary"
    sender.display_name regex_match "Security"
    sender.display_name regex_match "Service"
    sender.display_name regex_match "Signature"
    sender.display_name regex_match "Storage"
    sender.display_name regex_match "Support"
    sender.display_name regex_match "Sweepstakes"
    sender.display_name regex_match "System"
    sender.display_name regex_match "Tax"
    sender.display_name regex_match "Tech Support"
    sender.display_name regex_match "Update"
    sender.display_name regex_match "Upgrade"
    sender.display_name regex_match "Urgent"
    sender.display_name regex_match "VIP"
    sender.display_name regex_match "Validate"
    sender.display_name regex_match "Verify"
    sender.display_name regex_match "Webmaster"
    sender.display_name regex_match "Winner"
    sender.display_name regex_match "\\bIT\\b"
    subject.subject regex_match "38417"
    subject.subject regex_match ":completed"
    subject.subject regex_match "[il1]{2}mit.*ma[il1]{2} ?bo?x"
    subject.subject regex_match "[il][il][il]egai[ -]"
    subject.subject regex_match "[li][li][li]ega[li] attempt"
    subject.subject regex_match "[ng]-?[io]n .*block"
    subject.subject regex_match "[ng]-?[io]n .*cancel"
    subject.subject regex_match "[ng]-?[io]n .*deactiv"
    subject.subject regex_match "[ng]-?[io]n .*disabl"
    subject.subject regex_match "abandon.*package"
    subject.subject regex_match "about.your.account"
    subject.subject regex_match "acc(ou)?n?t (is )?on ho[li]d"
    subject.subject regex_match "acc(ou)?n?t.*terminat"
    subject.subject regex_match "acc(oun)?t.*[il1]{2}mitation"
    subject.subject regex_match "access.*limitation"
    subject.subject regex_match "account (will be )?block"
    subject.subject regex_match "account v[il]o[li]at"
    subject.subject regex_match "account.*de-?activat"
    subject.subject regex_match "account.*locked"
    subject.subject regex_match "account.*re-verification"
    subject.subject regex_match "account.*security"
    subject.subject regex_match "account.*suspension"
    subject.subject regex_match "account.has.been"
    subject.subject regex_match "account.has.expired"
    subject.subject regex_match "account.will.be.blocked"
    subject.subject regex_match "action.*required"
    subject.subject regex_match "activity.*acc(oun)?t"
    subject.subject regex_match "almost.full"
    subject.subject regex_match "app[li]e.[il]d"
    subject.subject regex_match "authenticate.*account"
    subject.subject regex_match "been.*suspend"
    subject.subject regex_match "clos.*of.*account.*processed"
    subject.subject regex_match "confirm.your.account"
    subject.subject regex_match "courier.*able"
    subject.subject regex_match "crediential.*notif"
    subject.subject regex_match "deactivation.*in.*progress"
    subject.subject regex_match "delivery.*attempt.*failed"
    subject.subject regex_match "document.received"
    subject.subject regex_match "documented.*shared.*with.*you"
    subject.subject regex_match "dropbox.*document"
    subject.subject regex_match "e-?ma[il1]+ .{010}suspen"
    subject.subject regex_match "e-?ma[il1]{1} user"
    subject.subject regex_match "e-?ma[il1]{2} acc"
    subject.subject regex_match "e-?ma[il1]{2}.*up.?grade"
    subject.subject regex_match "e.?ma[il1]{2}.*server"
    subject.subject regex_match "e.?ma[il1]{2}.*suspend"
    subject.subject regex_match "email.update"
    subject.subject regex_match "faxed you"
    subject.subject regex_match "fraud(ulent)?.*charge"
    subject.subject regex_match "from.helpdesk"
    subject.subject regex_match "fu[il1]{2}.*ma[il1]+[ -]?box"
    subject.subject regex_match "has.been.*suspended"
    subject.subject regex_match "has.been.limited"
    subject.subject regex_match "have.locked"
    subject.subject regex_match "he[li]p ?desk upgrade"
    subject.subject regex_match "heipdesk"
    subject.subject regex_match "i[il]iega[il]"
    subject.subject regex_match "ii[il]ega[il]"
    subject.subject regex_match "incoming e?mail"
    subject.subject regex_match "incoming.*fax"
    subject.subject regex_match "lock.*security"
    subject.subject regex_match "ma[il1]{1}[ -]?box.*quo"
    subject.subject regex_match "ma[il1]{2}[ -]?box.*fu[il1]"
    subject.subject regex_match "ma[il1]{2}box stor"
    subject.subject regex_match "ma[il1]{2}box.*[il1]{2}mit"
    subject.subject regex_match "mail on.?hold"
    subject.subject regex_match "mail.*box.*migration"
    subject.subject regex_match "mail.*de-?activat"
    subject.subject regex_match "mail.update.required"
    subject.subject regex_match "mails.*pending"
    subject.subject regex_match "messages.*pending"
    subject.subject regex_match "missed.*shipping.*notification"
    subject.subject regex_match "missed.shipment.notification"
    subject.subject regex_match "must.update.your.account"
    subject.subject regex_match "new [sl][io]g?[nig][ -]?in from"
    subject.subject regex_match "new voice ?-?mail"
    subject.subject regex_match "notifications.*pending"
    subject.subject regex_match "office.*3.*6.*5.*suspend"
    subject.subject regex_match "office365"
    subject.subject regex_match "on google docs with you"
    subject.subject regex_match "online doc"
    subject.subject regex_match "password.*compromised"
    subject.subject regex_match "periodic maintenance"
    subject.subject regex_match "potential(ly)? unauthorized"
    subject.subject regex_match "refund not approved"
    subject.subject regex_match "report"
    subject.subject regex_match "revised.*policy"
    subject.subject regex_match "scam"
    subject.subject regex_match "scanned.?invoice"
    subject.subject regex_match "secured?.update"
    subject.subject regex_match "security breach"
    subject.subject regex_match "securlty"
    subject.subject regex_match "signed.*delivery"
    subject.subject regex_match "statement is ready"
    subject.subject regex_match "status of your .{314}? ?delivery"
    subject.subject regex_match "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty"
    subject.subject regex_match "suspicious.*sign.*[io]n"
    subject.subject regex_match "suspicious.activit"
    subject.subject regex_match "temporar(il)?y deactivate"
    subject.subject regex_match "temporar[il1]{2}y disab[li]ed"
    subject.subject regex_match "temporarily.*lock"
    subject.subject regex_match "termination.*notice"
    subject.subject regex_match "un-?usua[li].activity"
    subject.subject regex_match "unable.*deliver"
    subject.subject regex_match "unauthorized.*activit"
    subject.subject regex_match "unauthorized.device"
    subject.subject regex_match "undelivered message"
    subject.subject regex_match "unread.*doc"
    subject.subject regex_match "unusual.activity"
    subject.subject regex_match "upgrade.*account"
    subject.subject regex_match "upgrade.notice"
    subject.subject regex_match "urgent message"
    subject.subject regex_match "urgent.verification"
    subject.subject regex_match "v[il1]o[li1]at[il1]on security"
    subject.subject regex_match "va[il1]{1}date.*ma[il1]{2}[ -]?box"
    subject.subject regex_match "verification ?-?require"
    subject.subject regex_match "verification( )?-?need"
    subject.subject regex_match "verify.your?.account"
    subject.subject regex_match "web ?-?ma[il1]{2}"
    subject.subject regex_match "web[ -]?ma[il1]{2}"
    subject.subject regex_match "will.be.suspended"
    subject.subject regex_match "your (customer )?account .as"
    subject.subject regex_match "your.office.365"
    subject.subject regex_match "your.online.access"
     macro "any($suspicious_subjects, strings.icontains(subject.subject, .))"
  any(attachments)
    and
      or
        attachments.content_type eq "application/pdf"
        attachments.file_extension eq "pdf"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
        attachments.file_type in ["doc", "docx", "pdf", "xls", "xlsx"]
       macro "any(file.explode(.),\n                // few links\n                0 < length(.scan.url.urls) < 20\n                // fewer unique root domain links\n                and length(distinct(.scan.url.urls, .domain.root_domain)) < 10\n                // sender domain matches no body domains\n                and all(.scan.url.urls,\n                        .domain.root_domain != sender.email.domain.root_domain\n                )\n        )"
  any(attachments)
    and
      or
        attachments.content_type eq "application/pdf"
        attachments.file_extension eq "pdf"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
        attachments.file_type in ["doc", "docx", "pdf", "xls", "xlsx"]
       macro "any(file.explode(.),\n                any(.scan.url.urls,\n                    (\n                      strings.icontains(ml.link_analysis(., mode=\"aggressive\").final_dom.display_text,\n                                        \"cloudflare\"\n                      )\n                      // includes the turnstile CAPTCHA\n                      or (\n                        strings.icontains(ml.link_analysis(., mode=\"aggressive\").final_dom.raw,\n                                          'https://challenges.cloudflare.com/turnstile/'\n                        )\n                        // has a short body length indicating the page is gated behind the turnstile instead\n                        // of just including the turnstile\n                        and length((\n                                     ml.link_analysis(., mode=\"aggressive\").final_dom.display_text\n                                   )\n                        ) < 200\n                      )\n                    )\n                    and not (\n                      ( // a Cloudflare error page\n                        strings.ilike(ml.link_analysis(., mode=\"aggressive\").final_dom.display_text,\n                                      \"*error code*\"\n                        )\n                        and any(ml.link_analysis(., mode=\"aggressive\").final_dom.links,\n                                strings.icontains(.href_url.query_params,\n                                                  \"utm_source=errorcode\"\n                                )\n                        )\n                      ) // a cookie warning mentioning Cloudflare\n                      or regex.icontains(ml.link_analysis(., mode=\"aggressive\").final_dom.display_text,\n                                         \"cookie.{0,50}Cloudflare\"\n                      )\n                      or ml.link_analysis(., mode=\"aggressive\").effective_url.domain.root_domain in (\n                        \"marketbeat.com\"\n                      )\n                    )\n                )\n        )"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
    sender.email.domain.root_domain macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    not
      profile.by_sender func_call "profile.by_sender().solicited"
  not
    any(attachments)
      attachments.content_type in ["message/delivery-status", "message/global-delivery-status"]
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
sender.display_nameregex_match
  • /bHR/b corpus 4 (mql 4)
  • Admin corpus 5 (mql 5)
  • Administrator corpus 5 (mql 5)
  • Alert corpus 5 (mql 5)
  • Assistant corpus 5 (mql 5)
  • Benefits corpus 5 (mql 5)
  • Billing corpus 5 (mql 5)
  • Bonus corpus 5 (mql 5)
  • CEO corpus 5 (mql 5)
  • CFO corpus 5 (mql 5)
  • CIO corpus 5 (mql 5)
  • CTO corpus 5 (mql 5)
  • Chairman corpus 5 (mql 5)
  • Claim corpus 5 (mql 5)
  • Confirm corpus 5 (mql 5)
  • Critical corpus 5 (mql 5)
  • Customer Service corpus 5 (mql 5)
  • Deal corpus 5 (mql 5)
  • Director corpus 5 (mql 5)
  • Discount corpus 5 (mql 5)
  • Exclusive corpus 5 (mql 5)
  • Executive corpus 5 (mql 5)
  • Fax corpus 5 (mql 5)
  • Free corpus 5 (mql 5)
  • Gift corpus 5 (mql 5)
  • Helpdesk corpus 5 (mql 5)
  • Human Resources corpus 5 (mql 5)
  • Immediate corpus 5 (mql 5)
  • Important corpus 5 (mql 5)
  • Info corpus 5 (mql 5)
  • Information corpus 5 (mql 5)
  • Invoice corpus 5 (mql 5)
  • Legal corpus 4 (mql 4)
  • Lottery corpus 5 (mql 5)
  • Management corpus 5 (mql 5)
  • Manager corpus 5 (mql 5)
  • Member Services corpus 5 (mql 5)
  • Notification corpus 5 (mql 5)
  • Offer corpus 5 (mql 5)
  • Operations corpus 5 (mql 5)
  • +33 more values (see full rule source)
field:"sender.display_name" kind:regex_match
subject.subjectregex_match
  • 38417 corpus 8 (mql 8)
  • :completed corpus 8 (mql 8)
  • [il1]{2}mit.*ma[il1]{2} ?bo?x corpus 8 (mql 8)
  • [il][il][il]egai[ -] corpus 8 (mql 8)
  • [li][li][li]ega[li] attempt corpus 8 (mql 8)
  • [ng]-?[io]n .*block corpus 8 (mql 8)
  • [ng]-?[io]n .*cancel corpus 8 (mql 8)
  • [ng]-?[io]n .*deactiv corpus 8 (mql 8)
  • [ng]-?[io]n .*disabl corpus 8 (mql 8)
  • abandon.*package corpus 8 (mql 8)
  • about.your.account corpus 8 (mql 8)
  • acc(ou)?n?t (is )?on ho[li]d corpus 8 (mql 8)
  • acc(ou)?n?t.*terminat corpus 8 (mql 8)
  • acc(oun)?t.*[il1]{2}mitation corpus 8 (mql 8)
  • access.*limitation corpus 8 (mql 8)
  • account (will be )?block corpus 8 (mql 8)
  • account v[il]o[li]at corpus 8 (mql 8)
  • account.*de-?activat corpus 8 (mql 8)
  • account.*locked corpus 8 (mql 8)
  • account.*re-verification corpus 8 (mql 8)
  • account.*security corpus 8 (mql 8)
  • account.*suspension corpus 8 (mql 8)
  • account.has.been corpus 8 (mql 8)
  • account.has.expired corpus 8 (mql 8)
  • account.will.be.blocked corpus 8 (mql 8)
  • action.*required corpus 8 (mql 8)
  • activity.*acc(oun)?t corpus 8 (mql 8)
  • almost.full corpus 8 (mql 8)
  • app[li]e.[il]d corpus 8 (mql 8)
  • authenticate.*account corpus 8 (mql 8)
  • been.*suspend corpus 8 (mql 8)
  • clos.*of.*account.*processed corpus 8 (mql 8)
  • confirm.your.account corpus 8 (mql 8)
  • courier.*able corpus 8 (mql 8)
  • crediential.*notif corpus 8 (mql 8)
  • deactivation.*in.*progress corpus 8 (mql 8)
  • delivery.*attempt.*failed corpus 8 (mql 8)
  • document.received corpus 7 (mql 7)
  • documented.*shared.*with.*you corpus 8 (mql 8)
  • dropbox.*document corpus 8 (mql 8)
  • +84 more values (see full rule source)
field:"subject.subject" kind:regex_match
type.inboundeq
  • true transforms: boolean corpus 1212 (mql 1212)
field:"type.inbound" kind:eq value:"true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments

Suspicious VBA macros from untrusted sender

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

Detects any VBA macro attachment that scores above a medium confidence threshold in the Sublime Macro Classifier.

Threat Classification

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

CategoryValues
Attack typesMalware/Ransomware
Tactics and techniquesMacros

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • type

Rule Body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_macros
          or (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and ml.macro_classifier(.).malicious
        and ml.macro_classifier(.).confidence in ("high")
)
and (
  profile.by_sender().prevalence in ("new", "outlier")
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)

Detection Logic

Scope: inbound message.

Detects any VBA macro attachment that scores above a medium confidence threshold in the Sublime Macro Classifier.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • all of:
        • .file_extension is missing
        • .file_type is 'unknown'
        • .content_type is 'application/octet-stream'
        • .size < 100000000
    • ml.macro_classifier(.).malicious
    • ml.macro_classifier(.).confidence in ("high")
  3. any of:
    • profile.by_sender().prevalence in ("new", "outlier")
    • all of:
      • profile.by_sender().any_messages_malicious_or_spam
      • not:
        • profile.by_sender().any_messages_benign

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: ml.macro_classifier, profile.by_sender. Reference lists: $file_extensions_macros.

Indicators Matched (2)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
        attachments.file_extension macro "attachments[].file_extension in file_extensions_macros"
      ml.macro_classifier func_call "ml.macro_classifier(.).confidence in (\"high\")"
      ml.macro_classifier func_call "ml.macro_classifier(.).malicious"
  or
    and
      not
        profile.by_sender func_call "profile.by_sender().any_messages_benign"
      profile.by_sender func_call "profile.by_sender().any_messages_malicious_or_spam"
    profile.by_sender func_call "profile.by_sender().prevalence in (\"new\", \"outlier\")"
  type.inbound eq "true"

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