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 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: 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 with embedded file from internal sender with SPF failurehigh
Attachment: ICS file with AWS Lambda URLmedium
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 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: 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 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 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 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 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 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: 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 exploiting CVE-2023-38831 (unsolicited)critical
Attachment: ZIP file with CVE-2026-0866 exploitmedium
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 of file.explode(.) where all hold:
      • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
        • .name is 'cred_theft'
        • .confidence is 'high'
      • .scan.ocr.raw contains 'password-protected'
      • any of ml.nlu_classifier(.scan.ocr.raw).entities where all hold:
        • .name is 'org'
        • .text is '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
      any(file.explode(attachments))
        and
          any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).entities)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).entities[].name eq "org"
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).entities[].text eq "Adobe"
          any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence eq "high"
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name eq "cred_theft"
          file.explode(attachments[])[].scan.ocr.raw contains "password-protected"
      attachments.file_extension eq "pdf"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where any holds:
      • .scan.ocr.raw matches '*please*enable*macros'
      • any of .scan.strings.strings where:
        • . matches '*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
      any(file.explode(attachments))
        or
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "please enable macros"
          file.explode(attachments[])[].scan.ocr.raw wildcard "*please*enable*macros"
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
  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
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 of file.oletools(.).macros.keywords where:
      • .type is '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) is 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"
         macro "attachments[].file_extension in file_extensions_macros"
      any(file.oletools(attachments).macros.keywords)
        file.oletools(attachments).macros.keywords.type eq "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
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 of file.explode(.) where:
      • any of .scan.vba.auto_exec where:
        • . is '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"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
      any(file.explode(attachments))
        any(file.explode(attachments).scan.vba.auto_exec)
          file.explode(attachments).scan.vba.auto_exec eq "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
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 of file.explode(.) where:
      • any of .flavors.yara where:
        • . is '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 is '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
      any(file.explode(attachments))
        any(file.explode(attachments).flavors.yara)
          file.explode(attachments).flavors.yara eq "encrypted_zip"
      or
        attachments.file_extension eq "zip"
        attachments.file_type eq "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
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 is '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"
         macro "attachments[].file_extension in file_extensions_macros"
      file.oletools func_call "file.oletools(attachments[]).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
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 of file.explode(.) where:
      • any of .scan.vba.hex where:
        • . matches '*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"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
      any(file.explode(attachments))
        any(file.explode(attachments).scan.vba.hex)
          file.explode(attachments).scan.vba.hex match "exe"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • .scan.docx.author matches '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"]
         macro "attachments[].file_extension in file_extensions_common_archives"
      any(file.explode(attachments))
        file.explode(attachments).scan.docx.author eq "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
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 of file.explode(.) where all hold:
      • any of .flavors.yara where:
        • . is 'encrypted_zip'
      • .scan.encrypted_zip.cracked_password is None

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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).flavors.yara)
            file.explode(attachments).flavors.yara eq "encrypted_zip"
          file.explode(attachments[])[].scan.encrypted_zip.cracked_password eq ""
      or
        attachments.file_extension eq "zip"
        attachments.file_type eq "zip"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
      file.oletools func_call "file.oletools(attachments[]).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 " "
  type.inbound eq "true"
   macro "sender.display_name in org_display_names"

Indicators

These rows show field, operator, and value matches.

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 of file.explode(.) where all hold:
      • any of .scan.strings.strings where:
        • . contains 'DllImport'
      • any of .scan.strings.strings where:
        • . contains '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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings contains "CreateProcess"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings contains "DllImport"
      attachments.file_extension eq "csproj"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.expand_archives(.).files where:
      • .file_type is '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
      any(file.expand_archives(attachments).files)
        file.expand_archives(attachments).files.file_type eq "rar"
      attachments.file_type eq "7z"
       macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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)) is 0
    • length(filter(attachments, .file_type != 'pdf')) is 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)))) is length(attachments)
  3. any of:
    • all of:
      • any of ml.logo_detect(file.message_screenshot()).brands where:
        • .name is 'Adobe'
      • all of:
        • length(body.links) > 0
        • 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'))) is not length(body.links)
    • any of filter(attachments) where:
      • any of file.explode(.) where any holds:
        • length(.scan.url.urls) > 0
        • length(.scan.pdf.urls) > 0
        • 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) is 0
  5. not:
    • any of headers.hops where:
      • any of .fields where:
        • .name is 'List-Unsubscribe-Post'
  6. not:
    • any of ml.nlu_classifier(body.current_thread.text).topics where all hold:
      • .name in ('Advertising and Promotions', 'Newsletters and Digests')
      • .confidence is '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 is 'new'
    • length(recipients.to) is 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
    any(filter(attachments))
      any(file.explode(filter(attachments)))
        or
          body.links length_compare "0"
          file.explode(filter(attachments)[])[].scan.pdf.urls length_compare "0"
          file.explode(filter(attachments)[])[].scan.url.urls length_compare "0"
    and
      any(body.links)
        body.links.display_text is_null
      any(ml.logo_detect(file.message_screenshot()).brands)
        ml.logo_detect(file.message_screenshot()).brands.name eq "Adobe"
      body.links length_compare "0"
      body.links length_compare "10"
      length func_call "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
    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
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"
  not
    any(ml.nlu_classifier(body.current_thread.text).topics)
      and
        ml.nlu_classifier(body.current_thread.text).topics.confidence eq "high"
        ml.nlu_classifier(body.current_thread.text).topics.name in ["Advertising and Promotions", "Newsletters and Digests"]
  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)"
       macro "all(recipients.to)"
    profile.by_sender_email func_call "profile.by_sender_email().prevalence == new"
    recipients.to length_compare "0"
  or
    filter(attachments, .file_type != 'pdf') length_compare "0"
    filter(attachments, .file_type not in $file_types_images) length_compare "0"
    length func_call "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)"
  not
    profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops
ml.nlu_classifier(body.current_thread.text).topicsarray_any(no value, null check)excludes:ml.nlu_classifier(body.current_thread.text).topics

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
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "adobe_sign_lure_banner_images"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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)

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
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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
field:"type.inbound" kind:eq value:"true"

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)

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
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
      • .depth > 0
      • .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
      any(file.explode(attachments))
        and
          file.explode(attachments[])[].depth gt "0"
          file.explode(attachments[])[].file_extension in ["htm", "html"]
       macro "attachments[].file_extension in file_extensions_common_archives"
  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
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 of file.explode(.) where any holds:
      • .file_extension in ('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', 'ade', 'adp', 'app', 'application', 'appref-ms', 'asp', 'aspx', 'asx', 'bat', 'bgi', 'cab', 'chm', 'cmd', 'cnt', 'com', 'cpl', 'diagcab', 'exe', 'fxp', 'gadget', 'hlp', 'hpj', 'hta', 'htc', 'ins', 'iso', 'isp', 'its', 'jar', 'jnlp', 'js', 'jse', 'ksh', 'lnk', 'mad', 'maf', 'mag', 'mam', 'maq', 'mar', 'mas', 'mat', 'mau', 'mav', 'maw', 'mcf', 'mda', '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', 'pyo', 'pyw', 'pyz', 'pyzw', 'reg', 'scf', 'scr', 'sct', 'shb', 'shs', 'theme', 'url', 'vb', 'vbe', 'vbp', 'vbs', 'vhd', 'vhdx', 'vsmacros', 'vsw', 'webpnp', 'website', 'ws', 'wsc', 'wsf', 'wsh', 'xbap', 'xll', 'xnk')
      • all of:
        • .depth is 1
        • .file_extension is '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
      any(file.explode(attachments))
        or
          and
            file.explode(attachments[])[].depth eq "1"
            file.explode(attachments[])[].file_extension eq "bas"
          file.explode(attachments[])[].file_extension in ["ade", "adp", "apk", "app", "application", "appref-ms", "appx", "appxbundle", "asp", "aspx", "asx", "bat", "bgi", "cab", "chm", "cmd", "cnt", "com", "cpl", "diagcab", "dll", "dmg", "ex", "ex_", "exe", "fxp", "gadget", "hlp", "hpj", "hta", "htc", "ins", "iso", "isp", "its", "jar", "jnlp", "js", "jse", "ksh", "lib", "lnk", "mad", "maf", "mag", "mam", "maq", "mar", "mas", "mat", "mau", "mav", "maw", "mcf", "mda", "mde", "mdt", "mdw", "mdz", "msc", "msh", "msh1", "msh1xml", "msh2", "msh2xml", "mshxml", "msi", "msix", "msixbundle", "msp", "mst", "msu", "nsh", "ops", "osd", "pcd", "pif", "pl", "plg", "prf", "prg", "printerexport", "ps1", "ps1xml", "ps2", "ps2xml", "psc1", "psc2", "psd1", "psdm1", "pst", "pyo", "pyw", "pyz", "pyzw", "reg", "scf", "scr", "sct", "shb", "shs", "sys", "theme", "url", "vb", "vbe", "vbp", "vbs", "vhd", "vhdx", "vsmacros", "vsw", "vxd", "webpnp", "website", "ws", "wsc", "wsf", "wsh", "xbap", "xll", "xnk"]
      or
        attachments.file_type eq "rar"
         macro "attachments[].file_extension in file_extensions_common_archives"
  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
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 of file.explode(.) where all hold:
      • any of:
        • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
        • .flavors.mime is 'text/html'
        • any of .flavors.yara where:
          • . is 'html_file'
      • any of .scan.url.urls where:
        • .scheme is '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
  any(attachments)
    and
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).flavors.yara)
              file.explode(attachments).flavors.yara eq "html_file"
            file.explode(attachments[])[].file_extension in ["dhtml", "htm", "html", "shtml"]
            file.explode(attachments[])[].flavors.mime eq "text/html"
          any(file.explode(attachments).scan.url.urls)
            file.explode(attachments).scan.url.urls.scheme eq "file"
       macro "attachments[].file_extension in file_extensions_common_archives"
  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
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 of file.explode(.) where all hold:
          • .scan.zip.encrypted is False
          • any of .scan.zip.all_paths where:
            • . contains 'dll'
        • any of file.explode(.) where all hold:
          • any of .flavors.yara where:
            • . matches 'vb_file'
          • any of .scan.strings.strings where:
            • . contains 'dll'
      • any of file.explode(.) where all hold:
        • .scan.zip.encrypted is True
        • any of .scan.zip.all_paths where:
          • any of $file_extensions_macros where:
            • strings.icontains(.)
        • any of .scan.zip.all_paths where:
          • . contains 'dll'
      • all of:
        • any of file.explode(.) where all hold:
          • any of .flavors.yara where:
            • . matches 'vb_file'
          • any of .scan.strings.strings where:
            • . matches '*Lib*.dll*'
        • any of file.explode(.) where:
          • .file_extension matches '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
          any(file.explode(attachments))
            and
              any(file.explode(attachments).flavors.yara)
                file.explode(attachments).flavors.yara eq "vb_file"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings contains "dll"
          any(file.explode(attachments))
            and
              any(file.explode(attachments).scan.zip.all_paths)
                file.explode(attachments).scan.zip.all_paths contains "dll"
              file.explode(attachments[])[].scan.zip.encrypted eq "false"
        and
          any(file.explode(attachments))
            and
              any(file.explode(attachments).flavors.yara)
                file.explode(attachments).flavors.yara eq "vb_file"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings wildcard "*Lib*.dll*"
          any(file.explode(attachments))
            file.explode(attachments).file_extension eq "dll"
        any(file.explode(attachments))
          and
            any(file.explode(attachments).scan.zip.all_paths)
              any($file_extensions_macros)
                strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.zip.all_paths[])"
            any(file.explode(attachments).scan.zip.all_paths)
              file.explode(attachments).scan.zip.all_paths contains "dll"
            file.explode(attachments[])[].scan.zip.encrypted eq "true"
      or
        attachments.file_type eq "rar"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • .file_extension is '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
      any(file.explode(attachments))
        file.explode(attachments).file_extension eq "chm"
       macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of .flavors.yara where:
        • . is 'mz_file'
      • .flavors.mime starts with '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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).flavors.yara)
            file.explode(attachments).flavors.yara eq "mz_file"
          file.explode(attachments[])[].flavors.mime starts_with "application"
      or
        attachments.file_type eq "rar"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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)) is 2
    • any of file.explode(.) where all hold:
      • .depth is 1
      • .file_extension is '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
      any(file.explode(attachments))
        and
          file.explode(attachments[])[].depth eq "1"
          file.explode(attachments[])[].file_extension eq "wsf"
      distinct(filter(file.explode(attachments[]), attachments[].depth == 1 and attachments[].flavors.mime in~ ('application/pdf', 'text/plain')), attachments[].flavors.mime) length_compare "2"
       macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.expand_archives(.).files where all hold:
      • .file_name contains '{'
      • any of:
        • .file_name contains 'echo,'
        • .file_name contains 'base64'
        • .file_name matches '\\bbash\\b'
        • any of beta.scan_base64(.file_name) where:
          • 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
      any(file.expand_archives(attachments).files)
        and
          or
            any(beta.scan_base64(file.expand_archives(attachments).files.file_name))
              beta.scan_base64(file.expand_archives(attachments).files.file_name) length_compare "10"
            file.expand_archives(attachments[]).files[].file_name contains "base64"
            file.expand_archives(attachments[]).files[].file_name contains "echo,"
            file.expand_archives(attachments[]).files[].file_name regex_match "\\bbash\\b"
          file.expand_archives(attachments[]).files[].file_name contains "{"
      or
        attachments.file_name contains "{"
         macro "attachments[].file_type in file_extensions_common_archives"
  attachments length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .file_extension in ('ics')
      • .scan.strings.raw matches '[\\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
  any(attachments)
    any(file.explode(attachments))
      and
        file.explode(attachments[])[].file_extension eq "ics"
        file.explode(attachments[])[].scan.strings.raw regex_match "[\\x{E0000}-\\x{E007F}\\x{E0100}-\\x{E01EF}\\x{2062}\\x{2064}]{8,}"
  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"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

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

Indicators

These rows show field, operator, and value matches.

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 of file.explode(.) where:
      • any of .scan.ics.calendars where:
        • any of .components where:
          • any of .organizers where:
            • 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)
    any(file.explode(attachments))
      any(file.explode(attachments).scan.ics.calendars)
        any(file.explode(attachments).scan.ics.calendars.components)
          any(file.explode(attachments).scan.ics.calendars.components.organizers)
            network.whois func_call "network.whois(file.explode(attachments[])[].scan.ics.calendars[].components[].organizers[].mailbox.email.domain).days_old < 90"
  attachments length_compare "0"
  type.inbound eq "true"
   macro "all(attachments)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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')
    • file.parse_text(.).text matches 'LOCATION[^:]*:.{1,300}google\\.com/url'
  3. any of ml.nlu_classifier(body.current_thread.text).topics where all hold:
    • .name is 'Request to View Invoice'
    • .confidence is '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"
      file.parse_text(attachments[]).text regex_match "LOCATION[^:]*:.{1,300}google\\.com/url"
  any(ml.nlu_classifier(body.current_thread.text).topics)
    and
      ml.nlu_classifier(body.current_thread.text).topics.confidence eq "high"
      ml.nlu_classifier(body.current_thread.text).topics.name eq "Request to View Invoice"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.url.urls where all hold:
        • any of:
          • .domain.domain in $free_file_hosts
          • all of:
            • .domain.root_domain in $free_subdomain_hosts
            • .domain.subdomain is set
            • none of:
              • .url ends with 'jpeg'
              • .url ends with 'png'
            • .domain.subdomain is not 'www'
        • any of ml.link_analysis(.).final_dom.links where:
          • any of .href_url.rewrite.encoders where:
            • . contains 'open_redirect'
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • any of distinct(headers.hops) where:
        • .authentication_results.dmarc matches '*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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          and
            or
              and
                not
                  or
                    file.explode(attachments[])[].scan.url.urls[].url ends_with "jpeg"
                    file.explode(attachments[])[].scan.url.urls[].url ends_with "png"
                file.explode(attachments[])[].scan.url.urls[].domain.subdomain is_not_null
                file.explode(attachments[])[].scan.url.urls[].domain.subdomain ne "www"
                 macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in free_subdomain_hosts"
               macro "file.explode(attachments[])[].scan.url.urls[].domain.domain in free_file_hosts"
            any(ml.link_analysis(file.explode(attachments).scan.url.urls).final_dom.links)
              any(ml.link_analysis(file.explode(attachments).scan.url.urls).final_dom.links.href_url.rewrite.encoders)
                ml.link_analysis(file.explode(attachments).scan.url.urls).final_dom.links.href_url.rewrite.encoders contains "open_redirect"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
  or
    and
      any(distinct(headers.hops))
        distinct(headers.hops).authentication_results.dmarc ends_with "fail"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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 is '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) is 0
        • all of recipients.to where:
          • .display_name is 'Undisclosed recipients'
      • length(recipients.cc) is 0
      • length(recipients.bcc) is 0
  6. any of attachments where all hold:
    • .file_type in $file_types_images
    • any of:
      • any of file.explode(.) where all hold:
        • not:
          • any of .scan.exiftool.fields where any holds:
            • .key is 'Model'
            • all of:
              • .key is 'Software'
              • .value starts with 'Android'
        • not:
          • any of .scan.exiftool.fields where all hold:
            • .key is 'DeviceManufacturer'
            • .value is 'Apple Computer Inc.'
        • not:
          • any of .scan.exiftool.fields where all hold:
            • .key is 'UserComment'
            • .value is 'Screenshot'
        • at least 4 of:
          • .scan.ocr.raw contains 'purchase'
          • .scan.ocr.raw contains 'payment'
          • .scan.ocr.raw contains 'transaction'
          • .scan.ocr.raw contains 'subscription'
          • .scan.ocr.raw contains 'antivirus'
          • .scan.ocr.raw contains 'order'
          • .scan.ocr.raw contains 'support'
          • .scan.ocr.raw contains 'help line'
          • .scan.ocr.raw contains 'receipt'
          • .scan.ocr.raw contains 'invoice'
          • .scan.ocr.raw contains 'call'
          • .scan.ocr.raw contains 'helpdesk'
          • .scan.ocr.raw contains 'cancel'
          • .scan.ocr.raw contains 'renew'
          • .scan.ocr.raw contains 'refund'
          • .scan.ocr.raw matches '(?:reach|contact) us at'
          • .scan.ocr.raw contains '+1'
          • .scan.ocr.raw contains 'amount'
          • .scan.ocr.raw contains 'charged'
          • .scan.ocr.raw contains 'crypto'
          • .scan.ocr.raw contains 'wallet address'
          • .scan.ocr.raw matches '\\$\\d{3}\\.\\d{2}\\b'
          • .scan.ocr.raw matches any of 2 patterns
            • \+?([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}
        • .scan.ocr.raw matches '(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 of ml.logo_detect(.).brands where:
        • .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
  any(attachments)
    and
      or
        any(file.explode(attachments))
          and
            not
              any(file.explode(attachments).scan.exiftool.fields)
                or
                  and
                    file.explode(attachments[])[].scan.exiftool.fields[].key eq "Software"
                    file.explode(attachments[])[].scan.exiftool.fields[].value starts_with "Android"
                  file.explode(attachments[])[].scan.exiftool.fields[].key eq "Model"
            not
              any(file.explode(attachments).scan.exiftool.fields)
                and
                  file.explode(attachments[])[].scan.exiftool.fields[].key eq "DeviceManufacturer"
                  file.explode(attachments[])[].scan.exiftool.fields[].value eq "Apple Computer Inc."
            not
              any(file.explode(attachments).scan.exiftool.fields)
                and
                  file.explode(attachments[])[].scan.exiftool.fields[].key eq "UserComment"
                  file.explode(attachments[])[].scan.exiftool.fields[].value eq "Screenshot"
            or
              file.explode(attachments[])[].scan.ocr.raw contains "+1"
              file.explode(attachments[])[].scan.ocr.raw contains "amount"
              file.explode(attachments[])[].scan.ocr.raw contains "antivirus"
              file.explode(attachments[])[].scan.ocr.raw contains "call"
              file.explode(attachments[])[].scan.ocr.raw contains "cancel"
              file.explode(attachments[])[].scan.ocr.raw contains "charged"
              file.explode(attachments[])[].scan.ocr.raw contains "crypto"
              file.explode(attachments[])[].scan.ocr.raw contains "help line"
              file.explode(attachments[])[].scan.ocr.raw contains "helpdesk"
              file.explode(attachments[])[].scan.ocr.raw contains "invoice"
              file.explode(attachments[])[].scan.ocr.raw contains "order"
              file.explode(attachments[])[].scan.ocr.raw contains "payment"
              file.explode(attachments[])[].scan.ocr.raw contains "purchase"
              file.explode(attachments[])[].scan.ocr.raw contains "receipt"
              file.explode(attachments[])[].scan.ocr.raw contains "refund"
              file.explode(attachments[])[].scan.ocr.raw contains "renew"
              file.explode(attachments[])[].scan.ocr.raw contains "subscription"
              file.explode(attachments[])[].scan.ocr.raw contains "support"
              file.explode(attachments[])[].scan.ocr.raw contains "transaction"
              file.explode(attachments[])[].scan.ocr.raw contains "wallet address"
              file.explode(attachments[])[].scan.ocr.raw regex_match "(?:reach|contact) us at"
              file.explode(attachments[])[].scan.ocr.raw regex_match "\\$\\d{3}\\.\\d{2}\\b"
              file.explode(attachments[])[].scan.ocr.raw regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
              file.explode(attachments[])[].scan.ocr.raw regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
            file.explode(attachments[])[].scan.ocr.raw regex_match "(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(attachments).brands)
          ml.logo_detect(attachments).brands.name in ["AT&T", "Ebay", "GeekSquad", "McAfee", "Norton", "PayPal"]
       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
      or
        recipients.to length_compare "0"
         macro "all(recipients.to)"
      recipients.bcc length_compare "0"
      recipients.cc length_compare "0"
    sender.email.domain.root_domain eq "onmicrosoft.com"
     macro "sender.email.domain.root_domain in free_email_providers"
  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"

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"

Indicators

These rows show field, operator, and value matches.

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) is 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 of ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics where all hold:
      • .name is 'Professional and Career Development'
      • .confidence is 'high'
  6. not:
    • any of attachments where all hold:
      • .file_type is 'pdf'
      • any of file.explode(.) where:
        • any of ml.nlu_classifier(.scan.ocr.raw).topics where all hold:
          • .name is 'Professional and Career Development'
          • .confidence is 'high'
  7. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any of file.explode(.) where all hold:
      • .depth is 0
      • .scan.exiftool.page_count < 3
      • any of:
        • not:
          • all of:
            • .scan.exiftool.producer starts with 'Aspose.Words for Java'
            • any of:
              • .scan.exiftool.creator is 'Anusha T'
              • any of .scan.exiftool.fields where all hold:
                • .key is 'Author'
                • .value is 'Anusha T'
        • .scan.exiftool.producer is missing
        • .scan.exiftool.creator is missing
    • any of:
      • any of file.explode(.) where all hold:
        • length(.scan.ocr.raw) > 60
        • at least 4 of:
          • .scan.ocr.raw contains 'purchase'
          • .scan.ocr.raw contains 'payment'
          • .scan.ocr.raw contains 'transaction'
          • .scan.ocr.raw contains 'subscription'
          • .scan.ocr.raw contains 'antivirus'
          • .scan.ocr.raw contains 'order'
          • .scan.ocr.raw contains 'support'
          • .scan.ocr.raw contains 'help line'
          • .scan.ocr.raw contains 'receipt'
          • .scan.ocr.raw contains 'invoice'
          • .scan.ocr.raw contains 'call'
          • .scan.ocr.raw contains 'helpdesk'
          • .scan.ocr.raw contains 'cancel'
          • .scan.ocr.raw contains 'renew'
          • .scan.ocr.raw contains 'refund'
          • .scan.ocr.raw matches '(?:reach|contact) us at'
          • .scan.ocr.raw contains '+1'
          • .scan.ocr.raw contains 'amount'
          • .scan.ocr.raw contains 'charged'
          • .scan.ocr.raw contains 'crypto'
          • .scan.ocr.raw contains 'wallet address'
          • .scan.ocr.raw matches '\\$\\d{3}\\.\\d{2}\\b'
          • .scan.ocr.raw matches any of 2 patterns
            • (\+[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}
        • any of:
          • .scan.ocr.raw matches '(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)'
          • .file_name matches 'INV(?:_|\\s)?\\d+(.pdf)$'
        • not:
          • at least 2 of 5: .scan.ocr.raw contains any of 5 patterns
            • opening balance
            • closing balance
            • direct debit
            • interest
            • account balance
      • any of ml.logo_detect(.).brands where:
        • .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) is 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
  any(attachments)
    and
      any(file.explode(attachments))
        and
          or
            not
              and
                or
                  any(file.explode(attachments).scan.exiftool.fields)
                    and
                      file.explode(attachments[])[].scan.exiftool.fields[].key eq "Author"
                      file.explode(attachments[])[].scan.exiftool.fields[].value eq "Anusha T"
                  file.explode(attachments[])[].scan.exiftool.creator eq "Anusha T"
                file.explode(attachments[])[].scan.exiftool.producer starts_with "Aspose.Words for Java"
            file.explode(attachments[])[].scan.exiftool.creator is_null
            file.explode(attachments[])[].scan.exiftool.producer is_null
          file.explode(attachments[])[].depth eq "0"
          file.explode(attachments[])[].scan.exiftool.page_count lt "3"
      or
        any(file.explode(attachments))
          and
            not
              or
                file.explode(attachments[])[].scan.ocr.raw contains "account balance"
                file.explode(attachments[])[].scan.ocr.raw contains "closing balance"
                file.explode(attachments[])[].scan.ocr.raw contains "direct debit"
                file.explode(attachments[])[].scan.ocr.raw contains "interest"
                file.explode(attachments[])[].scan.ocr.raw contains "opening balance"
            or
              attachments.file_name regex_match "INV(?:_|\\s)?\\d+(.pdf)$"
              file.explode(attachments[])[].scan.ocr.raw regex_match "(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)"
            or
              file.explode(attachments[])[].scan.ocr.raw contains "+1"
              file.explode(attachments[])[].scan.ocr.raw contains "amount"
              file.explode(attachments[])[].scan.ocr.raw contains "antivirus"
              file.explode(attachments[])[].scan.ocr.raw contains "call"
              file.explode(attachments[])[].scan.ocr.raw contains "cancel"
              file.explode(attachments[])[].scan.ocr.raw contains "charged"
              file.explode(attachments[])[].scan.ocr.raw contains "crypto"
              file.explode(attachments[])[].scan.ocr.raw contains "help line"
              file.explode(attachments[])[].scan.ocr.raw contains "helpdesk"
              file.explode(attachments[])[].scan.ocr.raw contains "invoice"
              file.explode(attachments[])[].scan.ocr.raw contains "order"
              file.explode(attachments[])[].scan.ocr.raw contains "payment"
              file.explode(attachments[])[].scan.ocr.raw contains "purchase"
              file.explode(attachments[])[].scan.ocr.raw contains "receipt"
              file.explode(attachments[])[].scan.ocr.raw contains "refund"
              file.explode(attachments[])[].scan.ocr.raw contains "renew"
              file.explode(attachments[])[].scan.ocr.raw contains "subscription"
              file.explode(attachments[])[].scan.ocr.raw contains "support"
              file.explode(attachments[])[].scan.ocr.raw contains "transaction"
              file.explode(attachments[])[].scan.ocr.raw contains "wallet address"
              file.explode(attachments[])[].scan.ocr.raw regex_match "(?:reach|contact) us at"
              file.explode(attachments[])[].scan.ocr.raw regex_match "(\\+[ilo0-9]|1.(\\()?[ilo0-9]{3}(\\))?\\D[ilo0-9]{3}\\D[ilo0-9]{4})"
              file.explode(attachments[])[].scan.ocr.raw regex_match "\\$\\d{3}\\.\\d{2}\\b"
              file.explode(attachments[])[].scan.ocr.raw regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
            file.explode(attachments[])[].scan.ocr.raw length_compare "60"
        any(ml.logo_detect(attachments).brands)
          ml.logo_detect(attachments).brands.name in ["AT&T", "Ebay", "GeekSquad", "McAfee", "Norton", "PayPal"]
      attachments.file_extension eq "pdf"
  not
    any(attachments)
      and
        any(file.explode(attachments))
          any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).topics)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].confidence eq "high"
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].name eq "Professional and Career Development"
        attachments.file_type eq "pdf"
  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(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics)
      and
        ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics.confidence eq "high"
        ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics.name eq "Professional and Career Development"
  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
       macro "all(recipients.to)"
       macro "sender.email.domain.root_domain in tranco_50k"
     macro "sender.email.domain.root_domain in free_email_providers"
  attachments length_compare "1"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
attachmentsarray_any(no value, null check)excludes:attachments
ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topicsarray_any(no value, null check)excludes:ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics

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
field:"type.inbound" kind:eq value:"true"

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) is 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)) is length(body.links)
  4. any of:
    • body.current_thread.text is missing
    • length(body.current_thread.text) < 50
  5. all of:
    • length(attachments) > 0
    • 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 of file.explode(.) where all hold:
      • any of:
        • .depth is 0
        • .flavors.mime is 'text/plain'
      • at least 4 of:
        • .scan.strings.raw contains 'purchase'
        • .scan.strings.raw contains 'payment'
        • .scan.strings.raw contains 'transaction'
        • .scan.strings.raw contains 'subscription'
        • .scan.strings.raw contains 'antivirus'
        • .scan.strings.raw contains 'order'
        • .scan.strings.raw contains 'support'
        • .scan.strings.raw contains 'help line'
        • .scan.strings.raw contains 'receipt'
        • .scan.strings.raw contains 'invoice'
        • .scan.strings.raw contains 'call'
        • .scan.strings.raw contains 'helpdesk'
        • .scan.strings.raw contains 'cancel'
        • .scan.strings.raw contains 'renew'
        • .scan.strings.raw contains 'refund'
        • .scan.strings.raw matches '(?:reach|contact) us at'
        • .scan.strings.raw contains '+1'
        • .scan.strings.raw contains 'amount'
        • .scan.strings.raw contains 'charged'
        • .scan.strings.raw contains 'crypto'
        • .scan.strings.raw contains 'wallet address'
        • .scan.strings.raw matches '\\$\\d{3}\\.\\d{2}\\b'
        • .scan.strings.raw matches any of 2 patterns
          • \+?([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}
      • .scan.strings.raw matches '(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 is not '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)

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
      any(file.explode(attachments))
        and
          or
            file.explode(attachments[])[].depth eq "0"
            file.explode(attachments[])[].flavors.mime eq "text/plain"
          or
            file.explode(attachments[])[].scan.strings.raw contains "+1"
            file.explode(attachments[])[].scan.strings.raw contains "amount"
            file.explode(attachments[])[].scan.strings.raw contains "antivirus"
            file.explode(attachments[])[].scan.strings.raw contains "call"
            file.explode(attachments[])[].scan.strings.raw contains "cancel"
            file.explode(attachments[])[].scan.strings.raw contains "charged"
            file.explode(attachments[])[].scan.strings.raw contains "crypto"
            file.explode(attachments[])[].scan.strings.raw contains "help line"
            file.explode(attachments[])[].scan.strings.raw contains "helpdesk"
            file.explode(attachments[])[].scan.strings.raw contains "invoice"
            file.explode(attachments[])[].scan.strings.raw contains "order"
            file.explode(attachments[])[].scan.strings.raw contains "payment"
            file.explode(attachments[])[].scan.strings.raw contains "purchase"
            file.explode(attachments[])[].scan.strings.raw contains "receipt"
            file.explode(attachments[])[].scan.strings.raw contains "refund"
            file.explode(attachments[])[].scan.strings.raw contains "renew"
            file.explode(attachments[])[].scan.strings.raw contains "subscription"
            file.explode(attachments[])[].scan.strings.raw contains "support"
            file.explode(attachments[])[].scan.strings.raw contains "transaction"
            file.explode(attachments[])[].scan.strings.raw contains "wallet address"
            file.explode(attachments[])[].scan.strings.raw regex_match "(?:reach|contact) us at"
            file.explode(attachments[])[].scan.strings.raw regex_match "\\$\\d{3}\\.\\d{2}\\b"
            file.explode(attachments[])[].scan.strings.raw regex_match "\\+?([ilo0-9]{1,2})?\\s?\\(?\\d{3}\\)?[\\s\\.\\-⋅]{0,5}[ilo0-9]{3}[\\s\\.\\-⋅]{0,5}[ilo0-9]{4}"
            file.explode(attachments[])[].scan.strings.raw regex_match "\\+?([ilo0-9]{1}.)?\\(?[ilo0-9]{3}?\\)?.[ilo0-9]{3}.?[ilo0-9]{4}"
          file.explode(attachments[])[].scan.strings.raw regex_match "(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)"
      or
        attachments.content_type eq "text/plain"
        attachments.file_type in ["doc", "docx", "xls", "xlsx"]
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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, .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)"
  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.

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 of filter(attachments) where all hold:
    • beta.parse_exif(.).author contains '@proton.me'
    • beta.parse_exif(.).producer is '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
  any(filter(attachments))
    and
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).producer == Canva"
      beta.parse_exif(filter(attachments)[]).author contains "@proton.me"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
        • .file_extension is '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
        any(file.explode(attachments))
          file.explode(attachments).file_extension eq "cmd"
         macro "attachments[].file_extension in file_extensions_common_archives"
      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
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 of map(...) where:
        • 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.valid
      • beta.parse_exif(.).title matches 'salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting'
    • any of:
      • any of file.explode(.) where:
        • any of [.scan.strings.raw, .scan.ocr.raw] where all hold:
          • . matches 'scan|camera|review and sign'
          • . matches '\\bQR\\b|Q\\.R\\.|barcode'
      • any of file.explode(.) where all hold:
        • .scan.qr.type is 'url'
        • .scan.qr.url.domain.valid
    • any of file.explode(.) where any holds:
      • any of [.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title] where:
        • . matches '\\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'
      • all of:
        • any of recipients.to where:
          • strings.contains(.scan.ocr.raw)
        • all of:
          • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
            • .name is 'cred_theft'
            • .confidence is not 'low'
          • any of ml.nlu_classifier(.scan.ocr.raw).topics where all hold:
            • .name in ('Benefit Enrollment', 'Financial Communications')
            • .confidence is not '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)
  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
      any(file.explode(attachments))
        or
          and
            any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
              and
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence ne "low"
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name eq "cred_theft"
            any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).topics)
              and
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].confidence ne "low"
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].name in ["Benefit Enrollment", "Financial Communications"]
            any(recipients.to)
              strings.contains func_call "strings.contains(file.explode(attachments[])[].scan.ocr.raw)"
          any([file.explode(attachments).scan.strings.raw, file.explode(attachments).scan.ocr.raw, file.explode(attachments).scan.exiftool.title])
            [file.explode(attachments).scan.strings.raw, file.explode(attachments).scan.ocr.raw, file.explode(attachments).scan.exiftool.title] regex_match "\\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
        any(file.explode(attachments))
          any([file.explode(attachments).scan.strings.raw, file.explode(attachments).scan.ocr.raw])
            and
              [file.explode(attachments[])[].scan.strings.raw, file.explode(attachments[])[].scan.ocr.raw][] regex_match "\\bQR\\b|Q\\.R\\.|barcode"
              [file.explode(attachments[])[].scan.strings.raw, file.explode(attachments[])[].scan.ocr.raw][] regex_match "scan|camera|review and sign"
        any(file.explode(attachments))
          and
            file.explode(attachments[])[].scan.qr.type eq "url"
            file.explode(attachments[])[].scan.qr.url.domain.valid eq "true"
      or
        any(recipients.to)
          and
            recipients.to.email.domain.valid eq "true"
            strings.icontains func_call "strings.icontains(attachments[].file_name)"
        attachments.file_name regex_match "salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting"
        beta.parse_exif(attachments[]).title regex_match "salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting"
  or
    and
      not
        coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
    any(map(...))
       macro "(length(body.current_thread.text) - length(map(...)[])) < 500"
    body.current_thread.text is_null
    body.current_thread.text length_compare "500"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

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 of map(...) where:
        • length(body.current_thread.text) - length(.) < 500
  3. any of filter(attachments) where all hold:
    • any of:
      • .file_name matches '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)'
      • any of recipients.to where all hold:
        • strings.icontains(.file_name)
        • .email.domain.valid
      • beta.parse_exif(.).title matches '(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)'
    • any of:
      • any of file.explode(.) where any holds:
        • any of [.scan.strings.raw, .scan.ocr.raw] where all hold:
          • . matches 'scan|camera|review and sign'
          • . matches '\\bQR\\b|Q\\.R\\.|barcode'
        • all of:
          • .scan.qr.type is 'url'
          • .scan.qr.url.url is set
          • any of recipients.to where all hold:
            • .email.domain.valid
            • any of:
              • strings.icontains(.scan.qr.url.url)
              • any of strings.scan_base64(.scan.qr.url.url) where:
                • strings.icontains(.)
      • any of file.explode(.) where all hold:
        • .scan.qr.type is 'url'
        • .scan.qr.url.domain.valid
    • any of file.explode(.) where any holds:
      • any of [.scan.strings.raw, .scan.ocr.raw, .scan.exiftool.title] where:
        • . matches '\\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'
      • all of:
        • any of recipients.to where:
          • strings.contains(.scan.ocr.raw)
        • all of:
          • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
            • .name is 'cred_theft'
            • .confidence is not 'low'
          • any of ml.nlu_classifier(.scan.ocr.raw).topics where all hold:
            • .name in ('Benefit Enrollment', 'Financial Communications')
            • .confidence is not 'low'
  4. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass)

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
  any(filter(attachments))
    and
      or
        any(file.explode(filter(attachments)))
          or
            and
              any(recipients.to)
                and
                  or
                    any(strings.scan_base64(file.explode(filter(attachments)).scan.qr.url.url))
                      strings.icontains func_call "strings.icontains(strings.scan_base64(file.explode(filter(attachments)[])[].scan.qr.url.url)[])"
                    strings.icontains func_call "strings.icontains(file.explode(filter(attachments)[])[].scan.qr.url.url)"
                  recipients.to.email.domain.valid eq "true"
              file.explode(filter(attachments)[])[].scan.qr.type eq "url"
              file.explode(filter(attachments)[])[].scan.qr.url.url is_not_null
            any([file.explode(filter(attachments)).scan.strings.raw, file.explode(filter(attachments)).scan.ocr.raw])
              and
                [file.explode(filter(attachments)[])[].scan.strings.raw, file.explode(filter(attachments)[])[].scan.ocr.raw][] regex_match "\\bQR\\b|Q\\.R\\.|barcode"
                [file.explode(filter(attachments)[])[].scan.strings.raw, file.explode(filter(attachments)[])[].scan.ocr.raw][] regex_match "scan|camera|review and sign"
        any(file.explode(filter(attachments)))
          and
            file.explode(filter(attachments)[])[].scan.qr.type eq "url"
            file.explode(filter(attachments)[])[].scan.qr.url.domain.valid eq "true"
      any(file.explode(filter(attachments)))
        or
          and
            any(ml.nlu_classifier(file.explode(filter(attachments)).scan.ocr.raw).intents)
              and
                ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].confidence ne "low"
                ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].name eq "cred_theft"
            any(ml.nlu_classifier(file.explode(filter(attachments)).scan.ocr.raw).topics)
              and
                ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).topics[].confidence ne "low"
                ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).topics[].name in ["Benefit Enrollment", "Financial Communications"]
            any(recipients.to)
              strings.contains func_call "strings.contains(file.explode(filter(attachments)[])[].scan.ocr.raw)"
          any([file.explode(filter(attachments)).scan.strings.raw, file.explode(filter(attachments)).scan.ocr.raw, file.explode(filter(attachments)).scan.exiftool.title])
            [file.explode(filter(attachments)).scan.strings.raw, file.explode(filter(attachments)).scan.ocr.raw, file.explode(filter(attachments)).scan.exiftool.title] regex_match "\\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
        any(recipients.to)
          and
            recipients.to.email.domain.valid eq "true"
            strings.icontains func_call "strings.icontains(filter(attachments)[].file_name)"
        beta.parse_exif(filter(attachments)[]).title regex_match "(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)"
        filter(attachments).file_name regex_match "(?:salary|pay(?:roll)|bonus|comp(?:ensation|liance|\\b)|remuneration|disbursement|incentive|merit|vesting|employee.*(?:reward|benefit)s?)"
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  or
    any(map(...))
       macro "(length(body.current_thread.text) - length(map(...)[])) < 500"
    body.current_thread.text is_null
    body.current_thread.text length_compare "500"
  filter(attachments, .file_type == 'docx') length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

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 of ml.nlu_classifier(body.current_thread.text).topics where:
      • .name in ('Advertising and Promotions')
  3. any of attachments where:
    • any of file.explode(.) where:
      • at least 3 of 11: .scan.strings.raw matches any of 11 patterns
        • Credit Card Application
        • Date of Birth
        • [eE]mail
        • [aA]ddress
        • Contact No
        • Pan No
        • ADHAAR
        • Annual.*salary
        • Mother Name
        • Father Name
        • SINGLE.*MARRIED
  4. any of:
    • body.current_thread.text matches 'whatsapp'
    • any of attachments where:
      • any of file.explode(.) where:
        • .scan.qr.url.url matches 'wa\\\\.me'
    • any of file.explode(...) where:
      • .scan.qr.url.url matches '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)
      any(file.explode(attachments))
        file.explode(attachments).scan.qr.url.url regex_match "wa\\\\.me"
    any(file.explode(...))
      file.explode(...).scan.qr.url.url regex_match "wa\\\\.me"
    body.current_thread.text regex_match "whatsapp"
  any(attachments)
    any(file.explode(attachments))
      or
        file.explode(attachments[])[].scan.strings.raw regex_match "ADHAAR"
        file.explode(attachments[])[].scan.strings.raw regex_match "Annual.*salary"
        file.explode(attachments[])[].scan.strings.raw regex_match "Contact No"
        file.explode(attachments[])[].scan.strings.raw regex_match "Credit Card Application"
        file.explode(attachments[])[].scan.strings.raw regex_match "Date of Birth"
        file.explode(attachments[])[].scan.strings.raw regex_match "Father Name"
        file.explode(attachments[])[].scan.strings.raw regex_match "Mother Name"
        file.explode(attachments[])[].scan.strings.raw regex_match "Pan No"
        file.explode(attachments[])[].scan.strings.raw regex_match "SINGLE.*MARRIED"
        file.explode(attachments[])[].scan.strings.raw regex_match "[aA]ddress"
        file.explode(attachments[])[].scan.strings.raw regex_match "[eE]mail"
  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(ml.nlu_classifier(body.current_thread.text).topics)
    ml.nlu_classifier(body.current_thread.text).topics.name eq "Advertising and Promotions"
  type.inbound eq "true"

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
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 of file.explode(.) where all hold:
      • any of .scan.strings.strings where:
        • . matches '*\\fonttbl*'
      • 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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "\\fonttbl"
          filter(file.explode(attachments[])[].scan.strings.strings, strings.ilike(file.explode(attachments[])[], '{\\f*;}')) length_compare "10000"
      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"]
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of:
        • .scan.exiftool.producer is 'DocFly'
        • any of .scan.exiftool.fields where all hold:
          • .key is 'XMPToolkit'
          • .value contains 'DynaPDF'
      • any of:
        • any of .scan.exiftool.fields where all hold:
          • .key is 'CreatorTool'
          • .value is 'Acrobat PDFMaker 24 for Word'
        • any of .scan.exiftool.fields where all hold:
          • .key is 'ContentTypeId'
          • .value is '2.2388136001807807e+43'
        • any of .scan.exiftool.fields where all hold:
          • .key is 'Creator'
          • .value in ('Julie Peters', 'Julie Pieters')
        • any of .scan.exiftool.fields where all hold:
          • .key is 'Author'
          • .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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).scan.exiftool.fields)
              and
                file.explode(attachments[])[].scan.exiftool.fields[].key eq "Author"
                file.explode(attachments[])[].scan.exiftool.fields[].value in ["Julie Peters", "Julie Pieters"]
            any(file.explode(attachments).scan.exiftool.fields)
              and
                file.explode(attachments[])[].scan.exiftool.fields[].key eq "ContentTypeId"
                file.explode(attachments[])[].scan.exiftool.fields[].value eq "2.2388136001807807e+43"
            any(file.explode(attachments).scan.exiftool.fields)
              and
                file.explode(attachments[])[].scan.exiftool.fields[].key eq "Creator"
                file.explode(attachments[])[].scan.exiftool.fields[].value in ["Julie Peters", "Julie Pieters"]
            any(file.explode(attachments).scan.exiftool.fields)
              and
                file.explode(attachments[])[].scan.exiftool.fields[].key eq "CreatorTool"
                file.explode(attachments[])[].scan.exiftool.fields[].value eq "Acrobat PDFMaker 24 for Word"
          or
            any(file.explode(attachments).scan.exiftool.fields)
              and
                file.explode(attachments[])[].scan.exiftool.fields[].key eq "XMPToolkit"
                file.explode(attachments[])[].scan.exiftool.fields[].value contains "DynaPDF"
            file.explode(attachments[])[].scan.exiftool.producer eq "DocFly"
      attachments.file_extension eq "pdf"
      attachments.size le "250000"
  attachments length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of ml.logo_detect(.).brands where:
      • .name is 'DocuSign'
    • any of file.explode(.) where:
      • any of .scan.pdf.urls where:
        • 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"
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.pdf.urls)
          network.whois func_call "network.whois(file.explode(attachments[])[].scan.pdf.urls[].domain).days_old <= 3"
      any(ml.logo_detect(attachments).brands)
        ml.logo_detect(attachments).brands.name eq "DocuSign"
      attachments.file_type eq "pdf"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
      • .file_extension in ('doc', 'docm', 'docx', 'dot', 'dotm', 'xls', 'xlsx', 'xlsm', 'xlm', 'xlsb', 'xlt', 'xltm', 'ppt', 'pptx', 'pptm', 'ppsm')
      • any of:
        • any of .flavors.yara where:
          • . is 'base64_pe'
        • any of .scan.strings.strings where:
          • . matches '*.createObjectURL(*)*'
        • any of .scan.strings.strings where:
          • . matches '*.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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).flavors.yara)
              file.explode(attachments).flavors.yara eq "base64_pe"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings wildcard "*.createObjectURL(*)*"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings wildcard "*.msSaveOrOpenBlob(*)*"
          file.explode(attachments[])[].file_extension in ["doc", "docm", "docx", "dot", "dotm", "ppsm", "ppt", "pptm", "pptx", "xlm", "xls", "xlsb", "xlsm", "xlsx", "xlt", "xltm"]
      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"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: DOCX with hyperlink targeting recipient address

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

Detects DOCX attachments containing hyperlinks with anchor references that match recipient email addresses. This technique is commonly used to personalize malicious documents and evade detection.

Threat classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesEvasion, 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_extension in ('docx', 'docm')),
        any(filter(file.explode(.),
                   strings.icontains(.scan.strings.raw, '<w:hyperlink')
            ),
            any(regex.iextract(.scan.strings.raw,
                               '<w:hyperlink[^\>]*w:anchor="(?P<email_address>[^\"]+)"'
                ),
                .named_groups["email_address"] == recipients.to[0].email.email
                or any(strings.scan_base64(.named_groups["email_address"],
                                           ignore_padding=true
                       ),
                       strings.icontains(., recipients.to[0].email.email)
                )
            )
        )
)

Detection logic

Scope: inbound message.

Detects DOCX attachments containing hyperlinks with anchor references that match recipient email addresses. This technique is commonly used to personalize malicious documents and evade detection.

  1. inbound message
  2. any of filter(attachments) where:
    • any of filter(...) where:
      • any of regex.iextract(.scan.strings.raw) where any holds:
        • .named_groups['email_address'] is recipients.to[0].email.email
        • any of strings.scan_base64(.named_groups['email_address']) where:
          • strings.icontains(.)

Inspects: attachments[].file_extension, recipients.to[0].email.email, type.inbound. Sensors: file.explode, regex.iextract, strings.icontains, strings.scan_base64.

Indicators matched (4)

FieldMatchValue
attachments[].file_extensionmemberdocx
attachments[].file_extensionmemberdocm
strings.icontainssubstring<w:hyperlink
regex.iextractregex<w:hyperlink[^\>]*w:anchor="(?P<email_address>[^\"]+)"

Stages and Predicates

Stage 1: mql_rule

and
  any(filter(attachments))
    any(filter(...))
      any(regex.iextract(filter(...).scan.strings.raw))
        or
          any(strings.scan_base64(regex.iextract(filter(...).scan.strings.raw).named_groups['email_address']))
            strings.icontains func_call "strings.icontains(strings.scan_base64(regex.iextract(filter(...)[].scan.strings.raw)[].named_groups['email_address'])[])"
          regex.iextract(filter(...)[].scan.strings.raw)[].named_groups['email_address'] cross_field_compare "recipients.to[0].email.email"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "malicious_docx_document_template_artifacts"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches any of 6 patterns
          • *VUVzREJCUUFBUUFJQ*
          • *VFc0RCQlFBQVFBSU*
          • *VRXNEQkJRQUFRQUlB*
          • *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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          or
            file.explode(attachments[])[].scan.strings.strings[] match "BlUQRFUQRJkQENXRV"
            file.explode(attachments[])[].scan.strings.strings[] match "QJFUUBFUUCJERzVUV"
            file.explode(attachments[])[].scan.strings.strings[] match "USBFVQBFlQCR0cFV"
            file.explode(attachments[])[].scan.strings.strings[] match "VFc0RCQlFBQVFBSU"
            file.explode(attachments[])[].scan.strings.strings[] match "VRXNEQkJRQUFRQUlB"
            file.explode(attachments[])[].scan.strings.strings[] match "VUVzREJCUUFBUUFJQ"
      attachments.file_extension in ["htm", "html"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: Dropbox image lure with no Dropbox domains in links

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

Detects Dropbox phishing emails with no Dropbox links with image attachments from an untrusted sender.

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

Rule body

type.inbound
and length(filter(attachments, .file_type not in $file_types_images)) == 0
and any(body.links,
        not strings.ilike(.href_url.domain.root_domain, "dropbox.*")
)
and any(attachments,
        .file_type in $file_types_images
        and any(file.explode(.),
                strings.ilike(.scan.ocr.raw, "*dropbox*")
                and strings.ilike(.scan.ocr.raw, "*review*", "*sign*")
        )
)
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 Dropbox phishing emails with no Dropbox links with image attachments from an untrusted sender.

  1. inbound message
  2. length(filter(attachments, .file_type not in $file_types_images)) is 0
  3. any of body.links where:
    • not:
      • .href_url.domain.root_domain matches 'dropbox.*'
  4. any of attachments where all hold:
    • .file_type in $file_types_images
    • any of file.explode(.) where all hold:
      • .scan.ocr.raw matches '*dropbox*'
      • .scan.ocr.raw matches any of 2 patterns
        • *review*
        • *sign*
  5. any of:
    • not:
      • profile.by_sender().solicited
    • profile.by_sender().any_messages_malicious_or_spam
  6. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].file_type, body.links, body.links[].href_url.domain.root_domain, type.inbound. Sensors: file.explode, profile.by_sender, strings.ilike. Reference lists: $file_types_images.

Indicators matched (3)

FieldMatchValue
strings.ilikesubstring*dropbox*
strings.ilikesubstring*review*
strings.ilikesubstring*sign*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        and
          or
            file.explode(attachments[])[].scan.ocr.raw match "review"
            file.explode(attachments[])[].scan.ocr.raw match "sign"
          file.explode(attachments[])[].scan.ocr.raw match "dropbox"
       macro "attachments[].file_type in file_types_images"
  any(body.links)
    not
      body.links.href_url.domain.root_domain starts_with "dropbox."
  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"
  filter(attachments, .file_type not in $file_types_images) length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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:
      • beta.parse_exif(.).page_count > 1
      • beta.parse_exif(.).page_count ≤ 3
    • beta.ocr(.).page_results[0].text is not ''
    • any of regex.iextract(...) where all hold:
      • .named_groups['page_1_3_lines'] is not ''
      • any of:
        • any of regex.iextract(...) where:
          • strings.levenshtein(.named_groups['page_2_3_lines']) ≤ 5
        • any of regex.iextract(...) where:
          • strings.levenshtein(.named_groups['page_3_3_lines']) ≤ 5
    • at least 3 of 29: beta.ocr(.).text contains any of 29 patterns
      • 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
      • 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
      • 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
      • 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
      any(regex.iextract(...))
        and
          or
            any(regex.iextract(...))
              strings.levenshtein func_call "strings.levenshtein(regex.iextract(...)[].named_groups['page_2_3_lines']) <= 5"
            any(regex.iextract(...))
              strings.levenshtein func_call "strings.levenshtein(regex.iextract(...)[].named_groups['page_3_3_lines']) <= 5"
          regex.iextract(...).named_groups['page_1_3_lines'] ne ""
      or
        beta.ocr(attachments[]).text contains "100% payment made in the form"
        beta.ocr(attachments[]).text contains "80/20 preference point system"
        beta.ocr(attachments[]).text contains "80:20"
        beta.ocr(attachments[]).text contains "Authorized Signature"
        beta.ocr(attachments[]).text contains "COMPULSORY BIDDERS MUST QUOTE"
        beta.ocr(attachments[]).text contains "Closing Date"
        beta.ocr(attachments[]).text contains "Closing Time and Date"
        beta.ocr(attachments[]).text contains "Conditions for Release of Payment"
        beta.ocr(attachments[]).text contains "Contact Person"
        beta.ocr(attachments[]).text contains "Date Issued"
        beta.ocr(attachments[]).text contains "Date of issue"
        beta.ocr(attachments[]).text contains "If unable to quote"
        beta.ocr(attachments[]).text contains "Method of RFQ Submission"
        beta.ocr(attachments[]).text contains "Must be inclusive"
        beta.ocr(attachments[]).text contains "Name and Capacity"
        beta.ocr(attachments[]).text contains "PRICING QUOTATION"
        beta.ocr(attachments[]).text contains "Partial Bids"
        beta.ocr(attachments[]).text contains "Payment Terms and Conditions"
        beta.ocr(attachments[]).text contains "Period of Validity of Quotes"
        beta.ocr(attachments[]).text contains "QUOTATIONS ARE HEREBY INVITED FOR THE SUPPLY OF"
        beta.ocr(attachments[]).text contains "Selection of suppliers will be based on"
        beta.ocr(attachments[]).text contains "Tax on Price Quotation"
        beta.ocr(attachments[]).text contains "This is not a Purchase Order"
        beta.ocr(attachments[]).text contains "freight, insurance until acceptance"
        beta.ocr(attachments[]).text contains "must be completed and accompanied by"
        beta.ocr(attachments[]).text contains "plant maintenance"
        beta.ocr(attachments[]).text contains "plant upgrade and maintenance"
        beta.ocr(attachments[]).text contains "remain binding upon me/us"
        beta.ocr(attachments[]).text contains "without an Official Purchase Order"
      attachments.file_type eq "pdf"
      beta.ocr func_call "beta.ocr(attachments[]).page_results[0].text != "
      beta.parse_exif func_call "beta.parse_exif(attachments[]).page_count <= 3"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).page_count > 1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . contains '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)
    any(file.explode(attachments))
      any(file.explode(attachments).scan.strings.strings)
        file.explode(attachments).scan.strings.strings contains "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
  any(attachments)
    attachments.file_name contains "eicar"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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:
        • file.parse_text(., encodings=['ascii', 'utf8', 'utf16-le']).text matches any of 9 patterns
          • *onload*
          • *window.location.href*
          • *onerror*
          • *CDATA*
          • *<script*
          • *</script*
          • *atob*
          • *location.assign*
          • *decodeURIComponent*
        • file.parse_text(., encodings=['ascii', 'utf8', 'utf16-le']).text matches '<iframe[^\\>]+src\\s*=\\s*\\"data:[^\\;]+;base64,'
        • any of beta.scan_base64(...) where:
          • . matches any of 9 patterns
            • *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 of file.explode(.) where all hold:
        • any of:
          • .file_extension in ('svg', 'svgz')
          • .flavors.mime is 'image/svg+xml'
        • any of .scan.strings.strings where:
          • . matches any of 9 patterns
            • *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
        any(file.explode(attachments))
          and
            any(file.explode(attachments).scan.strings.strings)
              or
                file.explode(attachments[])[].scan.strings.strings[] match "</script"
                file.explode(attachments[])[].scan.strings.strings[] match "<script"
                file.explode(attachments[])[].scan.strings.strings[] match "CDATA"
                file.explode(attachments[])[].scan.strings.strings[] match "atob"
                file.explode(attachments[])[].scan.strings.strings[] match "decodeURIComponent"
                file.explode(attachments[])[].scan.strings.strings[] match "location.assign"
                file.explode(attachments[])[].scan.strings.strings[] match "onerror"
                file.explode(attachments[])[].scan.strings.strings[] match "onload"
                file.explode(attachments[])[].scan.strings.strings[] match "window.location.href"
            or
              file.explode(attachments[])[].file_extension in ["svg", "svgz"]
              file.explode(attachments[])[].flavors.mime eq "image/svg+xml"
        or
          attachments.content_type eq "application/x-gzip"
          attachments.file_type eq "gz"
           macro "attachments[].file_extension in file_extensions_common_archives"
      and
        or
          any(beta.scan_base64(...))
            or
              beta.scan_base64(...) match "</script"
              beta.scan_base64(...) match "<script"
              beta.scan_base64(...) match "CDATA"
              beta.scan_base64(...) match "atob"
              beta.scan_base64(...) match "decodeURIComponent"
              beta.scan_base64(...) match "location.assign"
              beta.scan_base64(...) match "onerror"
              beta.scan_base64(...) match "onload"
              beta.scan_base64(...) match "window.location.href"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "</script"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "<script"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "CDATA"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "atob"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "decodeURIComponent"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "location.assign"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "onerror"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "onload"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "window.location.href"
          file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text regex_match "<iframe[^\\>]+src\\s*=\\s*\\\"data:[^\\;]+;base64,"
        or
          attachments.content_type eq "image/svg+xml"
          attachments.file_extension in ["svg", "svgz"]
          attachments.file_type eq "svg"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • .file_extension is 'mht'
    • any of file.explode(.) where:
      • any of .scan.html.scripts where:
        • .language is '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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.html.scripts)
          file.explode(attachments).scan.html.scripts.language eq "VBScript"
      or
        attachments.file_extension eq "mht"
         macro "attachments[].file_extension in file_extensions_common_archives"
      any(file.explode(attachments))
        file.explode(attachments).file_extension eq "mht"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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'
    • file.parse_eml(.).body.html.raw matches '*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"
      file.parse_eml(attachments[]).body.html.raw wildcard "*script*data:text/html;base64*"
  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"

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"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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) is 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 of file.explode(.) where any holds:
      • length(filter(.scan.javascript.strings, strings.ilike(., '*username*', '*login-form*', '*email-form*', '*Incorrect password. Please try again.*', '*Password Incomplete, please try again*'))) ≥ 3
      • all of:
        • .flavors.mime in ('text/html', 'text/plain')
        • at least 3 of:
          • any of .scan.strings.strings where:
            • . matches '*username*'
          • any of .scan.strings.strings where:
            • . matches '*login-form*'
          • any of .scan.strings.strings where:
            • . matches '*email-form*'
          • any of .scan.strings.strings where:
            • . matches '*Incorrect password. Please try again.*'
          • any of .scan.strings.strings where:
            • . matches '*Password Incomplete, please try again*'
      • at least 2 of:
        • any of .scan.strings.strings where:
          • . matches '*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*'
        • any of .scan.strings.strings where:
          • . matches '*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*'
        • any of .scan.strings.strings where:
          • . matches '*&#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
  any(attachments)
    and
      any(file.explode(attachments))
        or
          and
            or
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "Incorrect password. Please try again."
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "Password Incomplete, please try again"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "email-form"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "login-form"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "username"
            file.explode(attachments[])[].flavors.mime in ["text/html", "text/plain"]
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "&#83;&#105;&#103;&#110;&#32;&#105;&#110"
          filter(file.explode(attachments[])[].scan.javascript.strings, strings.ilike(file.explode(attachments[])[], '*username*', '*login-form*', '*email-form*', '*Incorrect password. Please try again.*', '*Password Incomplete, please try again*')) length_compare "3"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
  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"
  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"

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:).*"

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
field:"type.inbound" kind:eq value:"true"

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 of file.parse_eml(.).attachments where any holds:
      • .file_name matches '*htm*'
      • .file_type is 'html'
      • any of file.explode(.) where:
        • .flavors.mime is '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)
  8. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • coalesce(headers.auth_summary.dmarc.pass)
    • 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
  any(attachments)
    and
      any(file.parse_eml(attachments).attachments)
        or
          any(file.explode(file.parse_eml(attachments).attachments))
            file.explode(file.parse_eml(attachments).attachments).flavors.mime eq "text/html"
          file.parse_eml(attachments[]).attachments[].file_name match "htm"
          file.parse_eml(attachments[]).attachments[].file_type eq "html"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
  or
    and
      not
        coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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
        coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  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"

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:)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: EML file with IPFS links

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

Attached EML uses engaging language and IPFS links were detected in the EML file. IPFS has been recently observed hosting phishing sites.

Threat classification

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

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

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 in ('eml'))
        and any(file.explode(.),
                any(.scan.url.urls,
                    strings.icontains(ml.link_analysis(.).effective_url.url,
                                      'ipfs'
                    )
                    or (
                      regex.icontains(ml.link_analysis(.).effective_url.path,
                                      '[\.-/]ipfs|ipfs[\.-/]'
                      )
                      and ml.link_analysis(.).effective_url.domain.domain not in $org_domains
                      and (
                        (
                          // don't include high rep domains
                          ml.link_analysis(.).effective_url.domain.domain not in $tranco_1m
                          and ml.link_analysis(.).effective_url.domain.domain not in $umbrella_1m
                        )
                        // if it's in Tranco or Umbrella, still include it if it's one of these
                        or ml.link_analysis(.).effective_url.domain.domain in $free_file_hosts
                        or ml.link_analysis(.).effective_url.domain.root_domain in $free_file_hosts
                        or ml.link_analysis(.).effective_url.domain.root_domain in $free_subdomain_hosts
                      )
                    )
                )
        )
)

Detection logic

Scope: inbound message.

Attached EML uses engaging language and IPFS links were detected in the EML file. IPFS has been recently observed hosting phishing sites.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension in ('eml')
    • any of file.explode(.) where:
      • any of .scan.url.urls where any holds:
        • ml.link_analysis(.).effective_url.url contains 'ipfs'
        • all of:
          • ml.link_analysis(.).effective_url.path matches '[\\.-/]ipfs|ipfs[\\.-/]'
          • ml.link_analysis(.).effective_url.domain.domain not in $org_domains
          • any of:
            • all of:
              • ml.link_analysis(.).effective_url.domain.domain not in $tranco_1m
              • ml.link_analysis(.).effective_url.domain.domain not in $umbrella_1m
            • ml.link_analysis(.).effective_url.domain.domain in $free_file_hosts
            • ml.link_analysis(.).effective_url.domain.root_domain in $free_file_hosts
            • ml.link_analysis(.).effective_url.domain.root_domain in $free_subdomain_hosts

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: file.explode, ml.link_analysis, regex.icontains, strings.icontains. Reference lists: $free_file_hosts, $free_subdomain_hosts, $org_domains, $tranco_1m, $umbrella_1m.

Indicators matched (4)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionmembereml
strings.icontainssubstringipfs
regex.icontainsregex[\.-/]ipfs|ipfs[\.-/]

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          or
            and
              or
                and
                  ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.domain.domain not in tranco_1m"
                  ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.domain.domain not in umbrella_1m"
                ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.domain.domain in free_file_hosts"
                ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.domain.root_domain in free_file_hosts"
                ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.domain.root_domain in free_subdomain_hosts"
              ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.domain.domain not in org_domains"
              ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.path regex_match "[\\.-/]ipfs|ipfs[\\.-/]"
            ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.url contains "ipfs"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.parse_eml(.).attachments where any holds:
      • .file_extension in ('svg', 'svgz')
      • all of:
        • .file_type is 'svg'
        • any of:
          • any of:
            • file.parse_text(., encodings=['ascii', 'utf8', 'utf16-le']).text matches any of 9 patterns
              • *onload*
              • *window.location.href*
              • *onerror*
              • *CDATA*
              • *<script*
              • *</script*
              • *atob*
              • *location.assign*
              • *decodeURIComponent*
            • file.parse_text(., encodings=['ascii', 'utf8', 'utf16-le']).text matches '<iframe[^\\>]+src\\s*=\\s*\\"data:[^\\;]+;base64,'
            • any of beta.scan_base64(...) where:
              • . matches any of 9 patterns
                • *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 of file.explode(.) where all hold:
              • any of:
                • .file_extension in ('svg', 'svgz')
                • .flavors.mime is 'image/svg+xml'
              • any of .scan.strings.strings where:
                • . matches any of 9 patterns
                  • *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
      any(file.parse_eml(attachments).attachments)
        or
          and
            or
              and
                any(file.explode(file.parse_eml(attachments).attachments))
                  and
                    any(file.explode(file.parse_eml(attachments).attachments).scan.strings.strings)
                      or
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "</script"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "<script"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "CDATA"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "atob"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "decodeURIComponent"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "location.assign"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "onerror"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "onload"
                        file.explode(file.parse_eml(attachments[]).attachments[])[].scan.strings.strings[] match "window.location.href"
                    or
                      file.explode(file.parse_eml(attachments[]).attachments[])[].file_extension in ["svg", "svgz"]
                      file.explode(file.parse_eml(attachments[]).attachments[])[].flavors.mime eq "image/svg+xml"
                or
                  file.parse_eml(attachments[]).attachments[].content_type eq "application/x-gzip"
                  file.parse_eml(attachments[]).attachments[].file_type eq "gz"
                   macro "file.parse_eml(attachments[]).attachments[].file_extension in file_extensions_common_archives"
              any(beta.scan_base64(...))
                or
                  beta.scan_base64(...) match "</script"
                  beta.scan_base64(...) match "<script"
                  beta.scan_base64(...) match "CDATA"
                  beta.scan_base64(...) match "atob"
                  beta.scan_base64(...) match "decodeURIComponent"
                  beta.scan_base64(...) match "location.assign"
                  beta.scan_base64(...) match "onerror"
                  beta.scan_base64(...) match "onload"
                  beta.scan_base64(...) match "window.location.href"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "</script"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "<script"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "CDATA"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "atob"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "decodeURIComponent"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "location.assign"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "onerror"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "onload"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text match "window.location.href"
              file.parse_text(file.parse_eml(attachments[]).attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text regex_match "<iframe[^\\>]+src\\s*=\\s*\\\"data:[^\\;]+;base64,"
            file.parse_eml(attachments[]).attachments[].file_type eq "svg"
          file.parse_eml(attachments[]).attachments[].file_extension in ["svg", "svgz"]
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of filter(...) where:
      • any of file.explode(.) where any holds:
        • any of .flavors.yara where:
          • . is 'encrypted_zip'
        • .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
  any(filter(attachments))
    any(filter(...))
      any(file.explode(filter(...)))
        or
          any(file.explode(filter(...)).flavors.yara)
            file.explode(filter(...)).flavors.yara eq "encrypted_zip"
          file.explode(filter(...)[])[].scan.zip.encrypted eq "true"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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) is 1
  3. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension is 'eml'
    • any of file.parse_eml(.).body.links where any holds:
      • all of:
        • ml.link_analysis(.).credphish.disposition is 'phishing'
        • ml.link_analysis(.).credphish.confidence in ('medium', 'high')
      • any of ml.link_analysis(.).final_dom.links where any holds:
        • .href_url.domain.tld in $suspicious_tlds
        • ml.link_analysis(.href_url).effective_url.domain.tld in $suspicious_tlds
      • any of ml.link_analysis(., mode='aggressive').redirect_history where:
        • .domain.tld in $suspicious_tlds
      • all of:
        • length(distinct(map(ml.link_analysis(., mode='aggressive').redirect_history, .domain.tld))) ≥ 2
        • length(distinct(map(ml.link_analysis(., mode='aggressive').redirect_history, .domain.domain))) ≥ 3
    • any of:
      • any of ml.nlu_classifier(body.current_thread.text).entities where:
        • .name is 'request'
      • any of ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).entities where:
        • .name is 'request'
      • any of recipients.to where all hold:
        • .email.domain.sld in $org_slds
        • any of:
          • strings.icontains(subject.subject)
          • strings.icontains(sender.display_name)
      • 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 of $suspicious_subjects where:
        • 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
      any(file.parse_eml(attachments).body.links)
        or
          any(ml.link_analysis(file.parse_eml(attachments).body.links).final_dom.links)
            or
              ml.link_analysis func_call "ml.link_analysis(ml.link_analysis(file.parse_eml(attachments[]).body.links[]).final_dom.links[].href_url).effective_url.domain.tld in suspicious_tlds"
               macro "ml.link_analysis(file.parse_eml(attachments[]).body.links[]).final_dom.links[].href_url.domain.tld in suspicious_tlds"
          and
            distinct(map(ml.link_analysis(file.parse_eml(attachments[]).body.links[], mode='aggressive').redirect_history, file.parse_eml(attachments[]).body.links[].domain.domain)) length_compare "3"
            distinct(map(ml.link_analysis(file.parse_eml(attachments[]).body.links[], mode='aggressive').redirect_history, file.parse_eml(attachments[]).body.links[].domain.tld)) length_compare "2"
          and
            ml.link_analysis func_call "ml.link_analysis(file.parse_eml(attachments[]).body.links[]).credphish.confidence in (medium, high)"
            ml.link_analysis func_call "ml.link_analysis(file.parse_eml(attachments[]).body.links[]).credphish.disposition == phishing"
          any(ml.link_analysis(file.parse_eml(attachments).body.links, mode='aggressive').redirect_history)
             macro "ml.link_analysis(file.parse_eml(attachments[]).body.links[], mode='aggressive').redirect_history[].domain.tld in suspicious_tlds"
      or
        any(recipients.to)
          and
            or
              strings.icontains func_call "strings.icontains(sender.display_name)"
              strings.icontains func_call "strings.icontains(subject.subject)"
             macro "recipients.to[].email.domain.sld in org_slds"
        and
          headers.reply_to length_compare "0"
           macro "all(headers.reply_to)"
        any(ml.nlu_classifier(body.current_thread.text).entities)
          ml.nlu_classifier(body.current_thread.text).entities.name eq "request"
        any(ml.nlu_classifier(file.parse_eml(attachments).body.current_thread.text).entities)
          ml.nlu_classifier(file.parse_eml(attachments).body.current_thread.text).entities.name eq "request"
        any($suspicious_subjects)
          strings.icontains func_call "strings.icontains(subject.subject)"
        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"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
  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"

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:)"

Indicators

These rows show field, operator, and value matches.

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) is 1
  3. recipients.to[0].email.domain.valid
  4. any of attachments where:
    • any of file.parse_eml(.).attachments where any holds:
      • all of:
        • .file_extension in $file_extensions_macros
        • any of file.explode(.) where all hold:
          • .scan.qr.type is 'url'
          • ml.link_analysis(.scan.qr.url).final_dom.raw matches 'challenges\\.cloudflare\\.com'
      • any of beta.scan_qr(.).items where all hold:
        • .type is set
        • ml.link_analysis(.url).final_dom.raw matches '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)
    any(file.parse_eml(attachments).attachments)
      or
        and
          any(file.explode(file.parse_eml(attachments).attachments))
            and
              file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.type eq "url"
              ml.link_analysis(file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url).final_dom.raw regex_match "challenges\\.cloudflare\\.com"
           macro "file.parse_eml(attachments[]).attachments[].file_extension in file_extensions_macros"
        any(beta.scan_qr(file.parse_eml(attachments).attachments).items)
          and
            beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].type is_not_null
            ml.link_analysis(beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url).final_dom.raw regex_match "challenges\\.cloudflare\\.com"
  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.

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) is 1
    • all of:
      • length(filter(attachments, .file_extension == 'eml' or .content_type == 'message/rfc822')) is 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))) is length(attachments) - 1
  3. any of:
    • length(body.current_thread.text) < 300
    • body.current_thread.text is missing
    • any of ml.nlu_classifier(body.current_thread.text).intents where:
      • .name in ('cred_theft', 'steal_pii')
  4. not:
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'benign'
      • .confidence is '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 is ''
      • 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) is 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) is 1
    • not:
      • all of:
        • all of file.parse_eml(.).body.links where any holds:
          • .href_url.domain.root_domain in ('aka.ms', 'office365.com')
          • .href_url.url is '#additionalatt'
        • file.parse_eml(.).body.current_thread.text contains '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
      not
        and
          file.parse_eml(attachments[]).body.current_thread.text contains "We’re making sure your attachments are safe"
           macro "all(file.parse_eml(attachments[]).body.links)"
      or
        and
          file.parse_eml(attachments[]).recipients.to length_compare "1"
          recipients.to length_compare "1"
           macro "sender.email.email == file.parse_eml(attachments[]).sender.email.email"
           macro "sender.email.email in map(file.parse_eml(attachments[]).recipients.to, attachments[].email.email)"
           macro "sender.email.email in map(recipients.to, attachments[].email.email)"
        file.parse_eml func_call "file.parse_eml(attachments[]).sender.email.email == "
        file.parse_eml(attachments[]).body.html.raw length_compare "10"
        file.parse_eml(attachments[]).headers.hops length_compare "2"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
      file.parse_eml func_call "file.parse_eml(attachments[]).sender.email.domain.root_domain not in org_domains"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    any(ml.nlu_classifier(body.current_thread.text).intents)
      and
        ml.nlu_classifier(body.current_thread.text).intents.confidence eq "high"
        ml.nlu_classifier(body.current_thread.text).intents.name eq "benign"
  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
      filter(attachments, .file_extension == 'eml' or .content_type == 'message/rfc822') length_compare "1"
       macro "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)"
    attachments length_compare "1"
  or
    any(ml.nlu_classifier(body.current_thread.text).intents)
      ml.nlu_classifier(body.current_thread.text).intents.name in ["cred_theft", "steal_pii"]
    body.current_thread.text is_null
    body.current_thread.text length_compare "300"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
ml.nlu_classifier(body.current_thread.text).intentsarray_any(no value, null check)excludes:ml.nlu_classifier(body.current_thread.text).intents

Indicators

These rows show field, operator, and value matches.

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 of file.explode(.) where all hold:
      • .depth is 0
      • .size < 1000000
      • not:
        • .depth > 0
      • .scan.exiftool.zip_file_name ends with '.doc'
      • .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
  any(attachments)
    and
      any(file.explode(attachments))
        and
          not
            file.explode(attachments[])[].depth gt "0"
          file.explode(attachments[])[].depth eq "0"
          file.explode(attachments[])[].scan.exiftool.zip_file_name ends_with ".doc"
          file.explode(attachments[])[].scan.exiftool.zip_uncompressed_size gt "500000000"
          file.explode(attachments[])[].size lt "1000000"
      attachments.file_extension eq "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"
    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
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) is 2
  3. length(filter(attachments, strings.contains(.file_name, 'Empl0yment'))) is 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"
  filter(attachments, strings.contains(.file_name, 'Empl0yment')) length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

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"
         macro "attachments[].file_extension in file_extensions_macros"
      file.oletools func_call "file.oletools(attachments[]).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
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_encrypted_cred_phish_001"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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*:',
                     '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+)',
                     '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*:',
                            '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+)',
                            '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 of filter(attachments) where all hold:
    • any of file.explode(.) where any holds:
      • any of .scan.exiftool.fields where:
        • .key is 'Encryption'
      • all of:
        • .scan.entropy.entropy > 7
        • any of .scan.strings.strings where:
          • . contains '/Encrypt'
    • all of filter(...) where:
      • .size is 0
  3. any of:
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'cred_theft'
      • .confidence in ('medium', 'high')
    • any of ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents where all hold:
      • .name is 'cred_theft'
      • .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*:
      • 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+)
      • 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*:
          • 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+)
          • 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) is 0
      • all of recipients.to where:
        • .display_name matches 'undisclosed?recipients'
    • all of:
      • length(recipients.to) is 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.icontainsregexThis\s+(?:file|document|pdf)\s+is\s+(?:password[-\s]?)\s+protected\.\s*The\s+password\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
  any(filter(attachments))
    and
      any(file.explode(filter(attachments)))
        or
          and
            any(file.explode(filter(attachments)).scan.strings.strings)
              file.explode(filter(attachments)).scan.strings.strings contains "/Encrypt"
            file.explode(filter(attachments)[])[].scan.entropy.entropy gt "7"
          any(file.explode(filter(attachments)).scan.exiftool.fields)
            file.explode(filter(attachments)).scan.exiftool.fields.key eq "Encryption"
       macro "all(filter(...))"
  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 "The\\s+(?:file|document|pdf|attachment)\\s+(?:pass(?:code|word)|access\\s*code)\\s+is\\s*"
          body.previous_threads.text regex_match "This\\s+(?:file|document|pdf)\\s+is\\s+(?:password[-\\s]?)\\s+protected\\.\\s*The\\s+password\\s+is\\s*:?"
      or
        body.current_thread.text is_null
        body.current_thread.text length_compare "10"
    any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents)
      and
        ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents.confidence in ["high", "medium"]
        ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents.name eq "cred_theft"
    any(ml.nlu_classifier(body.current_thread.text).intents)
      and
        ml.nlu_classifier(body.current_thread.text).intents.confidence in ["high", "medium"]
        ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
    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 "The\\s+(?:file|document|pdf|attachment)\\s+(?:pass(?:code|word)|access\\s*code)\\s+is\\s*"
    body.current_thread.text regex_match "This\\s+(?:file|document|pdf)\\s+is\\s+(?:password[-\\s]?)\\s+protected\\.\\s*The\\s+password\\s+is\\s*:?"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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)"
  type.inbound eq "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"

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))
  • The\s+(?:file|document|pdf|attachment)\s+(?:pass(?:code|word)|access\s*code)\s+is\s*
  • This\s+(?:file|document|pdf)\s+is\s+(?:password[-\s]?)\s+protected.\s*The\s+password\s+is\s*:?
field:"body.current_thread.text" kind:regex_match
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(...) where all hold:
      • any of file.explode(.) where any holds:
        • any of .scan.exiftool.fields where:
          • .key is 'Encryption'
        • all of:
          • .scan.entropy.entropy > 7
          • any of .scan.strings.strings where:
            • . contains '/Encrypt'
      • all of filter(...) where:
        • .size is 0
    • any of:
      • any of ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents where all hold:
        • .name is 'cred_theft'
        • .confidence in ('medium', 'high')
      • any of ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(.).body.html)).text).intents where all hold:
        • .name is 'cred_theft'
        • .confidence in ('medium', 'high')
      • file.parse_eml(.).body.current_thread.text matches any of 4 patterns
        • 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 missing
        • any of file.parse_eml(.).body.previous_threads where:
          • .text matches any of 4 patterns
            • 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) is 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) is 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)

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
      any(filter(...))
        and
          any(file.explode(filter(...)))
            or
              and
                any(file.explode(filter(...)).scan.strings.strings)
                  file.explode(filter(...)).scan.strings.strings contains "/Encrypt"
                file.explode(filter(...)[])[].scan.entropy.entropy gt "7"
              any(file.explode(filter(...)).scan.exiftool.fields)
                file.explode(filter(...)).scan.exiftool.fields.key eq "Encryption"
           macro "all(filter(...))"
      or
        and
          any(file.parse_eml(attachments).body.previous_threads)
            or
              file.parse_eml(attachments[]).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+)"
              file.parse_eml(attachments[]).body.previous_threads[].text regex_match "(?:Access|Preview|Unlock|Decrypt|Pass)\\s*(?:word|code)\\s*(?:\\S+\\s+){0,3}PDF\\s*is?\\s*:"
              file.parse_eml(attachments[]).body.previous_threads[].text regex_match "PDF\\s*(?:Access|Preview|Unlock|Decrypt|passcode)"
              file.parse_eml(attachments[]).body.previous_threads[].text regex_match "This\\s+(?:file|document|pdf)\\s+is\\s+(?:password[-\\s]?)\\s+protected\\.\\s*The\\s+password\\s+is\\s*:?"
          or
            file.parse_eml(attachments[]).body.current_thread.text is_null
            file.parse_eml(attachments[]).body.current_thread.text length_compare "10"
        any(ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(attachments).body.html)).text).intents)
          and
            ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(attachments[]).body.html)).text).intents[].confidence in ["high", "medium"]
            ml.nlu_classifier(beta.ocr(file.html_screenshot(file.parse_eml(attachments[]).body.html)).text).intents[].name eq "cred_theft"
        any(ml.nlu_classifier(file.parse_eml(attachments).body.current_thread.text).intents)
          and
            ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].confidence in ["high", "medium"]
            ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].name eq "cred_theft"
        file.parse_eml(attachments[]).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+)"
        file.parse_eml(attachments[]).body.current_thread.text regex_match "(?:Access|Preview|Unlock|Decrypt|Pass)\\s*(?:word|code)\\s*(?:\\S+\\s+){0,3}PDF\\s*is?\\s*:"
        file.parse_eml(attachments[]).body.current_thread.text regex_match "PDF\\s*(?:Access|Preview|Unlock|Decrypt|passcode)"
        file.parse_eml(attachments[]).body.current_thread.text regex_match "This\\s+(?:file|document|pdf)\\s+is\\s+(?:password[-\\s]?)\\s+protected\\.\\s*The\\s+password\\s+is\\s*:?"
  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)"
       macro "all(recipients.to)"
    recipients.to length_compare "0"
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  type.inbound eq "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"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where:
    • any of file.explode(.) where all hold:
      • .scan.zip.encrypted is True
      • any of .scan.zip.all_paths where:
        • . 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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      and
        any(file.explode(filter(attachments)).scan.zip.all_paths)
          file.explode(filter(attachments)).scan.zip.all_paths ends_with "vhdx"
        file.explode(filter(attachments)[])[].scan.zip.encrypted eq "true"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where all hold:
    • any of file.explode(.) where any holds:
      • all of:
        • length(.scan.strings.raw) < 1000
        • .scan.strings.raw matches '(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)'
      • .scan.strings.raw contains 'Please download this spreadsheet or SVG and click'
      • all of:
        • length(.scan.strings.raw) < 500
        • .scan.strings.raw contains 'REVIEW DOCUMENT'
    • beta.parse_exif(.).creator is 'xuri'
    • any of beta.parse_exif(.).fields where all hold:
      • .key is 'Application'
      • .value is '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
  any(filter(attachments))
    and
      any(file.explode(filter(attachments)))
        or
          and
            file.explode(filter(attachments)[])[].scan.strings.raw contains "REVIEW DOCUMENT"
            file.explode(filter(attachments)[])[].scan.strings.raw length_compare "500"
          and
            file.explode(filter(attachments)[])[].scan.strings.raw length_compare "1000"
            file.explode(filter(attachments)[])[].scan.strings.raw regex_match "(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)"
          file.explode(filter(attachments)[])[].scan.strings.raw contains "Please download this spreadsheet or SVG and click"
      any(beta.parse_exif(filter(attachments)).fields)
        and
          beta.parse_exif(filter(attachments)[]).fields[].key eq "Application"
          beta.parse_exif(filter(attachments)[]).fields[].value eq "Go Excelize"
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).creator == xuri"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of beta.parse_exif(.).fields where all hold:
      • .key is 'Template'
      • .value is '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
      any(beta.parse_exif(attachments).fields)
        and
          beta.parse_exif(attachments[]).fields[].key eq "Template"
          beta.parse_exif(attachments[]).fields[].value eq "TM16390866"
      attachments.file_type eq "xlsx"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
        • .file_extension is '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
        any(file.explode(attachments))
          file.explode(attachments).file_extension eq "iqy"
         macro "attachments[].file_extension in file_extensions_common_archives"
    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
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 of ml.logo_detect(.).brands where all hold:
          • .name is 'FakeAttachment'
          • .confidence is 'high'
        • all of:
          • .size < 30000
          • any of file.explode(.) where all hold:
            • .scan.ocr.raw contains 'sent you'
            • .scan.ocr.raw matches '\\b\\d+.\\d{1,2}\\s?(k|m)b(\\s|$)'
    • any of ml.logo_detect(file.message_screenshot()).brands where all hold:
      • .name is 'FakeAttachment'
      • .confidence is '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 of file.parse_eml(.).attachments where all hold:
        • .file_type in $file_types_images
        • any of:
          • any of ml.logo_detect(.).brands where:
            • .name is 'FakeAttachment'
          • all of:
            • .size < 30000
            • any of file.explode(.) where all hold:
              • .scan.ocr.raw contains 'sent you'
              • .scan.ocr.raw matches '\\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
        any(file.parse_eml(attachments).attachments)
          and
            or
              and
                any(file.explode(file.parse_eml(attachments).attachments))
                  and
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.ocr.raw contains "sent you"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.ocr.raw regex_match "\\b\\d+.\\d{1,2}\\s?(k|m)b(\\s|$)"
                file.parse_eml(attachments[]).attachments[].size lt "30000"
              any(ml.logo_detect(file.parse_eml(attachments).attachments).brands)
                ml.logo_detect(file.parse_eml(attachments).attachments).brands.name eq "FakeAttachment"
             macro "file.parse_eml(attachments[]).attachments[].file_type in file_types_images"
        or
          attachments.content_type eq "message/rfc822"
          attachments.file_extension eq "eml"
    any(attachments)
      and
        or
          and
            any(file.explode(attachments))
              and
                file.explode(attachments[])[].scan.ocr.raw contains "sent you"
                file.explode(attachments[])[].scan.ocr.raw regex_match "\\b\\d+.\\d{1,2}\\s?(k|m)b(\\s|$)"
            attachments.size lt "30000"
          any(ml.logo_detect(attachments).brands)
            and
              ml.logo_detect(attachments[]).brands[].confidence eq "high"
              ml.logo_detect(attachments[]).brands[].name eq "FakeAttachment"
         macro "attachments[].file_type in file_types_images"
    any(ml.logo_detect(file.message_screenshot()).brands)
      and
        ml.logo_detect(file.message_screenshot()).brands.confidence eq "high"
        ml.logo_detect(file.message_screenshot()).brands.name eq "FakeAttachment"
    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]"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"

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:"答复:"

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
field:"type.inbound" kind:eq value:"true"

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) is 1
  3. beta.parse_exif(attachments[0]).creator is '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
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name in ["fake_invoice_pdf_images_01", "fake_invoice_pdf_structure_01"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of map(...) where:
      • 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 of file.explode(...) where:
        • at least 3 of:
          • body.current_thread.text matches '*scan date*'
          • body.current_thread.text matches '*was sent from*'
          • body.current_thread.text matches '*of pages*'
          • body.current_thread.text matches '*scanned file*'
          • body.current_thread.text contains 'Number of Images:'
          • body.current_thread.text contains 'Attachment File Type:'
          • body.current_thread.text contains 'Device Name:'
          • body.current_thread.text contains 'Device Location:'
          • body.current_thread.text contains 'Device Model:'
  4. any of:
    • all of:
      • length(filter(attachments, .file_type in ('pdf'))) is 1
      • any of attachments where all hold:
        • .file_type is 'pdf'
        • any of:
          • any of file.explode(.) where all hold:
            • any of:
              • .scan.ocr.raw matches any of 5 patterns
                • *scan date*
                • *was sent from*
                • *of pages*
                • *verif*document*
                • *scanned file*
              • any of ml.nlu_classifier(.scan.ocr.raw).intents where:
                • .name is 'cred_theft'
              • any of ml.logo_detect(.).brands where:
                • .name in ('DocuSign', 'Microsoft')
            • length(.scan.url.urls) is 1
          • any of file.explode(.) where any holds:
            • any of .scan.exiftool.fields where:
              • .key is 'Encryption'
            • all of:
              • .scan.entropy.entropy > 7
              • any of .scan.strings.strings where:
                • . contains '/Encrypt'
    • length(filter(attachments, .file_type in ('doc', 'docx'))) is 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
            any(file.explode(attachments))
              or
                and
                  any(file.explode(attachments).scan.strings.strings)
                    file.explode(attachments).scan.strings.strings contains "/Encrypt"
                  file.explode(attachments[])[].scan.entropy.entropy gt "7"
                any(file.explode(attachments).scan.exiftool.fields)
                  file.explode(attachments).scan.exiftool.fields.key eq "Encryption"
            any(file.explode(attachments))
              and
                or
                  any(ml.logo_detect(attachments).brands)
                    ml.logo_detect(attachments).brands.name in ["DocuSign", "Microsoft"]
                  any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
                    ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents.name eq "cred_theft"
                  file.explode(attachments[])[].scan.ocr.raw match "of pages"
                  file.explode(attachments[])[].scan.ocr.raw match "scan date"
                  file.explode(attachments[])[].scan.ocr.raw match "scanned file"
                  file.explode(attachments[])[].scan.ocr.raw match "was sent from"
                  file.explode(attachments[])[].scan.ocr.raw wildcard "*verif*document*"
                file.explode(attachments[])[].scan.url.urls length_compare "1"
          attachments.file_type eq "pdf"
      filter(attachments, .file_type in ('pdf')) length_compare "1"
    filter(attachments, .file_type in ('doc', 'docx')) length_compare "1"
  or
    any(file.explode(...))
      or
        body.current_thread.text contains "Attachment File Type:"
        body.current_thread.text contains "Device Location:"
        body.current_thread.text contains "Device Model:"
        body.current_thread.text contains "Device Name:"
        body.current_thread.text contains "Number of Images:"
        body.current_thread.text match "of pages"
        body.current_thread.text match "scan date"
        body.current_thread.text match "scanned file"
        body.current_thread.text match "was sent from"
    body.current_thread.text contains "Attachment File Type:"
    body.current_thread.text contains "Device Location:"
    body.current_thread.text contains "Device Model:"
    body.current_thread.text contains "Device Name:"
    body.current_thread.text contains "File Format:"
    body.current_thread.text contains "Number of Images:"
    body.current_thread.text contains "Resolution:"
    body.current_thread.text match "of pages"
    body.current_thread.text match "scan date"
    body.current_thread.text match "scanned file"
    body.current_thread.text match "was sent from"
  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
    any(map(...))
       macro "(length(body.current_thread.text) - length(map(...)[])) < 1500"
    body.current_thread.text length_compare "1500"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  type.inbound eq "true"
   macro "sender.email.domain.domain not in org_domains"

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*
  • *scanned file*
  • *was sent from*
field:"body.current_thread.text" kind:wildcard
type.inboundeq
  • true transforms: boolean
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 of ml.nlu_classifier(body.current_thread.text).intents where all hold:
    • .name is 'cred_theft'
    • .confidence is 'high'
  3. any of attachments where:
    • any of file.explode(.) where all hold:
      • any of .scan.strings.strings where:
        • . contains 'secure message'
      • any of:
        • any of .scan.url.urls where:
          • .domain.tld in $suspicious_tlds
        • any of .scan.url.urls where:
          • any of .rewrite.encoders where:
            • . contains 'open_redirect'
      • any of:
        • any of .scan.url.urls where:
          • .domain.root_domain is not sender.email.domain.root_domain
        • 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
  any(attachments)
    any(file.explode(attachments))
      and
        or
          any(file.explode(attachments).scan.url.urls)
            any(file.explode(attachments).scan.url.urls.rewrite.encoders)
              file.explode(attachments).scan.url.urls.rewrite.encoders contains "open_redirect"
          any(file.explode(attachments).scan.url.urls)
             macro "file.explode(attachments[])[].scan.url.urls[].domain.tld in suspicious_tlds"
        or
          any(file.explode(attachments).scan.url.urls)
            file.explode(attachments).scan.url.urls.domain.root_domain cross_field_compare "sender.email.domain.root_domain"
          not
            sender.email.domain.valid eq "true"
        any(file.explode(attachments).scan.strings.strings)
          file.explode(attachments).scan.strings.strings contains "secure message"
  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"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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)"
  any(ml.nlu_classifier(body.current_thread.text).intents)
    and
      ml.nlu_classifier(body.current_thread.text).intents.confidence eq "high"
      ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
  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)"
  type.inbound eq "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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of ml.logo_detect(file.html_screenshot(.)).brands where all hold:
      • .name is 'Slack'
      • .confidence in ('medium', 'high')
    • any of ml.nlu_classifier(file.parse_html(.).display_text).entities where all hold:
      • .name is 'request'
      • .text is 'download'
    • any of file.explode(.) where:
      • any of .scan.url.urls where all hold:
        • .path ends with '.exe'
        • .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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          and
            file.explode(attachments[])[].scan.url.urls[].path ends_with ".exe"
             macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain not in org_domains"
      any(ml.logo_detect(file.html_screenshot(attachments)).brands)
        and
          ml.logo_detect(file.html_screenshot(attachments[])).brands[].confidence in ["high", "medium"]
          ml.logo_detect(file.html_screenshot(attachments[])).brands[].name eq "Slack"
      any(ml.nlu_classifier(file.parse_html(attachments).display_text).entities)
        and
          ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].name eq "request"
          ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].text eq "download"
      or
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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) is 1
  3. not:
    • subject.base contains 'fax'
  4. any of:
    • length(body.current_thread.text) is 0
    • all of:
      • ml.nlu_classifier(body.current_thread.text).language is 'english'
      • any of:
        • any of ml.nlu_classifier(body.current_thread.text).topics where all hold:
          • .confidence is 'high'
          • .name is 'Voicemail Call and Missed Call Notifications'
        • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
          • .confidence is 'high'
          • .name is 'bec'
  5. any of attachments where all hold:
    • .file_extension is 'pdf'
    • ml.nlu_classifier(beta.ocr(.).text).language is 'english'
    • length(beta.ocr(.).text) > 95
    • any of ml.nlu_classifier(beta.ocr(.).text).topics where all hold:
      • .confidence is 'high'
      • .name is 'Voicemail Call and Missed Call Notifications'
    • beta.ocr(.).success
    • any of file.explode(.) where any holds:
      • all of:
        • length(.scan.pdf.urls) > 0
        • length(.scan.pdf.urls) ≤ 2
      • .scan.qr.url.url is set
    • any of file.explode(.) where all hold:
      • .depth is 0
      • .scan.exiftool.page_count is 1
  6. not:
    • all of:
      • sender.email.domain.root_domain is 'zendesk.com'
      • coalesce(headers.auth_summary.dmarc.pass)

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

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of ml.logo_detect(file.html_screenshot(.)).brands where all hold:
      • .name is 'Zoom'
      • .confidence in ('medium', 'high')
    • any of ml.nlu_classifier(file.parse_html(.).display_text).entities where all hold:
      • .name is 'request'
      • .text is 'download'
    • any of file.explode(.) where:
      • any of .scan.url.urls where all hold:
        • .path ends with '.exe'
        • .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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          and
            file.explode(attachments[])[].scan.url.urls[].path ends_with ".exe"
             macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain not in org_domains"
      any(ml.logo_detect(file.html_screenshot(attachments)).brands)
        and
          ml.logo_detect(file.html_screenshot(attachments[])).brands[].confidence in ["high", "medium"]
          ml.logo_detect(file.html_screenshot(attachments[])).brands[].name eq "Zoom"
      any(ml.nlu_classifier(file.parse_html(attachments).display_text).entities)
        and
          ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].name eq "request"
          ml.nlu_classifier(file.parse_html(attachments[]).display_text).entities[].text eq "download"
      or
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where any holds:
      • any of .scan.javascript.identifiers where:
        • . matches any of 2 patterns
          • ActiveXObject
          • ShellExecute
      • all of:
        • length(.scan.javascript.strings) > 0
        • all of .scan.javascript.strings where:
          • . matches any of 2 patterns
            • 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
      any(file.explode(attachments))
        or
          any(file.explode(attachments).scan.javascript.identifiers)
            or
              file.explode(attachments[])[].scan.javascript.identifiers[] eq "ActiveXObject"
              file.explode(attachments[])[].scan.javascript.identifiers[] eq "ShellExecute"
          and
            file.explode(attachments[])[].scan.javascript.strings length_compare "0"
             macro "all(file.explode(attachments[])[].scan.javascript.strings)"
       macro "attachments[].file_type in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
        • .file_name matches '\\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
        any(file.explode(attachments))
          file.explode(attachments).file_name regex_match "\\x{2800}"
         macro "attachments[].file_extension in file_extensions_common_archives"
      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
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 of file.explode(.) where:
        • .file_name matches any of 2 patterns
          • \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
        any(file.explode(attachments))
          or
            file.explode(attachments[])[].file_name regex_match "\\x{202D}"
            file.explode(attachments[])[].file_name regex_match "\\x{202E}"
         macro "attachments[].file_extension in file_extensions_common_archives"
      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
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . 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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.strings.strings)
        file.explode(filter(attachments)).scan.strings.strings contains "/Rect [ 249.75 560 407.25 599.75 ]"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of .scan.javascript.identifiers where:
        • . is 'location'
      • 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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.javascript.identifiers)
            file.explode(attachments).scan.javascript.identifiers eq "location"
          file.explode(attachments[])[].scan.javascript.identifiers length_compare "100"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
      attachments.size le "5000"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where any holds:
      • all of:
        • length(filter(.scan.javascript.strings, strings.ilike(., '*password*'))) ≥ 2
        • at least 2 of:
          • any of .scan.javascript.strings where:
            • . matches '*incorrect*'
          • any of .scan.javascript.strings where:
            • . matches '*invalid*'
          • any of .scan.javascript.strings where:
            • . matches '*login*'
          • any of .scan.javascript.strings where:
            • . matches 'sign.in'
      • all of:
        • length(filter(.scan.strings.strings, strings.ilike(., '*password*'))) ≥ 2
        • at least 2 of:
          • any of .scan.strings.strings where:
            • . matches '*incorrect*'
          • any of .scan.strings.strings where:
            • . matches '*invalid*'
          • any of .scan.strings.strings where:
            • . matches '*login*'
          • any of .scan.strings.strings where:
            • . matches '*<script>*'
          • any of .scan.strings.strings where:
            • . matches 'sign.in'
          • any of .scan.strings.strings where:
            • . matches '<title>.[^<]+(Payment|Invoice|Statement|Login|Microsoft|Email|Excel)'
      • at least 2 of:
        • any of .scan.strings.strings where:
          • . matches '*&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*'
        • any of .scan.strings.strings where:
          • . matches '*&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100*'
        • any of .scan.strings.strings where:
          • . matches '*&#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
      any(file.explode(attachments))
        or
          and
            or
              any(file.explode(attachments).scan.javascript.strings)
                file.explode(attachments).scan.javascript.strings match "incorrect"
              any(file.explode(attachments).scan.javascript.strings)
                file.explode(attachments).scan.javascript.strings match "invalid"
              any(file.explode(attachments).scan.javascript.strings)
                file.explode(attachments).scan.javascript.strings match "login"
              any(file.explode(attachments).scan.javascript.strings)
                file.explode(attachments).scan.javascript.strings regex_match "sign.in"
            filter(file.explode(attachments[])[].scan.javascript.strings, strings.ilike(file.explode(attachments[])[], '*password*')) length_compare "2"
          and
            or
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "<script>"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "incorrect"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "invalid"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings match "login"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings regex_match "<title>.[^<]+(Payment|Invoice|Statement|Login|Microsoft|Email|Excel)"
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings regex_match "sign.in"
            filter(file.explode(attachments[])[].scan.strings.strings, strings.ilike(file.explode(attachments[])[], '*password*')) length_compare "2"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "&#69;&#110;&#116;&#101;&#114;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "&#70;&#111;&#114;&#103;&#111;&#116;&#116;&#101;&#110;&#32;&#109;&#121;&#32;&#112;&#97;&#115;&#115;&#119;&#111;&#114;&#100"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "&#83;&#105;&#103;&#110;&#32;&#105;&#110"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"
       macro "sender.email.domain.root_domain in org_domains"
     macro "sender.email.domain.root_domain not in org_domains"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

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 of file.explode(.) where all hold:
      • length(.scan.strings.strings) is 1
      • any of .scan.strings.strings where:
        • . matches '\\s{0,}<script.*'
      • any of .scan.strings.strings where:
        • . 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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings ends_with "</script>"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "\\s{0,}<script.*"
          file.explode(attachments[])[].scan.strings.strings length_compare "1"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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:
      • file.parse_html(.).raw matches '<!-- saved from url=.{0,7}https://mail.google.com/mail/u/0/#inbox/'
    • length(file.parse_html(.).raw) < 50000
    • file.parse_html(.).raw matches any of 2 patterns
      • setTimeout\(\s*(?:function\s*)?\(.*?\)\s*(?:=>\s*)?\{[\s\S]*?\},\s*\d+\);
      • 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)

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
        file.parse_html(attachments[]).raw regex_match "<!-- saved from url=.{0,7}https://mail.google.com/mail/u/0/#inbox/"
      or
        file.parse_html(attachments[]).raw regex_match "setTimeout\\(\\s*(?:function\\s*)?\\(.*?\\)\\s*(?:=>\\s*)?\\{[\\s\\S]*?\\},\\s*\\d+\\);"
        file.parse_html(attachments[]).raw regex_match "setTimeout\\(\\s*\\w+\\,\\s*\\d{3,}\\)+;"
      file.parse_html(attachments[]).raw length_compare "50000"
      strings.count func_call "strings.count(file.parse_html(attachments[]).raw, \"const\") >= 7"
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is '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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.yara.matches)
          file.explode(attachments).scan.yara.matches.name eq "HTML_EXCESSIVE_PADDING"
      or
        attachments.content_type eq "text/html"
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .flavors.mime in ('text/html', 'text/plain')
      • any of recipients.to where all hold:
        • any of .scan.strings.strings where:
          • strings.icontains(.)
        • any of:
          • .email.domain.valid
          • .display_name contains 'undisclosed'
    • any of file.explode(.) where any holds:
      • all of:
        • any of .flavors.yara where:
          • . is 'javascript_file'
        • length(filter(.scan.javascript.identifiers, strings.ilike(., '_0x*'))) > 50
      • all of:
        • .flavors.mime is 'text/plain'
        • .file_name matches 'script*'
        • 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
      any(file.explode(attachments))
        and
          any(recipients.to)
            and
              or
                recipients.to.display_name contains "undisclosed"
                recipients.to.email.domain.valid eq "true"
              any(file.explode(attachments).scan.strings.strings)
                strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.strings.strings[])"
          file.explode(attachments[])[].flavors.mime in ["text/html", "text/plain"]
      any(file.explode(attachments))
        or
          and
            any(file.explode(attachments).flavors.yara)
              file.explode(attachments).flavors.yara eq "javascript_file"
            filter(file.explode(attachments[])[].scan.javascript.identifiers, strings.ilike(file.explode(attachments[])[], '_0x*')) length_compare "50"
          and
            file.explode(attachments[])[].file_name starts_with "script"
            file.explode(attachments[])[].flavors.mime eq "text/plain"
            filter(file.explode(attachments[])[].scan.strings.strings, regex.imatch(file.explode(attachments[])[], '.*_0x.*')) length_compare "50"
      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"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • not:
        • length(.scan.url.invalid_urls) > 0
      • length(.scan.url.urls) is 1
      • any of .scan.strings.strings where:
        • . matches '*body onload*'
      • any of .scan.url.urls where any holds:
        • .domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters
        • .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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.url.urls)
            or
               macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in abuse_ch_urlhaus_domains_trusted_reporters"
               macro "file.explode(attachments[])[].scan.url.urls[].domain.tld in suspicious_tlds"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "body onload"
          not
            file.explode(attachments[])[].scan.url.invalid_urls length_compare "0"
          file.explode(attachments[])[].scan.url.urls length_compare "1"
      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_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .scan.entropy.entropy ≥ 5
      • any of .scan.strings.strings where:
        • . matches '*body onload*'
      • any of .scan.strings.strings where:
        • . matches 'data:image/.*;base64'
      • any of .scan.strings.strings where:
        • . matches '*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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "body onload"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "document pass"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "data:image/.*;base64"
          file.explode(attachments[])[].scan.entropy.entropy ge "5"
      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_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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:
    • length(attachments) ≥ 1
    • 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 of file.explode(...) where any holds:
      • ml.link_analysis(.scan.qr.url).submitted
      • .scan.qr.data matches '\\.'
  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_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
      any(file.explode(...))
        or
          file.explode(...).scan.qr.data regex_match "\\."
          ml.link_analysis func_call "ml.link_analysis(file.explode(...)[].scan.qr.url).submitted"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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 of file.explode(.) where all hold:
      • .scan.entropy.entropy ≥ 5.7
      • .flavors.mime is 'text/html'
      • length(.scan.javascript.identifiers) is 0
      • any of .scan.url.urls where any holds:
        • .domain.domain not in $tranco_1m
        • .domain.root_domain in $free_subdomain_hosts
      • .scan.html.title matches any of 2 patterns
        • *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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.url.urls)
            or
               macro "file.explode(attachments[])[].scan.url.urls[].domain.domain not in tranco_1m"
               macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in free_subdomain_hosts"
          or
            file.explode(attachments[])[].scan.html.title match "microsoft"
            file.explode(attachments[])[].scan.html.title match "sign in"
          file.explode(attachments[])[].flavors.mime eq "text/html"
          file.explode(attachments[])[].scan.entropy.entropy ge "5.7"
          file.explode(attachments[])[].scan.javascript.identifiers length_compare "0"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  not
    sender.email.domain.root_domain in ["microsoft.com", "microsoftsupport.com", "office.com"]
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
      • .scan.entropy.entropy ≥ 5
      • any of:
        • length(filter(.scan.javascript.identifiers, strings.like(., 'document', 'write', 'atob'))) is 3
        • any of .scan.strings.strings where:
          • . matches 'document.{0,10}write.{0,10}atob'
        • any of .scan.strings.strings where:
          • . matches '=.?atob.*;'
        • any of .scan.strings.strings where:
          • . matches '*atob?atob*'
        • any of .scan.strings.strings where:
          • . matches '*{src: atob*'
        • any of .scan.strings.strings where:
          • . matches '*eval?atob*'
        • any of .scan.strings.strings where:
          • . matches '*atob(?0x*'
        • any of .scan.strings.strings where:
          • . matches "*'at'+'ob'*"
        • any of .scan.javascript.identifiers where:
          • . matches '*ato\\u0062*'
        • any of .scan.strings.strings where:
          • . matches '*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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).scan.javascript.identifiers)
              file.explode(attachments).scan.javascript.identifiers match "ato\\u0062"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "'at'+'ob'"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "atob(?0x"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "atob?atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "eval?atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "{src: atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings regex_match "=.?atob.*;"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings regex_match "document.{0,10}write.{0,10}atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings wildcard "*document*insertAdjacentHTML*atob*"
            filter(file.explode(attachments[])[].scan.javascript.identifiers, strings.like(file.explode(attachments[])[], 'document', 'write', 'atob')) length_compare "3"
          file.explode(attachments[])[].scan.entropy.entropy ge "5"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
        attachments.file_extension in ["dhtml", "eml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"

Exclusions

The rule actively suppresses these predicates.

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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
      • .scan.entropy.entropy ≥ 5
      • any of:
        • length(filter(.scan.javascript.identifiers, strings.like(., 'document', 'write', 'atob'))) is 3
        • any of .scan.strings.strings where:
          • . matches 'document.{0,10}write.{0,10}atob'
        • any of .scan.strings.strings where:
          • . matches '=.?atob.*;'
        • any of .scan.strings.strings where:
          • . matches '*atob?atob*'
        • any of .scan.strings.strings where:
          • . matches '*{src: atob*'
        • any of .scan.strings.strings where:
          • . matches '*eval?atob*'
        • any of .scan.strings.strings where:
          • . matches '*atob(?0x*'
        • any of .scan.strings.strings where:
          • . matches "*'at'+'ob'*"
        • any of .scan.javascript.identifiers where:
          • . matches '*ato\\u0062*'
        • any of .scan.strings.strings where:
          • . matches '*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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).scan.javascript.identifiers)
              file.explode(attachments).scan.javascript.identifiers match "ato\\u0062"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "'at'+'ob'"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "atob(?0x"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "atob?atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "eval?atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "{src: atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings regex_match "=.?atob.*;"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings regex_match "document.{0,10}write.{0,10}atob"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings wildcard "*document*insertAdjacentHTML*atob*"
            filter(file.explode(attachments[])[].scan.javascript.identifiers, strings.like(file.explode(attachments[])[], 'document', 'write', 'atob')) length_compare "3"
          file.explode(attachments[])[].scan.entropy.entropy ge "5"
      or
        attachments.content_type eq "text/calendar"
        attachments.file_extension eq "ics"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"

Exclusions

The rule actively suppresses these predicates.

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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
      • any of .scan.javascript.identifiers where:
        • . matches 'click'
      • any of .scan.javascript.identifiers where:
        • . matches 'addEventListener'
      • any of:
        • length(filter(.scan.javascript.identifiers, strings.like(., 'document', 'write', 'atob'))) is 3
        • any of .scan.strings.strings where:
          • . matches '*document*write*atob*'
        • any of .scan.strings.strings where:
          • . matches '*=*atob*;'
        • any of .scan.javascript.identifiers where:
          • . matches '*ato\\u0062*'
        • any of .scan.strings.strings where:
          • . matches any of 2 patterns
            • *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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).scan.strings.strings)
              or
                file.explode(attachments[])[].scan.strings.strings[] wildcard "*document*insertAdjacentHTML*atob*"
                file.explode(attachments[])[].scan.strings.strings[] wildcard "*document*write*atob*"
            any(file.explode(attachments).scan.javascript.identifiers)
              file.explode(attachments).scan.javascript.identifiers match "ato\\u0062"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings wildcard "*=*atob*;"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings wildcard "*document*write*atob*"
            filter(file.explode(attachments[])[].scan.javascript.identifiers, strings.like(file.explode(attachments[])[], 'document', 'write', 'atob')) length_compare "3"
          any(file.explode(attachments).scan.javascript.identifiers)
            file.explode(attachments).scan.javascript.identifiers eq "addEventListener"
          any(file.explode(attachments).scan.javascript.identifiers)
            file.explode(attachments).scan.javascript.identifiers eq "click"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of .scan.strings.strings where:
        • . contains 'data:text/javascript;base64'
      • 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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings contains "data:text/javascript;base64"
          file.explode(attachments[])[].scan.strings.strings length_compare "10"
      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"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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:
      • file.parse_text(.).text contains 'atob'
      • file.parse_text(.).text contains 'fromCharCode'
      • file.parse_text(.).text contains 'base64'
    • file.parse_text(.).text matches '[\\x2C\\x3B\\x3A\\x22\\x27\\x28\\x7B\\x5B\\s]UEsDB'
    • not:
      • file.parse_text(.).text contains '<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
        file.parse_text(attachments[]).text contains "<input type=\\\"hidden\\\" name=\\\"ZFRdata\\\" value=\\\"\\n-----BEGIN VOLTAGE SECURE BLOCK V3-----\\nUEsDBBQAAAAAAAAAAA"
      or
        file.parse_text(attachments[]).text contains "atob"
        file.parse_text(attachments[]).text contains "base64"
        file.parse_text(attachments[]).text contains "fromCharCode"
      file.parse_text(attachments[]).text regex_match "[\\x2C\\x3B\\x3A\\x22\\x27\\x28\\x7B\\x5B\\s]UEsDB"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches any of 2 patterns
          • *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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          or
            file.explode(attachments[])[].scan.strings.strings[] match "CJzYyIuY29uY2F0KCJyaXB0Iik"
            file.explode(attachments[])[].scan.strings.strings[] match "\"sc\".concat(\"ript\")"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches '(\\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_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          file.explode(attachments).scan.strings.strings regex_match "(\\d{2,3},){60,}"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches '<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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          file.explode(attachments).scan.strings.strings regex_match "<a href=\"data:application/octet-stream;base64,[a-z0-9/+]+={0,2}\" download=\".+\\.[a-z]{2,3}"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of:
        • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
        • .flavors.mime is 'text/plain'
      • any of .flavors.yara where:
        • . is '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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).flavors.yara)
            file.explode(attachments).flavors.yara eq "base64_pe"
          or
            file.explode(attachments[])[].file_extension in ["dhtml", "htm", "html", "shtml"]
            file.explode(attachments[])[].flavors.mime eq "text/plain"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches any of 4 patterns
          • *SVNPIDk2NjAvSEZT*
          • *MTk5MyBFLllPVU5HREFMRQ*
          • *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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          or
            file.explode(attachments[])[].scan.strings.strings[] match "MTk5MyBFLllPVU5HREFMRQ"
            file.explode(attachments[])[].scan.strings.strings[] match "QRMFERH5UVPllLFByM5kTM"
            file.explode(attachments[])[].scan.strings.strings[] match "SVNPIDk2NjAvSEZT"
            file.explode(attachments[])[].scan.strings.strings[] match "TZESvAjN2kDIPNVS"
      or
        attachments.file_extension in ["htm", "html"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches '.*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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          file.explode(attachments).scan.strings.strings regex_match ".*eval.{1,4}atob.*"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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'
    • file.parse_text(.).text matches '.*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"
      file.parse_text(attachments[]).text regex_match ".*eval.{1,4}atob.*"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where all hold:
        • . matches '(\\\\r\\\\n\\S{2}){50,}'
        • . 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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          and
            file.explode(attachments[])[].scan.strings.strings[] contains "decodeURIComponent"
            file.explode(attachments[])[].scan.strings.strings[] regex_match "(\\\\r\\\\n\\S{2}){50,}"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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.domain.valid
    • at least 1 of:
      • file.parse_html(.).raw matches '*window.location.href*'
      • file.parse_html(.).raw matches '*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(attachments[]).raw)"
      or
        file.parse_html(attachments[]).raw match "createObjectURL"
        file.parse_html(attachments[]).raw match "window.location.href"
      attachments.size lt "5000"
      strings.count func_call "strings.count(file.parse_html(attachments[]).raw, \"+\") > 20"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • length(.scan.javascript.identifiers) < 100
      • .scan.javascript.identifiers contains 'location'
      • .scan.javascript.identifiers contains 'charCodeAt'
      • .scan.javascript.identifiers contains 'fromCharCode'
      • .scan.javascript.identifiers contains 'indexOf'
      • .scan.javascript.keywords contains 'try'
      • .scan.javascript.keywords contains 'catch'

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
      any(file.explode(attachments))
        and
          file.explode(attachments[])[].scan.javascript.identifiers contains "charCodeAt"
          file.explode(attachments[])[].scan.javascript.identifiers contains "fromCharCode"
          file.explode(attachments[])[].scan.javascript.identifiers contains "indexOf"
          file.explode(attachments[])[].scan.javascript.identifiers contains "location"
          file.explode(attachments[])[].scan.javascript.identifiers length_compare "100"
          file.explode(attachments[])[].scan.javascript.keywords contains "catch"
          file.explode(attachments[])[].scan.javascript.keywords contains "try"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches '(\\\\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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          file.explode(attachments).scan.strings.strings regex_match "(\\\\x([a-zA-Z0-9]{2})){100}"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .scan.entropy.entropy ≥ 5
      • any of .scan.strings.strings where all hold:
        • . matches 'fromCharCode'
        • . matches 'parseInt'
        • . matches 'charCodeAt'
        • . matches '(\\\\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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            and
              file.explode(attachments[])[].scan.strings.strings[] regex_match "(\\\\x0.*?){50}"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "charCodeAt"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "fromCharCode"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "parseInt"
          file.explode(attachments[])[].scan.entropy.entropy ge "5"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of .scan.strings.strings where:
        • . matches '(\\W?0x[a-zA-Z0-9]{2}\\W?,\\s*){100}'
      • any of .scan.strings.strings where:
        • . 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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings contains ".map"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "(\\W?0x[a-zA-Z0-9]{2}\\W?,\\s*){100}"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches '*?[(?[?]+?[?])%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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          file.explode(attachments).scan.strings.strings match "?[(?[?]+?[?])%256]"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • at least 1 of:
        • any of .scan.javascript.identifiers where:
          • . in ('rot13', 'decodeROT13')
        • any of .scan.strings.strings where any holds:
          • . contains '\\"uggcf://'
          • . contains '\\"uggc://'
      • 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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).scan.strings.strings)
              or
                file.explode(attachments[])[].scan.strings.strings[] contains "\\\"uggc://"
                file.explode(attachments[])[].scan.strings.strings[] contains "\\\"uggcf://"
            any(file.explode(attachments).scan.javascript.identifiers)
              file.explode(attachments).scan.javascript.identifiers in ["decodeROT13", "rot13"]
          file.explode(attachments[])[].scan.javascript.identifiers length_compare "100"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type in ["html", "svg"]
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .scan.javascript.identifiers contains 'setTimeout'
      • any of .scan.strings.strings where:
        • . matches '*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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "location.href"
          file.explode(attachments[])[].scan.javascript.identifiers contains "setTimeout"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
      attachments.size le "400"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where any holds:
      • any of .scan.javascript.identifiers where:
        • . is 'unescape'
      • any of .scan.strings.strings where:
        • . matches '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
      any(file.explode(attachments))
        or
          any(file.explode(attachments).scan.javascript.identifiers)
            file.explode(attachments).scan.javascript.identifiers eq "unescape"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "document.write.{0,10}unescape"
      or
        attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
        attachments.file_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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(attachments[]).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"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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'
    • file.parse_html(.).raw matches '^<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"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  any(attachments)
    and
      attachments.file_extension eq "html"
      file.parse_html(attachments[]).raw regex_match "^<body style\\s*=\\s*\"\\s*display\\s*:\\s*none\\s*;\\s*\">"
  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
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 6: file.parse_html(.).raw contains any of 6 patterns
      • .replace
      • XMLHttpRequest
      • onreadystate
      • GET
      • send()
      • 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
        file.parse_html(attachments[]).raw contains ".replace"
        file.parse_html(attachments[]).raw contains "GET"
        file.parse_html(attachments[]).raw contains "XMLHttpRequest"
        file.parse_html(attachments[]).raw contains "onreadystate"
        file.parse_html(attachments[]).raw contains "responseText"
        file.parse_html(attachments[]).raw contains "send()"
      attachments.file_extension in ["dhtml", "htm", "html", "shtml"]
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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 of file.explode(.) where:
      • any of [.scan.strings.strings, .scan.javascript.identifiers] where:
        • any of . where:
          • . matches any of 2 patterns
            • *atob*
            • *decrypt*
    • any of file.explode(.) where:
      • any of recipients.to where all hold:
        • any of:
          • any of .scan.javascript.strings where:
            • strings.icontains(.)
          • any of .scan.strings.strings where:
            • strings.icontains(.)
        • any of:
          • .email.domain.valid
          • .display_name contains 'undisclosed'
    • not:
      • any of file.explode(.) where:
        • any of .scan.javascript.strings where any holds:
          • . contains 'Cisco Registered Envelope Service'
          • . contains 'https://res.cisco.com:443'
    • not:
      • any of file.explode(.) where all hold:
        • length(.scan.url.urls) > 0
        • all of .scan.url.urls where:
          • .domain.root_domain contains '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
      any(file.explode(attachments))
        any(recipients.to)
          and
            or
              any(file.explode(attachments).scan.javascript.strings)
                strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.javascript.strings[])"
              any(file.explode(attachments).scan.strings.strings)
                strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.strings.strings[])"
            or
              recipients.to.display_name contains "undisclosed"
              recipients.to.email.domain.valid eq "true"
      any(file.explode(attachments))
        any([file.explode(attachments).scan.strings.strings, file.explode(attachments).scan.javascript.identifiers])
          any([file.explode(attachments).scan.strings.strings, file.explode(attachments).scan.javascript.identifiers])
            or
              [file.explode(attachments[])[].scan.strings.strings, file.explode(attachments[])[].scan.javascript.identifiers][][] match "atob"
              [file.explode(attachments[])[].scan.strings.strings, file.explode(attachments[])[].scan.javascript.identifiers][][] match "decrypt"
      not
        any(file.explode(attachments))
          any(file.explode(attachments).scan.javascript.strings)
            or
              file.explode(attachments[])[].scan.javascript.strings[] contains "Cisco Registered Envelope Service"
              file.explode(attachments[])[].scan.javascript.strings[] contains "https://res.cisco.com:443"
      not
        any(file.explode(attachments))
          and
            file.explode(attachments[])[].scan.url.urls length_compare "0"
             macro "all(file.explode(attachments[])[].scan.url.urls)"
      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_type eq "html"
         macro "attachments[].file_extension in file_extensions_common_archives"
      attachments.size lt "1000000"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: ICS calendar file with base64 encoded recipient address in URL parameters

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

Detects inbound messages containing ICS calendar attachments where event links have multiple URL parameters, and the base64 decoded combination of those parameters matches the recipient's email address. This technique may be used to personalize malicious links or track specific targets.

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
  • 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(filter(.links, length(.href_url.query_params_decoded) > 1),
                    any(strings.scan_base64(strings.concat(coalesce(flatten(values(.display_url.query_params_decoded
                                                                            )
                                                                    )[0],
                                                                    ""
                                                           ),
                                                           coalesce(flatten(values(.display_url.query_params_decoded
                                                                            )
                                                                    )[1],
                                                                    ""
                                                           ),
                                                           coalesce(flatten(values(.display_url.query_params_decoded
                                                                            )
                                                                    )[2],
                                                                    ""
                                                           ),
                                                           coalesce(flatten(values(.display_url.query_params_decoded
                                                                            )
                                                                    )[3],
                                                                    ""
                                                           ),
                                                           coalesce(flatten(values(.display_url.query_params_decoded
                                                                            )
                                                                    )[4],
                                                                    ""
                                                           ),
                                                           coalesce(flatten(values(.display_url.query_params_decoded
                                                                            )
                                                                    )[5],
                                                                    ""
                                                           )
                                            )
                        ),
                        . == recipients.to[0].email.email
                    )
                )
        )
) 

Detection logic

Scope: inbound message.

Detects inbound messages containing ICS calendar attachments where event links have multiple URL parameters, and the base64 decoded combination of those parameters matches the recipient's email address. This technique may be used to personalize malicious links or track specific targets.

  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 beta.file.parse_ics(.).events where:
      • any of filter(.links) where:
        • any of strings.scan_base64(...) where:
          • . is 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, strings.concat, 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
      any(beta.file.parse_ics(attachments).events)
        any(filter(beta.file.parse_ics(attachments).events.links))
          any(strings.scan_base64(...))
            strings.scan_base64(...) cross_field_compare "recipients.to[0].email.email"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of beta.file.parse_ics(.).events where:
      • any of beta.scan_qr(file.html_screenshot(.description_html)).items where any holds:
        • strings.icontains(.url.url)
        • any of strings.scan_base64(.url.url) where:
          • strings.icontains(.)
        • any of strings.scan_base64(.url.fragment) where:
          • strings.icontains(.)

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
      any(beta.file.parse_ics(attachments).events)
        any(beta.scan_qr(file.html_screenshot(beta.file.parse_ics(attachments).events.description_html)).items)
          or
            any(strings.scan_base64(beta.scan_qr(file.html_screenshot(beta.file.parse_ics(attachments).events.description_html)).items.url.fragment))
              strings.icontains func_call "strings.icontains(strings.scan_base64(beta.scan_qr(file.html_screenshot(beta.file.parse_ics(attachments[]).events[].description_html)).items[].url.fragment)[])"
            any(strings.scan_base64(beta.scan_qr(file.html_screenshot(beta.file.parse_ics(attachments).events.description_html)).items.url.url))
              strings.icontains func_call "strings.icontains(strings.scan_base64(beta.scan_qr(file.html_screenshot(beta.file.parse_ics(attachments[]).events[].description_html)).items[].url.url)[])"
            strings.icontains func_call "strings.icontains(beta.scan_qr(file.html_screenshot(beta.file.parse_ics(attachments[]).events[].description_html)).items[].url.url)"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of beta.file.parse_ics(.).events where:
      • any of .raw_properties where all hold:
        • .key is 'UID'
        • .value is 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
      any(beta.file.parse_ics(attachments).events)
        any(beta.file.parse_ics(attachments).events.raw_properties)
          and
            beta.file.parse_ics(attachments[]).events[].raw_properties[].key eq "UID"
            beta.file.parse_ics(attachments[]).events[].raw_properties[].value cross_field_compare "recipients.to[0].email.email"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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:
      • beta.file.parse_ics(.).product_id matches '-//[a-z0-9]*[0-9][a-z0-9]*//EN'
      • beta.file.parse_ics(.).product_id contains any of 21 patterns
        • -//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
        beta.file.parse_ics(attachments[]).product_id contains "-//Calendar Auto//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//Calendar Event//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//CalendarInviteBuilder//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//CustomMailer//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//First Dips//Portal//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//HRNotify//CompChange 1.0//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//JANSANI//Email Engine v12.7//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//My App//NS9 Calendar//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//MyApp//example.com//"
        beta.file.parse_ics(attachments[]).product_id contains "-//Organization//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//Prof Morales Sender//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//SharePoint//NONSGML v1.0//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//X7fG3//Y2kL9//M9nP4 16.0 MIMEDIR//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//Your App//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//YourCassavaLtd//EateriesDept//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//caldav.icloud.com//CALDAVJ 2620B879//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-//dilmar//EN"
        beta.file.parse_ics(attachments[]).product_id contains "-Event Mandate"
        beta.file.parse_ics(attachments[]).product_id contains "-Meeting Schedule"
        beta.file.parse_ics(attachments[]).product_id contains "//NONSGML Event//EN"
        beta.file.parse_ics(attachments[]).product_id contains "Trafft"
        beta.file.parse_ics(attachments[]).product_id regex_match "-//[a-z0-9]*[0-9][a-z0-9]*//EN"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of beta.file.parse_ics(.).events where:
      • any of .raw_properties where all hold:
        • .key is 'UID'
        • .value ends with '@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
      any(beta.file.parse_ics(attachments).events)
        any(beta.file.parse_ics(attachments).events.raw_properties)
          and
            beta.file.parse_ics(attachments[]).events[].raw_properties[].key eq "UID"
            beta.file.parse_ics(attachments[]).events[].raw_properties[].value ends_with "@example.com"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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)
  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)))) is 1
  6. any of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.ics.calendars where:
        • any of .components where all hold:
          • .type is 'VEVENT'
          • length(.attendees) is 1
          • all of .attendees where:
            • .mailbox.email.domain.domain in $org_domains
          • any of .organizers where:
            • .mailbox.email.domain.domain in $org_domains
          • length(.attachments) > 0
          • all of .attachments where all hold:
            • .type is 'uri'
            • .uri starts with '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(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.ics.calendars)
        any(file.explode(filter(attachments)).scan.ics.calendars.components)
          and
            any(file.explode(filter(attachments)).scan.ics.calendars.components.organizers)
               macro "file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].organizers[].mailbox.email.domain.domain in org_domains"
            file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].attachments length_compare "0"
            file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].attendees length_compare "1"
            file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].type eq "VEVENT"
             macro "all(file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].attachments)"
             macro "all(file.explode(filter(attachments)[])[].scan.ics.calendars[].components[].attendees)"
  any(attachments)
    or
      attachments.content_type eq "text/calendar"
      attachments.file_extension eq "ics"
  not
    coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
  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))) length_compare "1"
  type.inbound eq "true"
   macro "sender.email.domain.domain in org_domains"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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:
      • file.parse_text(.).text matches 'lambda-url'
      • any of beta.file.parse_ics(.).events where:
        • any of .links where:
          • .href_url.domain.domain contains '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
        any(beta.file.parse_ics(attachments).events)
          any(beta.file.parse_ics(attachments).events.links)
            beta.file.parse_ics(attachments).events.links.href_url.domain.domain contains "lambda-url"
        file.parse_text(attachments[]).text regex_match "lambda-url"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where any holds:
    • regex.icount(file.parse_text(.).text, '[\\r\\n]X-[^\\r\\n]+\\x3b\\s?[^\\r\\n]+:\\s*[a-f0-9]{32,}') > 10
    • any of beta.file.parse_ics(.).events where:
      • 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
  any(filter(attachments))
    or
      any(beta.file.parse_ics(filter(attachments)).events)
        filter(beta.file.parse_ics(filter(attachments)[]).events[].raw_properties, strings.istarts_with(beta.file.parse_ics(filter(attachments)[]).events[].key, 'X-') and regex.icontains(beta.file.parse_ics(filter(attachments)[]).events[].value, '^[a-f0-9]{32,}$')) length_compare "10"
      regex.icount func_call "regex.icount(file.parse_text(filter(attachments)[]).text, \"[\\r\\n]X-[^\\r\\n]+\\x3b\\s?[^\\r\\n]+:\\s*[a-f0-9]{32,}\") > 10"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: ICS file with links to newly registered domains

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

Detects calendar invite attachments (ICS files) containing links to domains registered within the last 30 days, which may indicate malicious calendar invitations designed to redirect users to suspicious websites.

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
  • 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(.links, network.whois(.href_url.domain).days_old < 30)
        )
)

Detection logic

Scope: inbound message.

Detects calendar invite attachments (ICS files) containing links to domains registered within the last 30 days, which may indicate malicious calendar invitations designed to redirect users to suspicious websites.

  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 of beta.file.parse_ics(.).events where:
      • any of .links where:
        • network.whois(.href_url.domain).days_old < 30

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: beta.file.parse_ics, network.whois.

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
      any(beta.file.parse_ics(attachments).events)
        any(beta.file.parse_ics(attachments).events.links)
          network.whois func_call "network.whois(beta.file.parse_ics(attachments[]).events[].links[].href_url.domain).days_old < 30"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
        attachments.file_type eq "ics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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) is 1
  3. any of filter(attachments) where:
    • .file_name matches '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
  any(filter(attachments))
    filter(attachments).file_name regex_match "meeting_[a-zA-Z0-9]{5}\\."
  attachments length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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:
      • beta.file.parse_ics(.).scale contains '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
        beta.file.parse_ics(attachments[]).scale contains "GREGORIAN"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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'
    • file.parse_text(.).text matches '*ATTACH;ENCODING=*;VALUE=BINARY*'
    • file.parse_text(.).text matches any of 6 patterns
      • *FILENAME=*.doc*
      • *FILENAME=*.dot*
      • *FILENAME=*.pp*
      • *FILENAME=*.wbk*
      • *FILENAME=*.xl*
      • *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
        file.parse_text(attachments[]).text wildcard "*FILENAME=*.doc*"
        file.parse_text(attachments[]).text wildcard "*FILENAME=*.dot*"
        file.parse_text(attachments[]).text wildcard "*FILENAME=*.html*"
        file.parse_text(attachments[]).text wildcard "*FILENAME=*.pp*"
        file.parse_text(attachments[]).text wildcard "*FILENAME=*.wbk*"
        file.parse_text(attachments[]).text wildcard "*FILENAME=*.xl*"
      attachments.file_extension eq "ics"
      file.parse_text(attachments[]).text wildcard "*ATTACH;ENCODING=*;VALUE=BINARY*"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of:
        • .file_extension in ('svg', 'svgz')
        • .flavors.mime is 'image/svg+xml'
      • any of .scan.strings.strings where:
        • . matches any of 9 patterns
          • *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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            or
              file.explode(attachments[])[].scan.strings.strings[] match "</script"
              file.explode(attachments[])[].scan.strings.strings[] match "<script"
              file.explode(attachments[])[].scan.strings.strings[] match "CDATA"
              file.explode(attachments[])[].scan.strings.strings[] match "atob"
              file.explode(attachments[])[].scan.strings.strings[] match "decodeURIComponent"
              file.explode(attachments[])[].scan.strings.strings[] match "location.assign"
              file.explode(attachments[])[].scan.strings.strings[] match "onerror"
              file.explode(attachments[])[].scan.strings.strings[] match "onload"
              file.explode(attachments[])[].scan.strings.strings[] match "window.location.href"
          or
            file.explode(attachments[])[].file_extension in ["svg", "svgz"]
            file.explode(attachments[])[].flavors.mime eq "image/svg+xml"
      or
        attachments.content_type in ["application/ics", "text/calendar"]
        attachments.file_extension eq "ics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where all hold:
      • .depth is 0
      • any of .scan.strings.strings where:
        • . contains 'policy review'
      • any of .scan.strings.strings where:
        • . contains '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      and
        any(file.explode(filter(attachments)).scan.strings.strings)
          file.explode(filter(attachments)).scan.strings.strings contains "policy review"
        any(file.explode(filter(attachments)).scan.strings.strings)
          file.explode(filter(attachments)).scan.strings.strings contains "secure access"
        file.explode(filter(attachments)[])[].depth eq "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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
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
  • 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 regex.icontains(.file_name, '_inv_')
        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")
)
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)) is 2
  3. length(filter(attachments, .file_type == 'pdf')) is 2
  4. any of filter(attachments) where any holds:
    • beta.parse_exif(.).creator is 'Chromium'
    • beta.parse_exif(.).creator contains 'wkhtmltopdf'
    • beta.parse_exif(.).creator contains 'HeadlessChrome'
    • all of:
      • any of beta.parse_exif(.).fields where all hold:
        • .key is 'Creator'
        • .value is ''
      • any of beta.parse_exif(.).fields where all hold:
        • .key is 'Producer'
        • .value is ''
    • any of beta.parse_exif(.).fields where all hold:
      • .key in ('Producer', 'CreatorTool')
      • .value matches '(?: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}'
    • .file_name matches '_inv_'
    • beta.ocr(.).text contains 'Executive Business Coaching'
    • beta.ocr(.).text contains 'Executive Coaching'
    • beta.ocr(.).text contains 'Professional Services'
    • beta.ocr(.).text contains 'Business Systems Integration'
    • beta.ocr(.).text contains 'Consulting & Advisory'
    • beta.ocr(.).text contains 'Zoomlnfo'
  6. any of attachments where any holds:
    • .file_name is '.pdf'
    • beta.ocr(.).text matches '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)

Inspects: attachments[].file_name, attachments[].file_type, attachments[].sha1, headers.auth_summary.dmarc.pass, sender.email.domain.root_domain, type.inbound. Sensors: beta.ocr, beta.parse_exif, regex.contains, regex.icontains, strings.icontains, strings.istarts_with.

Indicators matched (25)

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_
13 more
regex.containsregex^Invoice\s\d{8,9}
regex.containsregex^INV[0-9]{7}
regex.containsregex^INV#[0-9]{12}
regex.icontainsregex_inv_
strings.icontainssubstringExecutive Business Coaching
strings.icontainssubstringExecutive Coaching
strings.icontainssubstringProfessional Services
strings.icontainssubstringBusiness Systems Integration
strings.icontainssubstringConsulting & Advisory
strings.icontainssubstringZoomlnfo
attachments[].file_nameequals.pdf
regex.containsregexW[=-]9
regex.icontainsregexw[-_]?9

Stages and Predicates

Stage 1: mql_rule

and
  any(filter(attachments))
    or
      and
        any(beta.parse_exif(filter(attachments)).fields)
          and
            beta.parse_exif(filter(attachments)[]).fields[].key eq "Creator"
            beta.parse_exif(filter(attachments)[]).fields[].value eq ""
        any(beta.parse_exif(filter(attachments)).fields)
          and
            beta.parse_exif(filter(attachments)[]).fields[].key eq "Producer"
            beta.parse_exif(filter(attachments)[]).fields[].value eq ""
      any(beta.parse_exif(filter(attachments)).fields)
        and
          beta.parse_exif(filter(attachments)[]).fields[].key in ["CreatorTool", "Producer"]
          beta.parse_exif(filter(attachments)[]).fields[].value regex_match "(?:pdfium|mpdf)"
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).creator == Chromium"
      beta.parse_exif(filter(attachments)[]).creator contains "HeadlessChrome"
      beta.parse_exif(filter(attachments)[]).creator contains "wkhtmltopdf"
  any(attachments)
    or
      attachments.file_name eq ".pdf"
      attachments.file_name regex_match "w[-_]?9"
      beta.ocr(attachments[]).text regex_match "W[=-]9"
  any(attachments)
    or
      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 regex_match "_inv_"
      attachments.file_name starts_with "inv-"
      attachments.file_name starts_with "invoice_"
      attachments.file_name starts_with "lnv"
      beta.ocr(attachments[]).text contains "Business Systems Integration"
      beta.ocr(attachments[]).text contains "Consulting & Advisory"
      beta.ocr(attachments[]).text contains "Executive Business Coaching"
      beta.ocr(attachments[]).text contains "Executive Coaching"
      beta.ocr(attachments[]).text contains "Professional Services"
      beta.ocr(attachments[]).text contains "Zoomlnfo"
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
      sender.email.domain.root_domain eq "intuit.com"
  distinct(attachments, .sha1) length_compare "2"
  filter(attachments, .file_type == 'pdf') length_compare "2"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
sender.email.domain.root_domaineqintuit.comexcludes:sender.email.domain.root_domain field:"sender.email.domain.root_domain" value:"intuit.com"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
      • any of:
        • .file_extension in ('js', 'jar')
        • any of .flavors.yara where:
          • . is 'javascript_file'
      • any of .flavors.yara where:
        • . is '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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).flavors.yara)
              file.explode(attachments).flavors.yara eq "javascript_file"
            file.explode(attachments[])[].file_extension in ["jar", "js"]
          any(file.explode(attachments).flavors.yara)
            file.explode(attachments).flavors.yara eq "base64_pe"
      or
        attachments.file_extension in ["jar", "js"]
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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')) is 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, '/') is 1
      • strings.count(.file_name, 'image') is 2
    • any of beta.parse_exif(.).fields where all hold:
      • .key is 'Comment'
      • .value starts with '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
      any(beta.parse_exif(attachments).fields)
        and
          beta.parse_exif(attachments[]).fields[].key eq "Comment"
          beta.parse_exif(attachments[]).fields[].value starts_with "CREATOR: gd-jpeg v1.0"
      or
        strings.count func_call "strings.count(attachments[].file_name, \"/\") == 1"
        strings.count func_call "strings.count(attachments[].file_name, \"image\") == 2"
      attachments.file_extension eq "jpeg"
      attachments.file_name contains "images"
      attachments.file_type eq "jpg"
  filter(attachments, .file_type == 'jpg') length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: Legal themed message or PDF with suspicious indicators

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

Detects messages with short body content or emoji containing PDF attachments from suspicious creators that include legal and compliance language with embedded malicious links, URL shorteners, or newly registered domains.

Threat classification

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

CategoryValues
Attack typesCredential Phishing, Extortion, BEC/Fraud
Tactics and techniquesEvasion, PDF, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • body
  • body.current_thread
  • body.plain
  • headers
  • subject
  • type

Rule body

type.inbound
// short body or contains emoji
and (
  length(body.current_thread.text) < 1500
  or regex.contains(body.plain.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}]'
  )
  or regex.contains(subject.base,
                    '[\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}]'
  )
)

// is not a reply
and length(headers.references) == 0
and headers.in_reply_to is null
and (
  ( // only one attachment
    length(attachments) == 1
    // or, any 2 attachments share the ~same file name
    or any(attachments,
           any(regex.extract(.file_name,
                             // the regex extracts the file name, discarding the file extention and any numbers in parens
                             // "test.txt" and "test (1).pdf" become "test"
                             '(?P<file_name>.*?)(?:\s*\([^)]+\))*\.[^.]+$'
               ),
               length(filter(attachments,
                             strings.istarts_with(.file_name,
                                                  ..named_groups["file_name"]
                             )
                      )
               ) > 1
           )
    )
  )
  // suspicious creator
  and any(attachments,
          (.file_extension == "pdf" or .file_type == "pdf")
          and any(file.explode(.),
                  strings.ilike(.scan.exiftool.producer,
                                "*Google Docs Renderer*",
                                "*Skia/PDF*",
                                "*Neevia Document Converter*"
                  )
                  or strings.istarts_with(.scan.exiftool.creator, "wkhtmltopdf")
          )
  )
)
and (
  // legal language in body with suspicious link in attachment
  (
    any(ml.nlu_classifier(body.current_thread.text).topics,
        .name == "Legal and Compliance" and .confidence in ("medium", "high")
    )
    and any(attachments,
            (.file_extension == "pdf" or .file_type == "pdf")
            and any(file.explode(.),
                    0 < length(.scan.pdf.urls) < 5
                    and (
                      any(.scan.pdf.urls,
                          // with links that are URL shortners
                          .domain.root_domain in $url_shorteners
                          or .domain.domain in $url_shorteners
                          or network.whois(.domain).days_old < 14
                          // when visiting those links, the link it is sus
                          or ml.link_analysis(.).effective_url.domain.tld in $suspicious_tlds
                          or ml.link_analysis(.).credphish.contains_captcha
                          or ml.link_analysis(.).credphish.disposition == "phishing"
                          or strings.icontains(ml.link_analysis(.).final_dom.display_text,
                                               "I'm Human"
                          )
                      )
                    )
            )
    )
  )
  // no body text, legal language in attachment
  or (
    length(body.current_thread.text) < 50
    and any(attachments,
            (.file_extension == "pdf" or .file_type == "pdf")
            and any(file.explode(.),
                    (
                      length(ml.nlu_classifier(.scan.ocr.raw).topics) == 1
                      and any(ml.nlu_classifier(.scan.ocr.raw).topics,
                              .name == "Legal and Compliance"
                              and .confidence in ("medium", "high")
                      )
                      and not any(ml.nlu_classifier(.scan.ocr.raw).entities,
                                  .name == "sender"
                                  and .text =~ sender.display_name
                      )
                    )
                    // foreign language indicators
                    or regex.icontains(.scan.ocr.raw,
                                       'pornograph(y|ie)',
                                       'interpol\b',
                                       'europol',
                                       'dissuade',
                                       // French indicators, seen in threatening language
                                       'ce jeu en ligne',
                                       'vraie vie'
                    )
            )
    )
  )
)

Detection logic

Scope: inbound message.

Detects messages with short body content or emoji containing PDF attachments from suspicious creators that include legal and compliance language with embedded malicious links, URL shorteners, or newly registered domains.

  1. inbound message
  2. any of:
    • length(body.current_thread.text) < 1500
    • body.plain.raw matches '[\\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}]'
    • subject.base matches '[\\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}]'
  3. length(headers.references) is 0
  4. headers.in_reply_to is missing
  5. all of:
    • any of:
      • length(attachments) is 1
      • any of attachments where:
        • any of regex.extract(.file_name) where:
          • length(filter(attachments, strings.istarts_with(.file_name, .named_groups['file_name']))) > 1
    • any of attachments where all hold:
      • any of:
        • .file_extension is 'pdf'
        • .file_type is 'pdf'
      • any of file.explode(.) where any holds:
        • .scan.exiftool.producer matches any of 3 patterns
          • *Google Docs Renderer*
          • *Skia/PDF*
          • *Neevia Document Converter*
        • .scan.exiftool.creator starts with 'wkhtmltopdf'
  6. any of:
    • all of:
      • any of ml.nlu_classifier(body.current_thread.text).topics where all hold:
        • .name is 'Legal and Compliance'
        • .confidence in ('medium', 'high')
      • any of attachments where all hold:
        • any of:
          • .file_extension is 'pdf'
          • .file_type is 'pdf'
        • any of file.explode(.) where all hold:
          • all of:
            • length(.scan.pdf.urls) > 0
            • length(.scan.pdf.urls) < 5
          • any of .scan.pdf.urls where any holds:
            • .domain.root_domain in $url_shorteners
            • .domain.domain in $url_shorteners
            • network.whois(.domain).days_old < 14
            • ml.link_analysis(.).effective_url.domain.tld in $suspicious_tlds
            • ml.link_analysis(.).credphish.contains_captcha
            • ml.link_analysis(.).credphish.disposition is 'phishing'
            • ml.link_analysis(.).final_dom.display_text contains "I'm Human"
    • all of:
      • length(body.current_thread.text) < 50
      • any of attachments where all hold:
        • any of:
          • .file_extension is 'pdf'
          • .file_type is 'pdf'
        • any of file.explode(.) where any holds:
          • all of:
            • length(ml.nlu_classifier(.scan.ocr.raw).topics) is 1
            • any of ml.nlu_classifier(.scan.ocr.raw).topics where all hold:
              • .name is 'Legal and Compliance'
              • .confidence in ('medium', 'high')
            • not:
              • any of ml.nlu_classifier(.scan.ocr.raw).entities where all hold:
                • .name is 'sender'
                • .text is sender.display_name
          • .scan.ocr.raw matches any of 6 patterns
            • pornograph(y|ie)
            • interpol\b
            • europol
            • dissuade
            • ce jeu en ligne
            • vraie vie

Inspects: attachments[].file_extension, attachments[].file_name, attachments[].file_type, body.current_thread.text, body.plain.raw, headers.in_reply_to, headers.references, sender.display_name, subject.base, type.inbound. Sensors: file.explode, ml.link_analysis, ml.nlu_classifier, network.whois, regex.contains, regex.extract, regex.icontains, strings.icontains, strings.ilike, strings.istarts_with. Reference lists: $suspicious_tlds, $url_shorteners.

Indicators matched (21)

FieldMatchValue
regex.containsregex[\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}]
regex.extractregex(?P<file_name>.*?)(?:\s*\([^)]+\))*\.[^.]+$
attachments[].file_extensionequalspdf
attachments[].file_typeequalspdf
strings.ilikesubstring*Google Docs Renderer*
strings.ilikesubstring*Skia/PDF*
strings.ilikesubstring*Neevia Document Converter*
strings.istarts_withprefixwkhtmltopdf
ml.nlu_classifier(body.current_thread.text).topics[].nameequalsLegal and Compliance
ml.nlu_classifier(body.current_thread.text).topics[].confidencemembermedium
ml.nlu_classifier(body.current_thread.text).topics[].confidencememberhigh
strings.icontainssubstringI'm Human
9 more
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].nameequalsLegal and Compliance
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].confidencemembermedium
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].confidencememberhigh
regex.icontainsregexpornograph(y|ie)
regex.icontainsregexinterpol\b
regex.icontainsregexeuropol
regex.icontainsregexdissuade
regex.icontainsregexce jeu en ligne
regex.icontainsregexvraie vie

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      any(attachments)
        and
          any(file.explode(attachments))
            or
              and
                not
                  any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).entities)
                    and
                      ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).entities[].name eq "sender"
                      ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).entities[].text cross_field_compare "sender.display_name"
                any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).topics)
                  and
                    ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].confidence in ["high", "medium"]
                    ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].name eq "Legal and Compliance"
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics length_compare "1"
              file.explode(attachments[])[].scan.ocr.raw regex_match "ce jeu en ligne"
              file.explode(attachments[])[].scan.ocr.raw regex_match "dissuade"
              file.explode(attachments[])[].scan.ocr.raw regex_match "europol"
              file.explode(attachments[])[].scan.ocr.raw regex_match "interpol\\b"
              file.explode(attachments[])[].scan.ocr.raw regex_match "pornograph(y|ie)"
              file.explode(attachments[])[].scan.ocr.raw regex_match "vraie vie"
          or
            attachments.file_extension eq "pdf"
            attachments.file_type eq "pdf"
      body.current_thread.text length_compare "50"
    and
      any(attachments)
        and
          any(file.explode(attachments))
            and
              any(file.explode(attachments).scan.pdf.urls)
                or
                  ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.pdf.urls[]).credphish.contains_captcha"
                  ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.pdf.urls[]).credphish.disposition == phishing"
                  ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.pdf.urls[]).effective_url.domain.tld in suspicious_tlds"
                  ml.link_analysis(file.explode(attachments[])[].scan.pdf.urls[]).final_dom.display_text contains "I'm Human"
                  network.whois func_call "network.whois(file.explode(attachments[])[].scan.pdf.urls[].domain).days_old < 14"
                   macro "file.explode(attachments[])[].scan.pdf.urls[].domain.domain in url_shorteners"
                   macro "file.explode(attachments[])[].scan.pdf.urls[].domain.root_domain in url_shorteners"
              file.explode(attachments[])[].scan.pdf.urls length_compare "0"
              file.explode(attachments[])[].scan.pdf.urls length_compare "5"
          or
            attachments.file_extension eq "pdf"
            attachments.file_type eq "pdf"
      any(ml.nlu_classifier(body.current_thread.text).topics)
        and
          ml.nlu_classifier(body.current_thread.text).topics.confidence in ["high", "medium"]
          ml.nlu_classifier(body.current_thread.text).topics.name eq "Legal and Compliance"
  any(attachments)
    and
      any(file.explode(attachments))
        or
          file.explode(attachments[])[].scan.exiftool.creator starts_with "wkhtmltopdf"
          file.explode(attachments[])[].scan.exiftool.producer match "Google Docs Renderer"
          file.explode(attachments[])[].scan.exiftool.producer match "Neevia Document Converter"
          file.explode(attachments[])[].scan.exiftool.producer match "Skia/PDF"
      or
        attachments.file_extension eq "pdf"
        attachments.file_type eq "pdf"
  or
    any(attachments)
      any(regex.extract(attachments.file_name))
        filter(attachments, strings.istarts_with(regex.extract(attachments[].file_name)[].file_name, attachments[].named_groups['file_name'])) length_compare "1"
    attachments length_compare "1"
  or
    body.current_thread.text length_compare "1500"
    body.plain.raw regex_match "[\\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}]"
    subject.base regex_match "[\\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}]"
  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
body.plain.rawregex_match
  • [\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}]
field:"body.plain.raw" kind:regex_match value:"[\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}]"
headers.in_reply_tois_null
  • (no value, null check)
field:"headers.in_reply_to" kind:is_null
subject.baseregex_match
  • [\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}]
field:"subject.base" kind:regex_match value:"[\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}]"
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where any holds:
      • any of .scan.strings.strings where:
        • . matches '\\\\\\\\([a-zA-Z0-9_:%.$-]+)\\\\([a-zA-Z0-9_:%.$-]+)'
      • any of .scan.strings.strings where:
        • . matches '%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)'

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
      any(file.explode(attachments))
        or
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "\\\\\\\\([a-zA-Z0-9_:%.$-]+)\\\\([a-zA-Z0-9_:%.$-]+)"
      attachments.file_extension in ["lnk", "url"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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) is 0
  3. any of attachments where all hold:
    • .file_type in ('pdf', 'doc', 'docx')
    • any of file.explode(.) where:
      • any of .scan.url.urls where all hold:
        • .domain.root_domain is 'doubleclick.net'
        • any of:
          • .path contains '/aclk'
          • .path contains '/pcs/click'
          • .path contains '/searchads/link/click'
        • .query_params matches '&(?: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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          and
            or
              file.explode(attachments[])[].scan.url.urls[].path contains "/aclk"
              file.explode(attachments[])[].scan.url.urls[].path contains "/pcs/click"
              file.explode(attachments[])[].scan.url.urls[].path contains "/searchads/link/click"
            file.explode(attachments[])[].scan.url.urls[].domain.root_domain eq "doubleclick.net"
            file.explode(attachments[])[].scan.url.urls[].query_params regex_match "&(?:adurl|ds_dest_url)=(?:[a-z]+(?:\\:|%3a))?(?:\\/|%2f)(?:\\/|%2f)"
      attachments.file_type in ["doc", "docx", "pdf"]
  body.links length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
        • .file_extension is '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
        any(file.explode(attachments))
          file.explode(attachments).file_extension eq "lnk"
         macro "attachments[].file_extension in file_extensions_common_archives"
      attachments.file_extension eq "lnk"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .file_extension is 'lnk'
      • any of .scan.exiftool.fields where all hold:
        • .key is 'TargetFileSize'
        • .value is '0'
      • any of .scan.exiftool.fields where all hold:
        • .key is 'CommandLineArguments'
        • .value matches any of 3 patterns
          • *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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.exiftool.fields)
            and
              or
                file.explode(attachments[])[].scan.exiftool.fields[].value match "Set-Content"
                file.explode(attachments[])[].scan.exiftool.fields[].value match "findstr"
                file.explode(attachments[])[].scan.exiftool.fields[].value match "sc $path"
              file.explode(attachments[])[].scan.exiftool.fields[].key eq "CommandLineArguments"
          any(file.explode(attachments).scan.exiftool.fields)
            and
              file.explode(attachments[])[].scan.exiftool.fields[].key eq "TargetFileSize"
              file.explode(attachments[])[].scan.exiftool.fields[].value eq "0"
          file.explode(attachments[])[].file_extension eq "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
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 of file.explode(.) where all hold:
      • .file_extension is 'mht'
      • not:
        • .flavors.mime is '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
      any(file.explode(attachments))
        and
          not
            file.explode(attachments[])[].flavors.mime eq "message/rfc822"
          file.explode(attachments[])[].file_extension eq "mht"
       macro "attachments[].file_extension in file_extensions_macros"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.strings.strings where:
        • . matches '*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"
         macro "attachments[].file_extension in file_extensions_macros"
      any(file.explode(attachments))
        any(file.explode(attachments).scan.strings.strings)
          file.explode(attachments).scan.strings.strings match "new:C08AFD90-F2A1-11D1-8455-00A0C91F3880"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is '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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.yara.matches)
          file.explode(attachments).scan.yara.matches.name eq "MALFORMED_OLE_HEADER"
       macro "attachments[].file_extension in file_extensions_macros"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .flavors.yara contains 'onenote_file'
      • any of .scan.strings.strings where:
        • . matches any of 10 patterns
          • *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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            or
              file.explode(attachments[])[].scan.strings.strings[] match "CreateObject"
              file.explode(attachments[])[].scan.strings.strings[] match "CreateProcess"
              file.explode(attachments[])[].scan.strings.strings[] match "ExecuteCmdAsync"
              file.explode(attachments[])[].scan.strings.strings[] match "SetEnvironmentVariable"
              file.explode(attachments[])[].scan.strings.strings[] match "Wscript.Shell"
              file.explode(attachments[])[].scan.strings.strings[] match "WshShell"
              file.explode(attachments[])[].scan.strings.strings[] match "echo off"
              file.explode(attachments[])[].scan.strings.strings[] match "powershell"
              file.explode(attachments[])[].scan.strings.strings[] match "schtasks"
              file.explode(attachments[])[].scan.strings.strings[] match "winmgmts"
          file.explode(attachments[])[].flavors.yara contains "onenote_file"
      or
        attachments.file_extension eq "one"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "zipline_delivery_telekom"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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)) is 0
  3. any of:
    • any of attachments where all hold:
      • .file_type in $file_types_images
      • any of ml.logo_detect(.).brands where:
        • .name starts with 'Microsoft'
    • any of attachments where all hold:
      • .file_type in $file_types_images
      • any of file.explode(.) where all hold:
        • .scan.ocr.raw matches any of 2 patterns
          • *microsoft*
          • *office
        • length(.scan.ocr.raw) < 1500
  4. any of attachments where all hold:
    • .file_type in $file_types_images
    • any of file.explode(.) where any holds:
      • 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
      • all of:
        • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
          • .name is 'cred_theft'
          • .confidence is 'high'
        • 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) is 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
  any(attachments)
    and
      any(file.explode(attachments))
        or
          and
            any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
              and
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence eq "high"
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name eq "cred_theft"
            ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).entities length_compare "1"
          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(attachments[].scan.ocr.raw, file.explode(attachments[])[])) length_compare "2"
       macro "attachments[].file_type in file_types_images"
  or
    any(attachments)
      and
        any(file.explode(attachments))
          and
            or
              file.explode(attachments[])[].scan.ocr.raw ends_with "office"
              file.explode(attachments[])[].scan.ocr.raw match "microsoft"
            file.explode(attachments[])[].scan.ocr.raw length_compare "1500"
         macro "attachments[].file_type in file_types_images"
    any(attachments)
      and
        any(ml.logo_detect(attachments).brands)
          ml.logo_detect(attachments).brands.name starts_with "Microsoft"
         macro "attachments[].file_type in file_types_images"
  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
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"
  not
     macro "all(body.links)"
  body.links length_compare "0"
  filter(attachments, .file_type not in $file_types_images) 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
field:"type.inbound" kind:eq value:"true"

Attachment: Microsoft impersonation via PDF with link and suspicious language

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

Attached PDF contains a Microsoft-affilated logo, suspicious language or keywords, and a link. Known malware delivery method.

Threat classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesImage as content, Impersonation: Brand, PDF, Scripting, 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_extension == "pdf" or .file_type == "pdf")
      and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft"))
  )
)
and any(attachments,
        (.file_extension == "pdf" or .file_type == "pdf")
        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",
                                  'engine failed',
                                  'OneDrive Error',
                                  'problem connecting',                                  
                                  'secure file',
                                  'access'
                                ],
                                strings.icontains(..scan.ocr.raw, .)
                         )
                  ) >= 2
                  or any(ml.nlu_classifier(.scan.ocr.raw).intents,
                         .name == "cred_theft" and .confidence == "high"
                  )
                )
                and (length(.scan.url.urls) > 0 or length(.scan.pdf.urls) > 0)
        )
)
and (
  not any(headers.hops,
          .authentication_results.compauth.verdict is not null
          and .authentication_results.compauth.verdict == "pass"
          and sender.email.domain.domain in (
            "microsoft.com",
            "sharepointonline.com"
          )
  )
)
// 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 contains a Microsoft-affilated logo, suspicious language or keywords, and a link. Known malware delivery method.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension is 'pdf'
      • .file_type is 'pdf'
    • any of ml.logo_detect(.).brands where:
      • .name starts with 'Microsoft'
  3. any of attachments where all hold:
    • any of:
      • .file_extension is 'pdf'
      • .file_type is 'pdf'
    • any of file.explode(.) where all hold:
      • any of:
        • 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', 'engine failed', 'OneDrive Error', 'problem connecting', 'secure file', 'access'], strings.icontains(.scan.ocr.raw, .))) ≥ 2
        • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
          • .name is 'cred_theft'
          • .confidence is 'high'
      • any of:
        • length(.scan.url.urls) > 0
        • length(.scan.pdf.urls) > 0
  4. not:
    • any of headers.hops where all hold:
      • .authentication_results.compauth.verdict is set
      • .authentication_results.compauth.verdict is 'pass'
      • sender.email.domain.domain in ('microsoft.com', 'sharepointonline.com')
  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, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].authentication_results.compauth.verdict, sender.email.domain.domain, sender.email.domain.root_domain, type.inbound. Sensors: file.explode, ml.logo_detect, ml.nlu_classifier, strings.icontains, strings.starts_with. Reference lists: $high_trust_sender_root_domains.

Indicators matched (5)

FieldMatchValue
attachments[].file_extensionequalspdf
attachments[].file_typeequalspdf
strings.starts_withprefixMicrosoft
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
  any(attachments)
    and
      any(file.explode(attachments))
        and
          or
            any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
              and
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence eq "high"
                ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name eq "cred_theft"
            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', 'engine failed', 'OneDrive Error', 'problem connecting', 'secure file', 'access'], strings.icontains(attachments[].scan.ocr.raw, file.explode(attachments[])[])) length_compare "2"
          or
            file.explode(attachments[])[].scan.pdf.urls length_compare "0"
            file.explode(attachments[])[].scan.url.urls length_compare "0"
      or
        attachments.file_extension eq "pdf"
        attachments.file_type eq "pdf"
  any(attachments)
    and
      or
        attachments.file_extension eq "pdf"
        attachments.file_type eq "pdf"
      any(ml.logo_detect(attachments).brands)
        ml.logo_detect(attachments).brands.name starts_with "Microsoft"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    any(headers.hops)
      and
        headers.hops.authentication_results.compauth.verdict eq "pass"
        headers.hops.authentication_results.compauth.verdict is_not_null
        sender.email.domain.domain in ["microsoft.com", "sharepointonline.com"]
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: Microsoft OAuth credential harvesting via EML with embedded malicious links

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

Detects inbound messages containing EML attachments with embedded links targeting Microsoft OAuth authentication flows. The rule identifies suspicious Microsoft login URLs with specific query parameters indicating credential harvesting attempts, including offline access permissions, read/write scopes, and reprocessing endpoints. Links are detected within EML body content, embedded PDF/HTML attachments, and ICS calendar files.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, Evasion, PDF

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 in ("eml"))
        and (
          // links in attached EML body
          any(file.parse_eml(.).body.links,
              .href_url.domain.domain == 'login.microsoftonline.com'
              and (
                strings.ilike(.href_url.query_params,
                              '*offline_access*',
                              '*.readwrite*',
                              '*.read*',
                              '*ctx=*',
                              '*prompt=none*'
                )
                or (
                  strings.icontains(.href_url.path, '/common/reprocess')
                  and strings.icontains(.href_url.query_params, 'ctx=')
                  and strings.icontains(.href_url.query_params, 'sessionId=')
                )
              )
          )
          // links in PDF and HTML attachments inside the EML
          or any(filter(file.parse_eml(.).attachments,
                        .file_type in ("pdf", "html")
                 ),
                 any(file.explode(.),
                     any(.scan.url.urls,
                         .domain.domain == 'login.microsoftonline.com'
                         and (
                           strings.ilike(.query_params,
                                         '*offline_access*',
                                         '*.readwrite*',
                                         '*.read*',
                                         '*ctx=*',
                                         '*prompt=none*'
                           )
                           or (
                             strings.icontains(.path, '/common/reprocess')
                             and strings.icontains(.query_params, 'ctx=')
                             and strings.icontains(.query_params, 'sessionId=')
                           )
                         )
                     )
                 )
          )
          // links in ICS attachments inside the EML
          or any(filter(file.parse_eml(.).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
                 //
                 any(beta.file.parse_ics(.).events,
                     any(.links,
                         .href_url.domain.domain == 'login.microsoftonline.com'
                         and (
                           strings.ilike(.href_url.query_params,
                                         '*offline_access*',
                                         '*.readwrite*',
                                         '*.read*',
                                         '*ctx=*',
                                         '*prompt=none*'
                           )
                           or (
                             strings.icontains(.href_url.path,
                                               '/common/reprocess'
                             )
                             and strings.icontains(.href_url.query_params,
                                                   'ctx='
                             )
                             and strings.icontains(.href_url.query_params,
                                                   'sessionId='
                             )
                           )
                         )
                     )
                 )
          )
        )
) 

Detection logic

Scope: inbound message.

Detects inbound messages containing EML attachments with embedded links targeting Microsoft OAuth authentication flows. The rule identifies suspicious Microsoft login URLs with specific query parameters indicating credential harvesting attempts, including offline access permissions, read/write scopes, and reprocessing endpoints. Links are detected within EML body content, embedded PDF/HTML attachments, and ICS calendar files.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .content_type is 'message/rfc822'
      • .file_extension in ('eml')
    • any of:
      • any of file.parse_eml(.).body.links where all hold:
        • .href_url.domain.domain is 'login.microsoftonline.com'
        • any of:
          • .href_url.query_params matches any of 5 patterns
            • *offline_access*
            • *.readwrite*
            • *.read*
            • *ctx=*
            • *prompt=none*
          • all of:
            • .href_url.path contains '/common/reprocess'
            • .href_url.query_params contains 'ctx='
            • .href_url.query_params contains 'sessionId='
      • any of filter(...) where:
        • any of file.explode(.) where:
          • any of .scan.url.urls where all hold:
            • .domain.domain is 'login.microsoftonline.com'
            • any of:
              • .query_params matches any of 5 patterns
                • *offline_access*
                • *.readwrite*
                • *.read*
                • *ctx=*
                • *prompt=none*
              • all of:
                • .path contains '/common/reprocess'
                • .query_params contains 'ctx='
                • .query_params contains 'sessionId='
      • any of filter(...) where:
        • any of beta.file.parse_ics(.).events where:
          • any of .links where all hold:
            • .href_url.domain.domain is 'login.microsoftonline.com'
            • any of:
              • .href_url.query_params matches any of 5 patterns
                • *offline_access*
                • *.readwrite*
                • *.read*
                • *ctx=*
                • *prompt=none*
              • all of:
                • .href_url.path contains '/common/reprocess'
                • .href_url.query_params contains 'ctx='
                • .href_url.query_params contains 'sessionId='

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: beta.file.parse_ics, file.explode, file.parse_eml, strings.icontains, strings.ilike.

Indicators matched (19)

FieldMatchValue
attachments[].content_typeequalsmessage/rfc822
attachments[].file_extensionmembereml
file.parse_eml(attachments[]).body.links[].href_url.domain.domainequalslogin.microsoftonline.com
strings.ilikesubstring*offline_access*
strings.ilikesubstring*.readwrite*
strings.ilikesubstring*.read*
strings.ilikesubstring*ctx=*
strings.ilikesubstring*prompt=none*
strings.icontainssubstring/common/reprocess
strings.icontainssubstringctx=
strings.icontainssubstringsessionId=
file.parse_eml(attachments[]).attachments[].file_typememberpdf
7 more
file.parse_eml(attachments[]).attachments[].file_typememberhtml
file.explode(filter(...)[])[].scan.url.urls[].domain.domainequalslogin.microsoftonline.com
file.parse_eml(attachments[]).attachments[].file_typeequalsics
file.parse_eml(attachments[]).attachments[].file_extensionequalsics
file.parse_eml(attachments[]).attachments[].content_typememberapplication/ics
file.parse_eml(attachments[]).attachments[].content_typemembertext/calendar
beta.file.parse_ics(filter(...)[]).events[].links[].href_url.domain.domainequalslogin.microsoftonline.com

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      or
        any(filter(...))
          any(beta.file.parse_ics(filter(...)).events)
            any(beta.file.parse_ics(filter(...)).events.links)
              and
                or
                  and
                    beta.file.parse_ics(filter(...)[]).events[].links[].href_url.path contains "/common/reprocess"
                    beta.file.parse_ics(filter(...)[]).events[].links[].href_url.query_params contains "ctx="
                    beta.file.parse_ics(filter(...)[]).events[].links[].href_url.query_params contains "sessionId="
                  beta.file.parse_ics(filter(...)[]).events[].links[].href_url.query_params match ".read"
                  beta.file.parse_ics(filter(...)[]).events[].links[].href_url.query_params match ".readwrite"
                  beta.file.parse_ics(filter(...)[]).events[].links[].href_url.query_params match "ctx="
                  beta.file.parse_ics(filter(...)[]).events[].links[].href_url.query_params match "offline_access"
                  beta.file.parse_ics(filter(...)[]).events[].links[].href_url.query_params match "prompt=none"
                beta.file.parse_ics(filter(...)[]).events[].links[].href_url.domain.domain eq "login.microsoftonline.com"
        any(filter(...))
          any(file.explode(filter(...)))
            any(file.explode(filter(...)).scan.url.urls)
              and
                or
                  and
                    file.explode(filter(...)[])[].scan.url.urls[].path contains "/common/reprocess"
                    file.explode(filter(...)[])[].scan.url.urls[].query_params contains "ctx="
                    file.explode(filter(...)[])[].scan.url.urls[].query_params contains "sessionId="
                  file.explode(filter(...)[])[].scan.url.urls[].query_params match ".read"
                  file.explode(filter(...)[])[].scan.url.urls[].query_params match ".readwrite"
                  file.explode(filter(...)[])[].scan.url.urls[].query_params match "ctx="
                  file.explode(filter(...)[])[].scan.url.urls[].query_params match "offline_access"
                  file.explode(filter(...)[])[].scan.url.urls[].query_params match "prompt=none"
                file.explode(filter(...)[])[].scan.url.urls[].domain.domain eq "login.microsoftonline.com"
        any(file.parse_eml(attachments).body.links)
          and
            or
              and
                file.parse_eml(attachments[]).body.links[].href_url.path contains "/common/reprocess"
                file.parse_eml(attachments[]).body.links[].href_url.query_params contains "ctx="
                file.parse_eml(attachments[]).body.links[].href_url.query_params contains "sessionId="
              file.parse_eml(attachments[]).body.links[].href_url.query_params match ".read"
              file.parse_eml(attachments[]).body.links[].href_url.query_params match ".readwrite"
              file.parse_eml(attachments[]).body.links[].href_url.query_params match "ctx="
              file.parse_eml(attachments[]).body.links[].href_url.query_params match "offline_access"
              file.parse_eml(attachments[]).body.links[].href_url.query_params match "prompt=none"
            file.parse_eml(attachments[]).body.links[].href_url.domain.domain eq "login.microsoftonline.com"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where:
    • any of file.explode(.) where:
      • .scan.ocr.raw contains any of 3 patterns
        • 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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      or
        file.explode(filter(attachments)[])[].scan.ocr.raw contains " invited you to edit"
        file.explode(filter(attachments)[])[].scan.ocr.raw contains " use of Microsoft 365 and may contain content that is controlled by"
        file.explode(filter(attachments)[])[].scan.ocr.raw contains "This invite will only work for you and people with existing access"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name starts with '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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.yara.matches)
          file.explode(attachments).scan.yara.matches.name starts_with "ShellExplorer1_LNK_"
      or
        attachments.file_type eq "rtf"
         macro "attachments[].file_extension in file_extensions_macros"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where all hold:
    • beta.parse_exif(.).creator is 'Administrator'
    • any of beta.parse_exif(.).fields where all hold:
      • .key is 'TotalEditTime'
      • .value is '0'
    • not:
      • map(...) contains 'TitlesOfParts'

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
  any(filter(attachments))
    and
      any(beta.parse_exif(filter(attachments)).fields)
        and
          beta.parse_exif(filter(attachments)[]).fields[].key eq "TotalEditTime"
          beta.parse_exif(filter(attachments)[]).fields[].value eq "0"
      not
        map(...) contains "TitlesOfParts"
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).creator == Administrator"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
        • .file_extension is '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
        any(file.explode(attachments))
          file.explode(attachments).file_extension eq "msi"
         macro "attachments[].file_extension in file_extensions_common_archives"
    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
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 of file.explode(.) where all hold:
      • .flavors.mime is 'text/xml'
      • any of .scan.strings.strings where:
        • . matches '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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "Target.{0,20}http.{0,200}dotm"
          file.explode(attachments[])[].flavors.mime eq "text/xml"
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .file_extension in ('doc', 'docm', 'docx', 'dot', 'dotm', 'xls', 'xlsx', 'xlsm', 'xlm', 'xlsb', 'xlt', 'xltm', 'ppt', 'pptx', 'pptm', 'ppsm')
      • any of .scan.exiftool.fields where all hold:
        • .key is 'Tag_AssemblyLocation'
        • .value matches '*.vsto*'
        • not:
          • .value matches 'C:\\Program Files*'
        • not:
          • any of $org_domains where:
            • 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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.exiftool.fields)
            and
              not
                any($org_domains)
                  strings.contains func_call "strings.contains(file.explode(attachments[])[].scan.exiftool.fields[].value)"
              not
                file.explode(attachments[])[].scan.exiftool.fields[].value starts_with "C:\\Program Files"
              file.explode(attachments[])[].scan.exiftool.fields[].key eq "Tag_AssemblyLocation"
              file.explode(attachments[])[].scan.exiftool.fields[].value match ".vsto"
          file.explode(attachments[])[].file_extension in ["doc", "docm", "docx", "dot", "dotm", "ppsm", "ppt", "pptm", "pptx", "xlm", "xls", "xlsb", "xlsm", "xlsx", "xlt", "xltm"]
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
  or
    and
      headers.reply_to length_compare "0"
       macro "all(headers.reply_to)"
    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
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 of file.oletools(.).relationships where any holds:
      • all of:
        • any of ml.nlu_classifier(ml.link_analysis(.target_url).final_dom.display_text).intents where all hold:
          • .name is 'cred_theft'
          • .confidence in ('medium', 'high')
        • .target_url.domain.root_domain not in ('google.com', 'goo.gl')
        • ml.link_analysis(.target_url).effective_url.domain.domain is not 'login.microsoftonline.com'
      • ml.link_analysis(.target_url).credphish.disposition is '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
      any(file.oletools(attachments).relationships)
        or
          and
            any(ml.nlu_classifier(ml.link_analysis(file.oletools(attachments).relationships.target_url).final_dom.display_text).intents)
              and
                ml.nlu_classifier(ml.link_analysis(file.oletools(attachments[]).relationships[].target_url).final_dom.display_text).intents[].confidence in ["high", "medium"]
                ml.nlu_classifier(ml.link_analysis(file.oletools(attachments[]).relationships[].target_url).final_dom.display_text).intents[].name eq "cred_theft"
            not
              file.oletools(attachments[]).relationships[].target_url.domain.root_domain in ["goo.gl", "google.com"]
            ml.link_analysis func_call "ml.link_analysis(file.oletools(attachments[]).relationships[].target_url).effective_url.domain.domain != login.microsoftonline.com"
          ml.link_analysis func_call "ml.link_analysis(file.oletools(attachments[]).relationships[].target_url).credphish.disposition == phishing"
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
         macro "attachments[].file_extension in file_extensions_macros"
      file.oletools(attachments[]).relationships length_compare "500"
  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
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of filter(.scan.url.urls) where all hold:
        • ml.link_analysis(.).credphish.disposition is 'phishing'
        • coalesce(ml.link_analysis(.).credphish.confidence == 'high')
        • not:
          • all of:
            • ml.link_analysis(.).credphish.brand.name is set
            • ml.link_analysis(.).credphish.brand.name is 'GoDaddy'
            • ml.link_analysis(.).final_dom.inner_text contains 'is parked free, courtesy of GoDaddy.com.'
            • ml.link_analysis(.).final_dom.inner_text contains '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(filter(file.explode(filter(attachments)).scan.url.urls))
        and
          not
            and
              ml.link_analysis func_call "ml.link_analysis(filter(file.explode(filter(attachments)[])[].scan.url.urls)[]).credphish.brand.name == GoDaddy"
              ml.link_analysis(filter(file.explode(filter(attachments)[])[].scan.url.urls)[]).credphish.brand.name is_not_null
              ml.link_analysis(filter(file.explode(filter(attachments)[])[].scan.url.urls)[]).final_dom.inner_text contains "Get This Domain"
              ml.link_analysis(filter(file.explode(filter(attachments)[])[].scan.url.urls)[]).final_dom.inner_text contains "is parked free, courtesy of GoDaddy.com."
          coalesce func_call "coalesce(ml.link_analysis(filter(file.explode(filter(attachments)[])[].scan.url.urls)[]).credphish.confidence == 'high')"
          ml.link_analysis func_call "ml.link_analysis(filter(file.explode(filter(attachments)[])[].scan.url.urls)[]).credphish.disposition == phishing"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where all hold:
    • any of file.explode(.) where any holds:
      • all of:
        • length(.scan.strings.raw) < 1000
        • .scan.strings.raw matches '(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)'
      • all of:
        • length(.scan.ocr.raw) < 1000
        • .scan.ocr.raw matches '(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)'
      • all of:
        • length(.scan.ocr.raw) < 500
        • .scan.ocr.raw ends with 'REVIEW DOCUMENTS'
    • any of file.explode(.) where any holds:
      • all of:
        • length(.scan.strings.raw) < 1000
        • .scan.strings.raw matches any of 2 patterns
          • (?:copy (?:and paste)?|right.?click)(?:\s+\w+\s*){0,9}browser
          • click.{0,50}(?:above|below|button) to (?:access|open)
      • all of:
        • length(.scan.ocr.raw) < 1000
        • .scan.ocr.raw matches any of 2 patterns
          • (?:copy (?:and paste)?|right.?click)(?:\s+\w+\s*){0,9}browser
          • click.{0,50}(?:above|below|button) to (?:access|open)
      • at least 5 of 39: .scan.ocr.raw contains any of 39 patterns
        • confidential and intended solely
        • intended solely for the use of
        • intended only for the people
        • intended recipient
        • received this email in error
        • notify the sender immediately
        • delete it from your system
        • delete the email from
        • virus-free
        • scan for viruses
        • legally binding agreement
        • informational purposes only
        • any attachments are confidential
        • loss or damage arising
        • responsibility for any loss
        • unauthorised and prohibited
        • subject to legal privilege
        • The information contained in or attached
        • The information contained in this email
        • people to whom it is addressed
        • received this in error, please inform
        • inform the sender and/or
        • immediately and delete the material
        • then delete the email from your inbox
        • confidential and/or privileged material
        • confidential and / or legally privileged
        • The information transmitted is intended
        • other than the intended recipient is prohibited
        • intended for use by the addressee
        • taking of any action in reliance upon
        • distribution is strictly prohibited
        • communication from the sender is confidential
        • use by the recipient
        • and others authorized to receive it
        • you are hereby notified
        • action in relation of the contents of this information
        • The information contained in this
        • you are not the recipient
        • 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
  any(filter(attachments))
    and
      any(file.explode(filter(attachments)))
        or
          and
            or
              file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "(?:copy (?:and paste)?|right.?click)(?:\\s+\\w+\\s*){0,9}browser"
              file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "click.{0,50}(?:above|below|button) to (?:access|open)"
            file.explode(filter(attachments)[])[].scan.ocr.raw length_compare "1000"
          and
            or
              file.explode(filter(attachments)[])[].scan.strings.raw regex_match "(?:copy (?:and paste)?|right.?click)(?:\\s+\\w+\\s*){0,9}browser"
              file.explode(filter(attachments)[])[].scan.strings.raw regex_match "click.{0,50}(?:above|below|button) to (?:access|open)"
            file.explode(filter(attachments)[])[].scan.strings.raw length_compare "1000"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "The information contained in or attached"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "The information contained in this email"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "The information contained in this"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "The information transmitted is intended"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "action in relation of the contents of this information"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "and others authorized to receive it"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "any attachments are confidential"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "communication from the sender is confidential"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "confidential and / or legally privileged"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "confidential and intended solely"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "confidential and/or privileged material"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "delete it from your system"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "delete the email from"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "distribution is strictly prohibited"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "immediately and delete the material"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "inform the sender and/or"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "informational purposes only"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "intended for use by the addressee"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "intended only for the people"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "intended recipient"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "intended solely for the use of"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "legally binding agreement"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "loss or damage arising"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "may be unlawful"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "notify the sender immediately"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "other than the intended recipient is prohibited"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "people to whom it is addressed"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "received this email in error"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "received this in error, please inform"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "responsibility for any loss"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "scan for viruses"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "subject to legal privilege"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "taking of any action in reliance upon"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "then delete the email from your inbox"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "unauthorised and prohibited"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "use by the recipient"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "virus-free"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "you are hereby notified"
          file.explode(filter(attachments)[])[].scan.ocr.raw contains "you are not the recipient"
      any(file.explode(filter(attachments)))
        or
          and
            file.explode(filter(attachments)[])[].scan.ocr.raw ends_with "REVIEW DOCUMENTS"
            file.explode(filter(attachments)[])[].scan.ocr.raw length_compare "500"
          and
            file.explode(filter(attachments)[])[].scan.ocr.raw length_compare "1000"
            file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)"
          and
            file.explode(filter(attachments)[])[].scan.strings.raw length_compare "1000"
            file.explode(filter(attachments)[])[].scan.strings.raw regex_match "(?:sent|shared|forwarded|provided|invited|received)(?:\\s+\\w+){0,9}\\s+(?:document|file|attachment)"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where any holds:
      • all of:
        • any of .scan.strings.strings where:
          • . matches '*URLDownloadToFile*'
        • any of .scan.strings.strings where:
          • . matches '*Auto_Open*'
      • any of .scan.strings.strings where:
        • . matches '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
      any(file.explode(attachments))
        or
          and
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "Auto_Open"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings match "URLDownloadToFile"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings regex_match "C:\\\\[A-Za-z]{7}\\\\[A-Za-z]{7}\\\\[A-Za-z]{7}"
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
  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
field:"type.inbound" kind:eq value:"true"

Attachment: OLE external relationship containing file scheme link to executable filetype

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

This rule identifies attachments containing file scheme links pointing to executable file types, a common indicator of malware distribution. It applies to various suspicious file extensions and archive formats, aiming to prevent the initiation and execution of malicious software.

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 (
            .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,
                .target_url.scheme == "file"
                and regex.icontains(.target_url.path,
                                    '\.(action|ahk|apk|app|appimage|applescript|bat|bin|cab|cmd|command|cpl|dll|dmg|exe|gadget|hta|inf|ins|ipa|isu|jar|job|js|jse|lnk|msi|msp|paf|pif|ps1|rgs|run|scr|sct|sh|shb|vb|vbe|vbs)($|[^\w])'
                )
                // avoid flagging on internal/network drives mappings
                and not (
                  strings.starts_with(.target_url.scheme, "file")
                  and not regex.imatch(.target_url.path, '/?[a-z]:/')
                )
        )
)
and (
  not profile.by_sender().any_messages_benign
  or profile.by_sender().any_messages_malicious_or_spam
)

Detection logic

Scope: inbound message.

This rule identifies attachments containing file scheme links pointing to executable file types, a common indicator of malware distribution. It applies to various suspicious file extensions and archive formats, aiming to prevent the initiation and execution of malicious software.

  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
    • length(file.oletools(.).relationships) < 500
    • any of file.oletools(.).relationships where all hold:
      • .target_url.scheme is 'file'
      • .target_url.path matches '\\.(action|ahk|apk|app|appimage|applescript|bat|bin|cab|cmd|command|cpl|dll|dmg|exe|gadget|hta|inf|ins|ipa|isu|jar|job|js|jse|lnk|msi|msp|paf|pif|ps1|rgs|run|scr|sct|sh|shb|vb|vbe|vbs)($|[^\\w])'
      • not:
        • all of:
          • .target_url.scheme starts with 'file'
          • not:
            • .target_url.path matches '/?[a-z]:/'
  3. any of:
    • not:
      • profile.by_sender().any_messages_benign
    • profile.by_sender().any_messages_malicious_or_spam

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, attachments[].size, type.inbound. Sensors: file.oletools, profile.by_sender, regex.icontains, regex.imatch, strings.starts_with. Reference lists: $file_extensions_common_archives, $file_extensions_macros.

Indicators matched (5)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
file.oletools(attachments[]).relationships[].target_url.schemeequalsfile
regex.icontainsregex\.(action|ahk|apk|app|appimage|applescript|bat|bin|cab|cmd|command|cpl|dll|dmg|exe|gadget|hta|inf|ins|ipa|isu|jar|job|js|jse|lnk|msi|msp|paf|pif|ps1|rgs|run|scr|sct|sh|shb|vb|vbe|vbs)($|[^\w])
regex.imatchregex/?[a-z]:/

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.oletools(attachments).relationships)
        and
          not
            and
              not
                file.oletools(attachments[]).relationships[].target_url.path regex_match "/?[a-z]:/"
              file.oletools(attachments[]).relationships[].target_url.scheme starts_with "file"
          file.oletools(attachments[]).relationships[].target_url.path regex_match "\\.(action|ahk|apk|app|appimage|applescript|bat|bin|cab|cmd|command|cpl|dll|dmg|exe|gadget|hta|inf|ins|ipa|isu|jar|job|js|jse|lnk|msi|msp|paf|pif|ps1|rgs|run|scr|sct|sh|shb|vb|vbe|vbs)($|[^\\w])"
          file.oletools(attachments[]).relationships[].target_url.scheme eq "file"
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
      file.oletools(attachments[]).relationships length_compare "500"
  or
    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"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: OLE external relationship containing file scheme link to IP address

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

This rule identifies attachments containing file scheme links pointing to IP Addresses, a common indicator of malware distribution. It applies to various suspicious file extensions and archive formats, aiming to prevent the initiation and execution of malicious software. The rule negates firing on IP addresses governed by RFC1918 or privately allocated space.

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 (
            .file_extension is null
            and .file_type == "unknown"
            and .content_type == "application/octet-stream"
            and .size < 100000000
          )
        )
        and any(file.oletools(.).relationships,
                .target_url.scheme == "file"
                and regex.contains(.target_url.path,
                                   '([0-9]{2,3}\.){3}[0-9]{2,3}'
                )
                and not regex.icontains(.target_url.path,
                                        '(10\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5]))|(172\.(?:1[6-9]|2\d|3[0-1])\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5]))|(192\.168\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5]))'
                )
        )
)
and (
  not profile.by_sender().any_messages_benign
  or profile.by_sender().any_messages_malicious_or_spam
)

Detection logic

Scope: inbound message.

This rule identifies attachments containing file scheme links pointing to IP Addresses, a common indicator of malware distribution. It applies to various suspicious file extensions and archive formats, aiming to prevent the initiation and execution of malicious software. The rule negates firing on IP addresses governed by RFC1918 or privately allocated space.

  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 of file.oletools(.).relationships where all hold:
      • .target_url.scheme is 'file'
      • .target_url.path matches '([0-9]{2,3}\\.){3}[0-9]{2,3}'
      • not:
        • .target_url.path matches '(10\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))|(172\\.(?:1[6-9]|2\\d|3[0-1])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))|(192\\.168\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))'
  3. any of:
    • not:
      • profile.by_sender().any_messages_benign
    • profile.by_sender().any_messages_malicious_or_spam

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

Indicators matched (4)

FieldMatchValue
attachments[].file_typeequalsunknown
attachments[].content_typeequalsapplication/octet-stream
file.oletools(attachments[]).relationships[].target_url.schemeequalsfile
regex.containsregex([0-9]{2,3}\.){3}[0-9]{2,3}

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.oletools(attachments).relationships)
        and
          not
            file.oletools(attachments[]).relationships[].target_url.path regex_match "(10\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))|(172\\.(?:1[6-9]|2\\d|3[0-1])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))|(192\\.168\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))"
          file.oletools(attachments[]).relationships[].target_url.path regex_match "([0-9]{2,3}\\.){3}[0-9]{2,3}"
          file.oletools(attachments[]).relationships[].target_url.scheme eq "file"
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
         macro "attachments[].file_extension in file_extensions_common_archives"
         macro "attachments[].file_extension in file_extensions_macros"
  or
    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"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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) is 1
  3. any of filter(attachments) where all hold:
    • any of beta.parse_exif(.).fields where:
      • .value contains 'password protected'
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    and
      any(file.explode(filter(attachments)))
        any(file.explode(filter(attachments)).scan.yara.matches)
          file.explode(filter(attachments)).scan.yara.matches.name eq "pwd_protected_pdf_fake_document_1"
      any(beta.parse_exif(filter(attachments)).fields)
        beta.parse_exif(filter(attachments)).fields.value contains "password protected"
  attachments length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where all hold:
    • beta.parse_exif(.).page_count ≤ 2
    • any of file.explode(.) where:
      • any of .scan.url.urls where:
        • .domain.root_domain is '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
  any(filter(attachments))
    and
      any(file.explode(filter(attachments)))
        any(file.explode(filter(attachments)).scan.url.urls)
          file.explode(filter(attachments)).scan.url.urls.domain.root_domain eq "workers.dev"
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).page_count <= 2"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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) is 1
  3. any of attachments where all hold:
    • .file_type is 'pdf'
    • beta.parse_exif(.).page_count is 1
  4. at least 2 of:
    • any of attachments where:
      • any of file.explode(.) where:
        • any of .scan.url.urls where:
          • ml.link_analysis(., mode='aggressive').final_dom.display_text matches '(?:\\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 [subject.base, sender.display_name, body.current_thread.text] where:
      • . matches '\\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 of file.explode(.) where:
        • .scan.ocr.raw matches '(?:\\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 of file.explode(.) where:
        • any of .scan.url.urls where:
          • .url matches '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'
  5. any of:
    • any of attachments where:
      • any of file.explode(.) where any holds:
        • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
          • .name is 'cred_theft'
          • .confidence is 'high'
        • any of ml.nlu_classifier(.scan.ocr.raw).topics where all hold:
          • .name is 'Purchase Orders'
          • .confidence is 'high'
    • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
      • .name is 'cred_theft'
      • .confidence is 'high'
    • any of ml.nlu_classifier(body.current_thread.text).topics where all hold:
      • .name is 'Purchase Orders'
      • .confidence is 'high'
  6. any of attachments where:
    • any of file.explode(.) where:
      • any of .scan.url.urls where any holds:
        • .domain.root_domain in $self_service_creation_platform_domains
        • .domain.domain in $self_service_creation_platform_domains
        • .domain.root_domain in $free_file_hosts
        • .domain.domain in $free_file_hosts
        • .domain.root_domain in $free_subdomain_hosts
        • .domain.domain in $free_subdomain_hosts
        • .domain.tld in $suspicious_tlds
        • .domain.domain in $url_shorteners
        • .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
    any(attachments)
      any(file.explode(attachments))
        or
          any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence eq "high"
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name eq "cred_theft"
          any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).topics)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].confidence eq "high"
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).topics[].name eq "Purchase Orders"
    any(ml.nlu_classifier(body.current_thread.text).intents)
      and
        ml.nlu_classifier(body.current_thread.text).intents.confidence eq "high"
        ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
    any(ml.nlu_classifier(body.current_thread.text).topics)
      and
        ml.nlu_classifier(body.current_thread.text).topics.confidence eq "high"
        ml.nlu_classifier(body.current_thread.text).topics.name eq "Purchase Orders"
  or
    any(attachments)
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          file.explode(attachments).scan.url.urls.url regex_match "(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)"
    any(attachments)
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          ml.link_analysis(file.explode(attachments[])[].scan.url.urls[], mode='aggressive').final_dom.display_text regex_match "(?:\\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(attachments))
        file.explode(attachments).scan.ocr.raw regex_match "(?:\\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([subject.base, sender.display_name, body.current_thread.text])
      [subject.base, sender.display_name, body.current_thread.text] regex_match "\\b(?:bid|proposal|rfp|rfq|quotation)\\b"
    any(attachments)
      attachments.file_name regex_match "\\b(?:bid|proposal|rfp|rfq|quotation)\\b"
  any(attachments)
    any(file.explode(attachments))
      any(file.explode(attachments).scan.url.urls)
        or
           macro "file.explode(attachments[])[].scan.url.urls[].domain.domain in free_file_hosts"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.domain in free_subdomain_hosts"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.domain in self_service_creation_platform_domains"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.domain in url_shorteners"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in free_file_hosts"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in free_subdomain_hosts"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in self_service_creation_platform_domains"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in url_shorteners"
           macro "file.explode(attachments[])[].scan.url.urls[].domain.tld in suspicious_tlds"
  any(attachments)
    and
      attachments.file_type eq "pdf"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).page_count == 1"
  not
    and
      sender.email.domain.root_domain eq "effem.com"
      sender.email.local_part eq "workflow.robot"
  not
    profile.by_sender func_call "profile.by_sender().solicited"
  not
     macro "all(body.links)"
  attachments length_compare "1"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name in ["invoice_pdf_01", "w9_pdf_01", "w9_pdf_IDs"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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) is 1
  4. all of attachments where all hold:
    • .file_extension is 'pdf'
    • .file_name matches '(\\d\\.\\d{3,4}.{0,12}BTC|bitcoin)'
    • any of file.explode(.) where all hold:
      • .scan.exiftool.page_count ≥ 5
      • .depth is 0
      • length(filter(.scan.strings.strings, regex.match(., '^\\/URI \\(http.*'))) is 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"
  type.inbound eq "true"
   macro "all(attachments)"
   macro "sender.email.domain.root_domain in free_email_providers"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: PDF file with low reputation link to ZIP file (unsolicited)

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

Detects messages with PDF attachments linking directly to zip files from unsolicited senders.

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
  • body
  • body.current_thread
  • type

Rule body

type.inbound
and any(ml.nlu_classifier(body.current_thread.text).entities,
        .name == "request"
)
and any(attachments,
        .file_extension == "pdf"
        and any(file.explode(.),
                any(.scan.pdf.urls,
                    regex.contains(.url, '\.(?:zip)')
                    and .domain.root_domain not in $tranco_1m
                )
        )
)
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 PDF attachments linking directly to zip files from unsolicited senders.

  1. inbound message
  2. any of ml.nlu_classifier(body.current_thread.text).entities where:
    • .name is 'request'
  3. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any of file.explode(.) where:
      • any of .scan.pdf.urls where all hold:
        • .url matches '\\.(?:zip)'
        • .domain.root_domain not in $tranco_1m
  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

Inspects: attachments[].file_extension, body.current_thread.text, type.inbound. Sensors: file.explode, ml.nlu_classifier, profile.by_sender, regex.contains. Reference lists: $tranco_1m.

Indicators matched (3)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsrequest
attachments[].file_extensionequalspdf
regex.containsregex\.(?:zip)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.pdf.urls)
          and
            file.explode(attachments[])[].scan.pdf.urls[].url regex_match "\\.(?:zip)"
             macro "file.explode(attachments[])[].scan.pdf.urls[].domain.root_domain not in tranco_1m"
      attachments.file_extension eq "pdf"
  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(ml.nlu_classifier(body.current_thread.text).entities)
    ml.nlu_classifier(body.current_thread.text).entities.name eq "request"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: PDF file with low reputation links to suspicious filetypes (unsolicited)

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

Detects messages with PDF attachments linking directly to suspicious filetypes on hosts with low reputation from unsolicited senders.

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
  • body
  • body.current_thread
  • type

Rule body

type.inbound
and any(ml.nlu_classifier(body.current_thread.text).entities,
        .name == "request"
)
and any(attachments,
        .file_extension == "pdf"
        and any(file.explode(.),
                any(.scan.pdf.urls,
                    regex.contains(.path,
                                   '\.(?:exe|cab|vbs|ps1|rar|iso|dll|one|lnk|sh)\b'
                    )
                    and .domain.root_domain not in $tranco_1m
                )
        )
)
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 PDF attachments linking directly to suspicious filetypes on hosts with low reputation from unsolicited senders.

  1. inbound message
  2. any of ml.nlu_classifier(body.current_thread.text).entities where:
    • .name is 'request'
  3. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any of file.explode(.) where:
      • any of .scan.pdf.urls where all hold:
        • .path matches '\\.(?:exe|cab|vbs|ps1|rar|iso|dll|one|lnk|sh)\\b'
        • .domain.root_domain not in $tranco_1m
  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

Inspects: attachments[].file_extension, body.current_thread.text, type.inbound. Sensors: file.explode, ml.nlu_classifier, profile.by_sender, regex.contains. Reference lists: $tranco_1m.

Indicators matched (3)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).entities[].nameequalsrequest
attachments[].file_extensionequalspdf
regex.containsregex\.(?:exe|cab|vbs|ps1|rar|iso|dll|one|lnk|sh)\b

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.pdf.urls)
          and
            file.explode(attachments[])[].scan.pdf.urls[].path regex_match "\\.(?:exe|cab|vbs|ps1|rar|iso|dll|one|lnk|sh)\\b"
             macro "file.explode(attachments[])[].scan.pdf.urls[].domain.root_domain not in tranco_1m"
      attachments.file_extension eq "pdf"
  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(ml.nlu_classifier(body.current_thread.text).entities)
    ml.nlu_classifier(body.current_thread.text).entities.name eq "request"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where all hold:
    • strings.icontains(.file_name)
    • .file_name starts with 'ATT'
    • .file_name contains '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
  any(filter(attachments))
    and
      filter(attachments).file_name contains "eCheckRun"
      filter(attachments).file_name starts_with "ATT"
      strings.icontains func_call "strings.icontains(filter(attachments)[].file_name)"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where all hold:
    • beta.parse_exif(.).producer starts with 'Qt'
    • beta.parse_exif(.).creator contains 'wkhtmltopdf'
    • beta.parse_exif(.).title is '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
  any(filter(attachments))
    and
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).title == Document"
      beta.parse_exif(filter(attachments)[]).creator contains "wkhtmltopdf"
      beta.parse_exif(filter(attachments)[]).producer starts_with "Qt"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • .scan.pdf_obj_hash.object_hash is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      file.explode(filter(attachments)).scan.pdf_obj_hash.object_hash eq "63bf167b66091a4bc53e8944a76f6b08"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • .scan.pdf_obj_hash.object_hash is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      file.explode(filter(attachments)).scan.pdf_obj_hash.object_hash eq "cc08b7eae4b6f5f4e897dd0998b90e21"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • .scan.pdf_obj_hash.object_hash is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      file.explode(filter(attachments)).scan.pdf_obj_hash.object_hash eq "cf509abbdc5aa6b1b759a216e3e570cf"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • .scan.pdf_obj_hash.object_hash is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      file.explode(filter(attachments)).scan.pdf_obj_hash.object_hash eq "8638ef6bfe382a927aa12a18f2150757"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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(.scan.url.urls) == 1
                and all(.scan.url.urls,
                        .domain.root_domain not in (
                          'iso.org',
                          'w3.org',
                          'bfo.com', // pdf producer
                          'camscanner.com', // pdf producer
                        )
                        and not strings.istarts_with(.url, 'mailto')
                )
        )
)
// negate highly trusted sender domains unless they fail DMARC authentication
and not (
  sender.email.domain.root_domain in $high_trust_sender_root_domains
  and coalesce(headers.auth_summary.dmarc.pass, false)
)

Detection logic

Scope: inbound message.

PDF attachment with 'proposal' in filename contains sender or recipient domain, credential theft language detected via OCR, and includes a single URL link.

  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')) is 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 is 1
    • any of ml.nlu_classifier(beta.ocr(.).text).intents where:
      • .name is 'cred_theft'
    • length(beta.ocr(.).text) < 2000
    • beta.ocr(.).success
    • any of file.explode(.) where all hold:
      • .depth is 0
      • length(.scan.url.urls) is 1
      • all of .scan.url.urls where all hold:
        • .domain.root_domain not in ('iso.org', 'w3.org', 'bfo.com', 'camscanner.com')
        • not:
          • .url starts with 'mailto'
  5. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass)

Inspects: attachments[].file_name, attachments[].file_type, headers.auth_summary.dmarc.pass, headers.in_reply_to, headers.references, sender.email.domain.root_domain, subject.is_forward, subject.is_reply, type.inbound. Sensors: beta.ocr, beta.parse_exif, file.explode, ml.nlu_classifier, regex.icontains, strings.istarts_with. Reference lists: $high_trust_sender_root_domains.

Indicators matched (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
  any(attachments)
    and
      any(file.explode(attachments))
        and
          file.explode(attachments[])[].depth eq "0"
          file.explode(attachments[])[].scan.url.urls length_compare "1"
           macro "all(file.explode(attachments[])[].scan.url.urls)"
      any(ml.nlu_classifier(beta.ocr(attachments).text).intents)
        ml.nlu_classifier(beta.ocr(attachments).text).intents.name eq "cred_theft"
      attachments.file_name regex_match "(?:proposal|bid|document|rf[pq])\\b"
      attachments.file_type eq "pdf"
      beta.ocr func_call "beta.ocr(attachments[]).success"
      beta.ocr(attachments[]).text length_compare "2000"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).page_count == 1"
  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"
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
  filter(attachments, .file_type == 'pdf') length_compare "1"
  type.inbound eq "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"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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"
        // a single page pdf
        and beta.parse_exif(.).page_count == 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)\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'
    • beta.parse_exif(.).page_count is 1
    • any of file.explode(.) where any holds:
      • any of .scan.strings.strings where:
        • . matches any of 17 patterns
          • ^\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)\s*$
          • View Secure Fax
          • It seems there was an issue opening the document. Please view it online.
          • Update Adobe Viewer
          • Learn more about messages protected by Microsoft
          • This document is protected by 256-bit encryption.
          • .*sent you a \S+ to review(?:\s*(?:and|&)\s*sign)$
          • ^You received a \S+ to review and sign$
          • \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
      • all of:
        • .scan.strings.strings contains 'Error'
        • any of .scan.strings.strings where:
          • . matches '^\\s*(?:View Video)\\s*$'
      • all of:
        • length(.scan.strings.strings) is 1
        • .scan.strings.strings contains 'Some additional information here'
    • any of file.explode(.) where all hold:
      • .depth is 0
      • any of:
        • length(filter(.scan.url.urls, not strings.istarts_with(.url, 'mailto:') and not strings.istarts_with(.url, 'email:') 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'))) is 1
        • all of:
          • length(distinct(filter(.scan.url.urls, not strings.istarts_with(.url, 'mailto:') and not strings.istarts_with(.url, 'email:') 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)) is 1
          • all of distinct(...) where any holds:
            • .domain.domain in $self_service_creation_platform_domains
            • .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 (21)

FieldMatchValue
attachments[].file_typeequalspdf
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)\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$
regex.icontainsregex\s*DocuSign Contract Under Review\s*
regex.icontainsregexDOCUMENT PREVIEW
regex.icontainsregexPREVIEW DOCUMENT
9 more
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
      any(file.explode(attachments))
        and
          or
            and
              distinct(filter(file.explode(attachments[])[].scan.url.urls, not strings.istarts_with(file.explode(attachments[])[].url, 'mailto:') and not strings.istarts_with(file.explode(attachments[])[].url, 'email:') and not any([attachments[].scan.exiftool.producer, attachments[].scan.exiftool.creator], file.explode(attachments[])[] is not null and strings.icontains(file.explode(attachments[])[], attachments[].domain.domain)) and not file.explode(attachments[])[].domain.root_domain in ('pdf-tools.com') and not file.explode(attachments[])[].url in ('https://gamma.app/?utm_source=made-with-gamma')), file.explode(attachments[])[].domain.domain) length_compare "1"
               macro "all(distinct(...))"
            filter(file.explode(attachments[])[].scan.url.urls, not strings.istarts_with(file.explode(attachments[])[].url, 'mailto:') and not strings.istarts_with(file.explode(attachments[])[].url, 'email:') and not any([attachments[].scan.exiftool.producer, attachments[].scan.exiftool.creator], file.explode(attachments[])[] is not null and strings.icontains(file.explode(attachments[])[], attachments[].domain.domain)) and not file.explode(attachments[])[].domain.root_domain in ('pdf-tools.com') and not file.explode(attachments[])[].url in ('https://gamma.app/?utm_source=made-with-gamma')) length_compare "1"
          file.explode(attachments[])[].depth eq "0"
      any(file.explode(attachments))
        or
          and
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings regex_match "^\\s*(?:View Video)\\s*$"
            file.explode(attachments[])[].scan.strings.strings contains "Error"
          any(file.explode(attachments).scan.strings.strings)
            or
              file.explode(attachments[])[].scan.strings.strings[] regex_match "(?:check your personal|view your) forecast"
              file.explode(attachments[])[].scan.strings.strings[] regex_match ".*sent you a \\S+ to review(?:\\s*(?:and|&)\\s*sign)$"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "DOCUMENT PREVIEW"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "It seems there was an issue opening the document. Please view it online."
              file.explode(attachments[])[].scan.strings.strings[] regex_match "Learn more about messages protected by Microsoft"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "PREVIEW DOCUMENT"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "This document is protected by 256-bit encryption."
              file.explode(attachments[])[].scan.strings.strings[] regex_match "UN1TED STATES"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "Update Adobe Viewer"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "VIEW REMITTANCE COPY HERE"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "View Secure Fax"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "\\s*DocuSign Contract Under Review\\s*"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "^You received a \\S+ to review and sign$"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "^\\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)\\s*$"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "full new state pension"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "shared a file with you"
              file.explode(attachments[])[].scan.strings.strings[] regex_match "view secure documents"
          and
            file.explode(attachments[])[].scan.strings.strings contains "Some additional information here"
            file.explode(attachments[])[].scan.strings.strings length_compare "1"
      attachments.file_type eq "pdf"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).page_count == 1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where all hold:
      • .depth is 0
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      and
        any(file.explode(filter(attachments)).scan.yara.matches)
          file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_b64_js_var_eval"
        file.explode(filter(attachments)[])[].depth eq "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_lure_image_blurry"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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) is 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 of file.explode(.) where all hold:
      • any of ml.nlu_classifier(.scan.strings.raw).intents where all hold:
        • .name is 'cred_theft'
        • .confidence is 'high'
      • strings.icontains(.scan.strings.raw)
  6. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass)

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
      any(file.explode(attachments))
        and
          any(ml.nlu_classifier(file.explode(attachments).scan.strings.raw).intents)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.strings.raw).intents[].confidence eq "high"
              ml.nlu_classifier(file.explode(attachments[])[].scan.strings.raw).intents[].name eq "cred_theft"
          strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.strings.raw)"
      attachments.file_type eq "pdf"
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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.

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 of ml.nlu_classifier(body.current_thread.text).intents where all hold:
    • .name is 'cred_theft'
    • .confidence in ('medium', 'high')
  3. any of attachments where all hold:
    • .file_extension is 'pdf'
    • any of file.explode(.) where all hold:
      • any of .scan.pdf.urls where all hold:
        • .domain.root_domain in $free_subdomain_hosts
        • .domain.subdomain is set
        • .domain.subdomain is not 'www'
      • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
        • .name is 'cred_theft'
        • .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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.pdf.urls)
            and
              file.explode(attachments[])[].scan.pdf.urls[].domain.subdomain is_not_null
              file.explode(attachments[])[].scan.pdf.urls[].domain.subdomain ne "www"
               macro "file.explode(attachments[])[].scan.pdf.urls[].domain.root_domain in free_subdomain_hosts"
          any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence in ["high", "medium"]
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name eq "cred_theft"
      attachments.file_extension eq "pdf"
  any(ml.nlu_classifier(body.current_thread.text).intents)
    and
      ml.nlu_classifier(body.current_thread.text).intents.confidence in ["high", "medium"]
      ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
  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
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 of filter(attachments) where:
    • any of file.explode(.) where all hold:
      • .depth is 0
      • any of .scan.yara.matches where:
        • .name is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      and
        any(file.explode(filter(attachments)).scan.yara.matches)
          file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_cve_2026_34621_observed_lures"
        file.explode(filter(attachments)[])[].depth eq "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_eCheckLure_format"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_fake_invoice_image_font_sizes"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where all hold:
      • .depth is 0
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      and
        any(file.explode(filter(attachments)).scan.yara.matches)
          file.explode(filter(attachments)).scan.yara.matches.name in ["pdf_jsfck_ratio", "pdf_jsfck_strings"]
        file.explode(filter(attachments)[])[].depth eq "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: PDF with link to DMG file download

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

This rule identifies PDF attachments that either link directly to a DMG file, link to a ZIP archive containing a DMG file, or link to an encrypted ZIP containing a DMG file. This technique has been observed delivering MetaStealer Malware.

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_type == "pdf"
        and any(file.explode(.),
                any(.scan.url.urls,

                    // url links to dmg or zip
                    (
                      strings.iends_with(.url, ".dmg")
                      or strings.iends_with(.url, "zip")
                    )

                    // and downloads a dmg or a zip
                    and any(ml.link_analysis(.).files_downloaded,
                            (
                              .file_extension == "dmg"
                              or (
                                .file_extension in~ $file_extensions_common_archives

                                // and the zip contains a dmg file
                                and any(file.explode(.),
                                        (.file_extension =~ "dmg")

                                        // exif inspection if encrypted
                                        or strings.ends_with(.scan.exiftool.zip_file_name,
                                                             ".dmg"
                                        )
                                )
                              )
                            )
                    )
                )
        )
)
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.

This rule identifies PDF attachments that either link directly to a DMG file, link to a ZIP archive containing a DMG file, or link to an encrypted ZIP containing a DMG file. This technique has been observed delivering MetaStealer Malware.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • any of file.explode(.) where:
      • any of .scan.url.urls where all hold:
        • any of:
          • .url ends with '.dmg'
          • .url ends with 'zip'
        • any of ml.link_analysis(.).files_downloaded where any holds:
          • .file_extension is 'dmg'
          • all of:
            • .file_extension in $file_extensions_common_archives
            • any of file.explode(.) where any holds:
              • .file_extension is 'dmg'
              • .scan.exiftool.zip_file_name ends with '.dmg'
  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_type, type.inbound. Sensors: file.explode, ml.link_analysis, profile.by_sender, strings.ends_with, strings.iends_with. Reference lists: $file_extensions_common_archives.

Indicators matched (6)

FieldMatchValue
attachments[].file_typeequalspdf
strings.iends_withsuffix.dmg
strings.iends_withsuffixzip
ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[].file_extensionequalsdmg
file.explode(ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[])[].file_extensionequalsdmg
strings.ends_withsuffix.dmg

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          and
            any(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded)
              or
                and
                  any(file.explode(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded))
                    or
                      file.explode(ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[])[].file_extension eq "dmg"
                      file.explode(ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[])[].scan.exiftool.zip_file_name ends_with ".dmg"
                   macro "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[].file_extension in file_extensions_common_archives"
                ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[].file_extension eq "dmg"
            or
              file.explode(attachments[])[].scan.url.urls[].url ends_with ".dmg"
              file.explode(attachments[])[].scan.url.urls[].url ends_with "zip"
      attachments.file_type eq "pdf"
  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
field:"type.inbound" kind:eq value:"true"

Attachment: PDF with link to zip containing a wsf file

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

Detects a PDF attachment with a link to a ZIP file that contains a WSF file

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_type == "pdf"
        and any(file.explode(.),
                any(.scan.url.urls,
                    strings.icontains(.url, "zip")
                    and any(ml.link_analysis(.).files_downloaded,
                            any(file.explode(.), .file_extension == "wsf")
                    )
                )
                or any(.scan.url.urls,
                       strings.icontains(.url, "php")
                       and any(ml.link_analysis(.).files_downloaded,
                               any(file.explode(.),
                                   .file_extension == "zip"
                                   and any(.scan.zip.attempted_files,
                                           strings.icontains(., "wsf")
                                   )
                               )
                       )
                )
        )
)

Detection logic

Scope: inbound message.

Detects a PDF attachment with a link to a ZIP file that contains a WSF file

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • any of file.explode(.) where any holds:
      • any of .scan.url.urls where all hold:
        • .url contains 'zip'
        • any of ml.link_analysis(.).files_downloaded where:
          • any of file.explode(.) where:
            • .file_extension is 'wsf'
      • any of .scan.url.urls where all hold:
        • .url contains 'php'
        • any of ml.link_analysis(.).files_downloaded where:
          • any of file.explode(.) where all hold:
            • .file_extension is 'zip'
            • any of .scan.zip.attempted_files where:
              • . contains 'wsf'

Inspects: attachments[].file_type, type.inbound. Sensors: file.explode, ml.link_analysis, strings.icontains.

Indicators matched (6)

FieldMatchValue
attachments[].file_typeequalspdf
strings.icontainssubstringzip
file.explode(ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[])[].file_extensionequalswsf
strings.icontainssubstringphp
file.explode(ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[])[].file_extensionequalszip
strings.icontainssubstringwsf

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        or
          any(file.explode(attachments).scan.url.urls)
            and
              any(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded)
                any(file.explode(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded))
                  and
                    any(file.explode(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded).scan.zip.attempted_files)
                      file.explode(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded).scan.zip.attempted_files contains "wsf"
                    file.explode(ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).files_downloaded[])[].file_extension eq "zip"
              file.explode(attachments[])[].scan.url.urls[].url contains "php"
          any(file.explode(attachments).scan.url.urls)
            and
              any(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded)
                any(file.explode(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded))
                  file.explode(ml.link_analysis(file.explode(attachments).scan.url.urls).files_downloaded).file_extension eq "wsf"
              file.explode(attachments[])[].scan.url.urls[].url contains "zip"
      attachments.file_type eq "pdf"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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) is 1
  3. any of:
    • sender.email.email is recipients.to[0].email.email
    • recipients.to[0].email.domain.valid is False
  4. any of filter(attachments) where:
    • beta.parse_exif(.).title starts with '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
  any(filter(attachments))
    beta.parse_exif(filter(attachments)[]).title starts_with "127.0.0.1"
  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"

Indicators

These rows show field, operator, and value matches.

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 of filter(attachments) where all hold:
    • any of ml.nlu_classifier(beta.ocr(.).text).topics where all hold:
      • .name is 'Secure Message'
      • .confidence is 'high'
    • beta.ocr(.).text contains '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
  any(filter(attachments))
    and
      any(ml.nlu_classifier(beta.ocr(filter(attachments)).text).topics)
        and
          ml.nlu_classifier(beta.ocr(filter(attachments)[]).text).topics[].confidence eq "high"
          ml.nlu_classifier(beta.ocr(filter(attachments)[]).text).topics[].name eq "Secure Message"
      beta.ocr(filter(attachments)[]).text contains "Microsoft Purview Message"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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) is 1
  3. any of attachments where all hold:
    • .file_type is 'pdf'
    • any of file.explode(.) where all hold:
      • .depth is 0
      • length(.scan.url.urls) is 1
      • any of .scan.url.urls where all hold:
        • .domain.domain is 'doc.clickup.com'
        • any of:
          • ml.link_analysis(.).final_dom.display_text starts with 'This page is currently unavailable'
          • any of filter(...) where any holds:
            • network.whois(.href_url.domain).days_old < 30
            • .href_url.domain.root_domain in $free_file_hosts
            • .href_url.domain.domain in $free_file_hosts
            • all of:
              • .href_url.domain.root_domain in $free_subdomain_hosts
              • .href_url.domain.subdomain is set
              • .href_url.domain.subdomain is not 'www'
            • .href_url.domain.root_domain in $url_shorteners
            • .href_url.domain.root_domain in $social_landing_hosts
            • .href_url.domain.domain in $url_shorteners
            • .href_url.domain.domain in $social_landing_hosts
            • all of:
              • .display_text matches '(?:view|click|show|access|download|goto|Validate|Va[il]idar|login|verify|account)'
              • any of:
                • ml.link_analysis(.).credphish.disposition is 'phishing'
                • ml.link_analysis(.).credphish.contains_captcha
                • all of:
                  • length(ml.link_analysis(., mode='aggressive').redirect_history) > 0
                  • ml.link_analysis(.).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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.url.urls)
            and
              or
                any(filter(...))
                  or
                    and
                      or
                        and
                          ml.link_analysis func_call "ml.link_analysis(filter(...)[]).effective_url.domain.root_domain in tranco_10k"
                          ml.link_analysis(filter(...)[], mode='aggressive').redirect_history length_compare "0"
                        ml.link_analysis func_call "ml.link_analysis(filter(...)[]).credphish.contains_captcha"
                        ml.link_analysis func_call "ml.link_analysis(filter(...)[]).credphish.disposition == phishing"
                      filter(...).display_text regex_match "(?:view|click|show|access|download|goto|Validate|Va[il]idar|login|verify|account)"
                    and
                      filter(...).href_url.domain.subdomain is_not_null
                      filter(...).href_url.domain.subdomain ne "www"
                       macro "filter(...)[].href_url.domain.root_domain in free_subdomain_hosts"
                    network.whois func_call "network.whois(filter(...)[].href_url.domain).days_old < 30"
                     macro "filter(...)[].href_url.domain.domain in free_file_hosts"
                     macro "filter(...)[].href_url.domain.domain in social_landing_hosts"
                     macro "filter(...)[].href_url.domain.domain in url_shorteners"
                     macro "filter(...)[].href_url.domain.root_domain in free_file_hosts"
                     macro "filter(...)[].href_url.domain.root_domain in social_landing_hosts"
                     macro "filter(...)[].href_url.domain.root_domain in url_shorteners"
                ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).final_dom.display_text starts_with "This page is currently unavailable"
              file.explode(attachments[])[].scan.url.urls[].domain.domain eq "doc.clickup.com"
          file.explode(attachments[])[].depth eq "0"
          file.explode(attachments[])[].scan.url.urls length_compare "1"
      attachments.file_type eq "pdf"
  attachments length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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')) is 1
  3. any of regex.extract(body.current_thread.text) where:
    • any of filter(attachments) where:
      • strings.contains(.file_name)

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
  any(regex.extract(body.current_thread.text))
    any(filter(attachments))
      strings.contains func_call "strings.contains(filter(attachments)[].file_name)"
  filter(attachments, .file_type == 'pdf') length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.url.urls where any holds:
        • strings.icontains(.path)
        • .path contains '/: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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          or
            file.explode(attachments[])[].scan.url.urls[].path contains "/:o:/g/personal/"
            strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.url.urls[].path)"
      attachments.file_type eq "pdf"
  filter(attachments, .file_type == 'pdf') length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where all hold:
    • any of filter(...) where:
      • any of ml.nlu_classifier(.scan.strings.raw).intents where:
        • .name is 'cred_theft'
    • length(beta.scan_qr(.).items) > 0
    • any of beta.scan_qr(.).items where all hold:
      • .url.domain.valid
      • any of recipients.to where all hold:
        • .email.domain.valid
        • any of:
          • strings.icontains(.url.url)
          • any of strings.scan_base64(.url.url) where:
            • strings.icontains(.)

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
  any(filter(attachments))
    and
      any(beta.scan_qr(filter(attachments)).items)
        and
          any(recipients.to)
            and
              or
                any(strings.scan_base64(beta.scan_qr(filter(attachments)).items.url.url))
                  strings.icontains func_call "strings.icontains(strings.scan_base64(beta.scan_qr(filter(attachments)[]).items[].url.url)[])"
                strings.icontains func_call "strings.icontains(beta.scan_qr(filter(attachments)[]).items[].url.url)"
              recipients.to.email.domain.valid eq "true"
          beta.scan_qr(filter(attachments)[]).items[].url.domain.valid eq "true"
      any(filter(...))
        any(ml.nlu_classifier(filter(...).scan.strings.raw).intents)
          ml.nlu_classifier(filter(...).scan.strings.raw).intents.name eq "cred_theft"
      beta.scan_qr(filter(attachments)[]).items length_compare "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_quote_lure_01"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: PDF with recipient email in link

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

Detects PDF attachments that contain the recipient's domain in the filename and include a link personalized with the recipient's email address, either in the URL directly, encoded in base64, or within a QR code.

Threat classification

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

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

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • recipients
  • recipients.to
  • type

Rule body

type.inbound
// one or more PDF documents
and length(filter(attachments, .file_type == "pdf")) >= 1
and length(attachments) <= 4
// a single recipient (this is in the link so there can be only one)
and length(recipients.to) == 1
and all(recipients.to, .email.domain.valid)
and any(filter(attachments, .file_type == "pdf"),
        (
          // the urls in the PDF
          any(filter(file.explode(.), .depth == 0),
              // remove links we are not interested in
              any(filter(.scan.pdf.urls,
                         // remove mailto: links
                         not strings.istarts_with(.url, 'mailto:')
                         and not strings.istarts_with(.url, 'email:')
                         // remove links found in exiftool output
                         and not (
                           ..scan.exiftool.producer is not null
                           and strings.icontains(..scan.exiftool.producer,
                                                 .domain.domain
                           )
                         )

                         // remove links found in exiftool output
                         and not (
                           ..scan.exiftool.creator is not null
                           and strings.icontains(..scan.exiftool.creator,
                                                 .domain.domain
                           )
                         )
                         // legitimate domains that exhibits this behavior
                         and .domain.root_domain not in (
                           "univarsolutions.com",
                           "westpac.com.au",
                           "safeshiphub.com",
                           "sharepoint.com"
                         )
                  ),
                  // it contains the email address of the recipient
                  any(recipients.to,
                      .email.domain.valid
                      and (
                        strings.icontains(..url, .email.email)
                        // or the base64 encoded email
                        or any(beta.scan_base64(..url,
                                                format="url",
                                                ignore_padding=true
                               ),
                               strings.icontains(., ..email.email)
                        )
                      )
                  )
              )
          )
          // or there is a QR code
          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
            //
            any(beta.scan_qr(.).items,
                .url.domain.valid
                and any(recipients.to,
                        // QR code contains the email
                        (
                          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 that contain the recipient's domain in the filename and include a link personalized with the recipient's email address, either in the URL directly, encoded in base64, or within a QR code.

  1. inbound message
  2. length(filter(attachments, .file_type == 'pdf')) ≥ 1
  3. length(attachments) ≤ 4
  4. length(recipients.to) is 1
  5. all of recipients.to where:
    • .email.domain.valid
  6. any of filter(attachments) where any holds:
    • any of filter(...) where:
      • any of filter(.scan.pdf.urls) where:
        • any of recipients.to where all hold:
          • .email.domain.valid
          • any of:
            • strings.icontains(.url)
            • any of beta.scan_base64(.url) where:
              • strings.icontains(.)
    • any of beta.scan_qr(.).items where all hold:
      • .url.domain.valid
      • any of recipients.to where any holds:
        • strings.icontains(.url.url)
        • any of strings.scan_base64(.url.url) where:
          • strings.icontains(.)

Inspects: attachments[].file_type, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: beta.scan_base64, beta.scan_qr, file.explode, strings.icontains, strings.istarts_with, strings.scan_base64.

Indicators matched (1)

FieldMatchValue
attachments[].file_typeequalspdf

Stages and Predicates

Stage 1: mql_rule

and
  any(filter(attachments))
    or
      any(filter(...))
        any(filter(filter(...).scan.pdf.urls))
          any(recipients.to)
            and
              or
                any(beta.scan_base64(filter(filter(...).scan.pdf.urls).url))
                  strings.icontains func_call "strings.icontains(beta.scan_base64(filter(filter(...)[].scan.pdf.urls)[].url)[])"
                strings.icontains func_call "strings.icontains(filter(filter(...)[].scan.pdf.urls)[].url)"
              recipients.to.email.domain.valid eq "true"
      any(beta.scan_qr(filter(attachments)).items)
        and
          any(recipients.to)
            or
              any(strings.scan_base64(beta.scan_qr(filter(attachments)).items.url.url))
                strings.icontains func_call "strings.icontains(strings.scan_base64(beta.scan_qr(filter(attachments)[]).items[].url.url)[])"
              strings.icontains func_call "strings.icontains(beta.scan_qr(filter(attachments)[]).items[].url.url)"
          beta.scan_qr(filter(attachments)[]).items[].url.domain.valid eq "true"
  attachments length_compare "4"
  filter(attachments, .file_type == 'pdf') length_compare "1"
  recipients.to length_compare "1"
  type.inbound eq "true"
   macro "all(recipients.to)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 is 'ReportLab PDF Library - (opensource)'
    • beta.parse_exif(.).title is 'untitled'
    • beta.parse_exif(.).creator is 'anonymous'
    • any of beta.parse_exif(.).fields where all hold:
      • .key is 'Subject'
      • .value is 'unspecified'
    • beta.parse_exif(.).author is '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
      any(beta.parse_exif(attachments).fields)
        and
          beta.parse_exif(attachments[]).fields[].key eq "Subject"
          beta.parse_exif(attachments[]).fields[].value eq "unspecified"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).author == anonymous"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).creator == anonymous"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).producer == ReportLab PDF Library - (opensource)"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).title == untitled"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name in ["pdf_prompt_ack_secure_document_image_sizes", "pdf_prompt_ack_secure_document_link"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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)]) is 1
  3. any of:
    • sender.email.email is recipients.to[0].email.email
    • recipients.to[0].email.domain.valid is False
  4. length(attachments) is 1
  5. beta.parse_exif(attachments[0]).page_count is 1
  6. any of filter(attachments) where:
    • any of filter(...) where all hold:
      • all of:
        • length(filter(.scan.url.urls, not strings.istarts_with(.url, 'mailto:') and not strings.istarts_with(.url, 'email:') 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
        • length(filter(.scan.url.urls, not strings.istarts_with(.url, 'mailto:') and not strings.istarts_with(.url, 'email:') 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
      • all of .scan.url.urls where any holds:
        • .domain.root_domain in $self_service_creation_platform_domains
        • .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
  any(filter(attachments))
    any(filter(...))
      and
        filter(filter(...)[].scan.url.urls, not strings.istarts_with(filter(...)[].url, 'mailto:') and not strings.istarts_with(filter(...)[].url, 'email:') and not any([filter(attachments)[].scan.exiftool.producer, filter(attachments)[].scan.exiftool.creator], filter(...)[] is not null and strings.icontains(filter(...)[], filter(attachments)[].domain.domain)) and not filter(...)[].domain.root_domain in ('pdf-tools.com') and not filter(...)[].url in ('https://gamma.app/?utm_source=made-with-gamma')) length_compare "1"
        filter(filter(...)[].scan.url.urls, not strings.istarts_with(filter(...)[].url, 'mailto:') and not strings.istarts_with(filter(...)[].url, 'email:') and not any([filter(attachments)[].scan.exiftool.producer, filter(attachments)[].scan.exiftool.creator], filter(...)[] is not null and strings.icontains(filter(...)[], filter(attachments)[].domain.domain)) and not filter(...)[].domain.root_domain in ('pdf-tools.com') and not filter(...)[].url in ('https://gamma.app/?utm_source=made-with-gamma')) length_compare "3"
         macro "all(filter(...)[].scan.url.urls)"
  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"

Indicators

These rows show field, operator, and value matches.

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 of filter(attachments) where any holds:
    • beta.parse_exif(.).author is 'Shelby Porter'
    • beta.parse_exif(.).creator is '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
  any(filter(attachments))
    or
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).author == Shelby Porter"
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).creator == Shelby Porter"
  filter(attachments, .file_type == 'pdf') length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_w9_signature_c003"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name starts with '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name starts_with "Phishing_PDF_Split_QR_Code_Pair"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "pdf_view_doc_here_title_box"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 == "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 of filter(attachments) where all hold:
    • beta.parse_exif(.).creator contains 'HeadlessChrome'
    • beta.parse_exif(.).page_count is 1
    • all of:
      • any of:
        • beta.parse_exif(.).title matches '^[a-f0-9]{32}\\.html$'
        • all of:
          • beta.parse_exif(.).title is 'about:blank'
          • beta.parse_exif(.).producer starts with 'Skia/PDF'
          • beta.parse_exif(.).creator contains 'Windows'
        • all of:
          • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
            • .name is 'cred_theft'
            • .confidence is not 'low'
          • beta.parse_exif(.).producer starts with 'Skia/PDF'
          • beta.parse_exif(.).creator contains 'Windows'
      • not:
        • beta.parse_exif(.).producer contains '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)

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 (6)

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[].nameequalscred_theft

Stages and Predicates

Stage 1: mql_rule

and
  any(filter(attachments))
    and
      or
        and
          any(ml.nlu_classifier(body.current_thread.text).intents)
            and
              ml.nlu_classifier(body.current_thread.text).intents.confidence ne "low"
              ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
          beta.parse_exif(filter(attachments)[]).creator contains "Windows"
          beta.parse_exif(filter(attachments)[]).producer starts_with "Skia/PDF"
        and
          beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).title == about:blank"
          beta.parse_exif(filter(attachments)[]).creator contains "Windows"
          beta.parse_exif(filter(attachments)[]).producer starts_with "Skia/PDF"
        beta.parse_exif(filter(attachments)[]).title regex_match "^[a-f0-9]{32}\\.html$"
      not
        beta.parse_exif(filter(attachments)[]).producer contains "Google Docs"
      beta.parse_exif func_call "beta.parse_exif(filter(attachments)[]).page_count == 1"
      beta.parse_exif(filter(attachments)[]).creator contains "HeadlessChrome"
  not
    and
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
      sender.email.domain.root_domain in ["aglgroup.com", "gominis.com", "guardtek.net", "truckerzoom.com"]
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
sender.email.domain.root_domaininaglgroup.com, gominis.com, guardtek.net, truckerzoom.comexcludes:sender.email.domain.root_domain

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where:
    • any of file.explode(.) where all hold:
      • .depth is 0
      • any of .scan.strings.strings where:
        • . 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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      and
        any(file.explode(filter(attachments)).scan.strings.strings)
          file.explode(filter(attachments)).scan.strings.strings contains "[<C57237C22450666518136DE404118E5E>"
        file.explode(filter(attachments)[])[].depth eq "0"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: PDF with suspicious language and redirect to suspicious file type

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

Attached PDF contains credential theft language, and links to an open redirect to a suspicious file type. This has been observed in-the-wild as a Qakbot technique.

Threat classification

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

CategoryValues
Attack typesMalware/Ransomware, Credential Phishing
Tactics and techniquesEvasion, 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(.),
                length(.scan.url.urls) > 0
                and any(ml.nlu_classifier(.scan.ocr.raw).intents,
                        .name == "cred_theft"
                        and .confidence in~ ("medium", "high")
                )
                and any(.scan.url.urls,
                        strings.icontains(ml.link_analysis(.).final_dom.display_text,
                                          "Redirect Notice"
                        )
                        and (
                          strings.contains(ml.link_analysis(.).final_dom.display_text,
                                           ".zip"
                          )
                          or strings.contains(ml.link_analysis(.).final_dom.display_text,
                                              ".php"
                          )
                        )
                )
        )
)

Detection logic

Scope: inbound message.

Attached PDF contains credential theft language, and links to an open redirect to a suspicious file type. This has been observed in-the-wild as a Qakbot technique.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • any of file.explode(.) where all hold:
      • length(.scan.url.urls) > 0
      • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
        • .name is 'cred_theft'
        • .confidence in ('medium', 'high')
      • any of .scan.url.urls where all hold:
        • ml.link_analysis(.).final_dom.display_text contains 'Redirect Notice'
        • any of:
          • ml.link_analysis(.).final_dom.display_text contains '.zip'
          • ml.link_analysis(.).final_dom.display_text contains '.php'

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

Indicators matched (7)

FieldMatchValue
attachments[].file_typeequalspdf
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
strings.icontainssubstringRedirect Notice
strings.containssubstring.zip
strings.containssubstring.php

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.url.urls)
            and
              or
                ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).final_dom.display_text contains ".php"
                ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).final_dom.display_text contains ".zip"
              ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).final_dom.display_text contains "Redirect Notice"
          any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
            and
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidence in ["high", "medium"]
              ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].name eq "cred_theft"
          file.explode(attachments[])[].scan.url.urls length_compare "0"
      attachments.file_type eq "pdf"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: PDF with suspicious link and action-oriented language

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

Detects PDF attachments containing a single link that leads to pages with language prompting users to view, review, or read documents, accounts, or business-related content such as bids, proposals, agreements, or contracts.

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 length(filter(attachments, .file_type == "pdf")) >= 1
and any(attachments,
        .file_type == "pdf"
        and beta.parse_exif(.).page_count == 1
        and any(file.explode(.),
                .depth == 0
                // reduce fps by limiting the length to a single link
                and length(.scan.url.urls) == 1
                and any(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
                               and not (
                                 ..scan.exiftool.producer is not null
                                 and strings.icontains(..scan.exiftool.producer,
                                                       .domain.domain
                                 )
                               )

                               // remove links found in exiftool output
                               and not (
                                 ..scan.exiftool.creator is not null
                                 and strings.icontains(..scan.exiftool.creator,
                                                       .domain.domain
                                 )
                               )
                               and not .domain.root_domain in ('pdf-tools.com')
                        ),
                        (
                          200 <= ml.link_analysis(.).status_code < 300
                          and length(ml.link_analysis(.).final_dom.links) < 100
                          and any(ml.link_analysis(.).final_dom.links,
                                  .href_url.domain.root_domain != ..domain.root_domain
                                  and regex.icontains(.display_text,
                                                      '\b(?:(?:re)?view|see|read|click\s+(?:here\s+)?to)[\t\x20]*(?:\S+[\t\x20]*){0,3}[\t\x20]*(?:document|message|now|proceed)',
                                                      '\b(?:request|review)\b.{1,5}\b(?:bid|proposal|agreement|portfolio|contract|settlement|invoice)\b',
                                  )
                          )
                        )
                        or (
                          200 <= ml.link_analysis(.).status_code < 300
                          and length(ml.link_analysis(.).final_dom.display_text) < 1050
                          and regex.icontains(ml.link_analysis(.).final_dom.display_text,
                                              '\b(?:(?:re)?view|see|read|click\s+(?:here\s+)?to)[\t\x20]*(?:\S+[\t\x20]*){0,3}[\t\x20]*(?:document|message|now|proceed)',
                                              '\b(?:request|review)\b.{1,5}\b(?:bid|proposal|agreement|portfolio|contract|settlement|invoice)\b'
                          )
                          // a common fp in the .au for a payment system
                          and not strings.icontains(ml.link_analysis(.).final_dom.display_text,
                                                    'View Podium Message'
                          )
                        )
                        // the title contains high confidence indicators
                        or any(html.xpath(ml.link_analysis(.).final_dom,
                                          '//title'
                               ).nodes,
                               strings.icontains(.raw, 'Secure Document')
                        )
                )
        )
)

Detection logic

Scope: inbound message.

Detects PDF attachments containing a single link that leads to pages with language prompting users to view, review, or read documents, accounts, or business-related content such as bids, proposals, agreements, or contracts.

  1. inbound message
  2. length(filter(attachments, .file_type == 'pdf')) ≥ 1
  3. any of attachments where all hold:
    • .file_type is 'pdf'
    • beta.parse_exif(.).page_count is 1
    • any of file.explode(.) where all hold:
      • .depth is 0
      • length(.scan.url.urls) is 1
      • any of filter(.scan.url.urls) where any holds:
        • all of:
          • all of:
            • ml.link_analysis(.).status_code ≥ 200
            • ml.link_analysis(.).status_code < 300
          • length(ml.link_analysis(.).final_dom.links) < 100
          • any of ml.link_analysis(.).final_dom.links where all hold:
            • .href_url.domain.root_domain is not .domain.root_domain
            • .display_text matches any of 2 patterns
              • \b(?:(?:re)?view|see|read|click\s+(?:here\s+)?to)[\t\x20]*(?:\S+[\t\x20]*){0,3}[\t\x20]*(?:document|message|now|proceed)
              • \b(?:request|review)\b.{1,5}\b(?:bid|proposal|agreement|portfolio|contract|settlement|invoice)\b
        • all of:
          • all of:
            • ml.link_analysis(.).status_code ≥ 200
            • ml.link_analysis(.).status_code < 300
          • length(ml.link_analysis(.).final_dom.display_text) < 1050
          • ml.link_analysis(.).final_dom.display_text matches any of 2 patterns
            • \b(?:(?:re)?view|see|read|click\s+(?:here\s+)?to)[\t\x20]*(?:\S+[\t\x20]*){0,3}[\t\x20]*(?:document|message|now|proceed)
            • \b(?:request|review)\b.{1,5}\b(?:bid|proposal|agreement|portfolio|contract|settlement|invoice)\b
          • not:
            • ml.link_analysis(.).final_dom.display_text contains 'View Podium Message'
        • any of html.xpath(ml.link_analysis(.).final_dom, '//title').nodes where:
          • .raw contains 'Secure Document'

Inspects: attachments[].file_type, type.inbound. Sensors: beta.parse_exif, file.explode, html.xpath, ml.link_analysis, regex.icontains, strings.icontains, strings.istarts_with.

Indicators matched (4)

FieldMatchValue
attachments[].file_typeequalspdf
regex.icontainsregex\b(?:(?:re)?view|see|read|click\s+(?:here\s+)?to)[\t\x20]*(?:\S+[\t\x20]*){0,3}[\t\x20]*(?:document|message|now|proceed)
regex.icontainsregex\b(?:request|review)\b.{1,5}\b(?:bid|proposal|agreement|portfolio|contract|settlement|invoice)\b
strings.icontainssubstringSecure Document

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        and
          any(filter(file.explode(attachments).scan.url.urls))
            or
              and
                any(ml.link_analysis(filter(file.explode(attachments).scan.url.urls)).final_dom.links)
                  and
                    or
                      ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.links[].display_text regex_match "\\b(?:(?:re)?view|see|read|click\\s+(?:here\\s+)?to)[\\t\\x20]*(?:\\S+[\\t\\x20]*){0,3}[\\t\\x20]*(?:document|message|now|proceed)"
                      ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.links[].display_text regex_match "\\b(?:request|review)\\b.{1,5}\\b(?:bid|proposal|agreement|portfolio|contract|settlement|invoice)\\b"
                    ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.links[].href_url.domain.root_domain cross_field_compare "filter(file.explode(attachments[])[].scan.url.urls)[].domain.root_domain"
                ml.link_analysis func_call "ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).status_code < 300"
                ml.link_analysis func_call "ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).status_code >= 200"
                ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.links length_compare "100"
              and
                not
                  ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.display_text contains "View Podium Message"
                or
                  ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.display_text regex_match "\\b(?:(?:re)?view|see|read|click\\s+(?:here\\s+)?to)[\\t\\x20]*(?:\\S+[\\t\\x20]*){0,3}[\\t\\x20]*(?:document|message|now|proceed)"
                  ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.display_text regex_match "\\b(?:request|review)\\b.{1,5}\\b(?:bid|proposal|agreement|portfolio|contract|settlement|invoice)\\b"
                ml.link_analysis func_call "ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).status_code < 300"
                ml.link_analysis func_call "ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).status_code >= 200"
                ml.link_analysis(filter(file.explode(attachments[])[].scan.url.urls)[]).final_dom.display_text length_compare "1050"
              any(html.xpath(ml.link_analysis(filter(file.explode(attachments).scan.url.urls)).final_dom, '//title').nodes)
                html.xpath(ml.link_analysis(filter(file.explode(attachments).scan.url.urls)).final_dom, '//title').nodes.raw contains "Secure Document"
          file.explode(attachments[])[].depth eq "0"
          file.explode(attachments[])[].scan.url.urls length_compare "1"
      attachments.file_type eq "pdf"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).page_count == 1"
  filter(attachments, .file_type == 'pdf') length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is '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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name eq "view_document_pdf_characteristics"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.yara.matches)
        file.explode(filter(attachments)).scan.yara.matches.name in ["w9_c001_signatures", "w9_c001_structure"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • at least 1 of:
        • any of .scan.strings.strings where:
          • . matches '*Win32_Processor*'
        • any of .scan.strings.strings where:
          • . matches '*Win32_LogicalDisk*'
        • any of .scan.strings.strings where:
          • . matches '*Win32_ComputerSystem*'
        • any of .scan.strings.strings where:
          • . matches '*Win32_Process*'
        • any of .scan.strings.strings where:
          • . matches '*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
      any(file.explode(attachments))
        or
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "LDAP://RootDSE"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "Win32_ComputerSystem"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "Win32_LogicalDisk"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "Win32_Process"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "Win32_Processor"
      or
        and
          attachments.content_type eq "application/octet-stream"
          attachments.file_extension is_null
          attachments.file_type eq "unknown"
          attachments.size lt "100000000"
         macro "attachments[].file_extension in file_extensions_macros"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: PowerPoint with suspicious hyperlink

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

Attached PowerPoint contains a suspicious hyperlink that can execute arbitrary 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 in~ ("ppt", "pptx"))
        and any(file.explode(.),
                any(.scan.exiftool.fields,
                    .key == "Hyperlinks"
                    and (
                      4 of (
                        strings.ilike(.value, "*[Convert]::ToChar*"),
                        strings.ilike(.value, "*vbs*"),
                        strings.ilike(.value, "*[IO.File]::Create*"),
                        strings.ilike(.value, "*[IO.File]::Exists*"),
                        strings.ilike(.value,
                                      "*[io.FileOPtions]::DeleteOnClose*"
                        ),
                        strings.ilike(.value, "*Net.WebClient*"),
                        strings.ilike(.value, "*dll*"),
                      )
                    )
                )
        )
)

Detection logic

Scope: inbound message.

Attached PowerPoint contains a suspicious hyperlink that can execute arbitrary code.

  1. inbound message
  2. any of attachments where all hold:
    • .file_extension in ('ppt', 'pptx')
    • any of file.explode(.) where:
      • any of .scan.exiftool.fields where all hold:
        • .key is 'Hyperlinks'
        • at least 4 of 7: .value matches any of 7 patterns
          • *[Convert]::ToChar*
          • *vbs*
          • *[IO.File]::Create*
          • *[IO.File]::Exists*
          • *[io.FileOPtions]::DeleteOnClose*
          • *Net.WebClient*
          • *dll*

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

Indicators matched (10)

FieldMatchValue
attachments[].file_extensionmemberppt
attachments[].file_extensionmemberpptx
file.explode(attachments[])[].scan.exiftool.fields[].keyequalsHyperlinks
strings.ilikesubstring*[Convert]::ToChar*
strings.ilikesubstring*vbs*
strings.ilikesubstring*[IO.File]::Create*
strings.ilikesubstring*[IO.File]::Exists*
strings.ilikesubstring*[io.FileOPtions]::DeleteOnClose*
strings.ilikesubstring*Net.WebClient*
strings.ilikesubstring*dll*

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.exiftool.fields)
          and
            or
              file.explode(attachments[])[].scan.exiftool.fields[].value match "Net.WebClient"
              file.explode(attachments[])[].scan.exiftool.fields[].value match "[Convert]::ToChar"
              file.explode(attachments[])[].scan.exiftool.fields[].value match "[IO.File]::Create"
              file.explode(attachments[])[].scan.exiftool.fields[].value match "[IO.File]::Exists"
              file.explode(attachments[])[].scan.exiftool.fields[].value match "[io.FileOPtions]::DeleteOnClose"
              file.explode(attachments[])[].scan.exiftool.fields[].value match "dll"
              file.explode(attachments[])[].scan.exiftool.fields[].value match "vbs"
            file.explode(attachments[])[].scan.exiftool.fields[].key eq "Hyperlinks"
      attachments.file_extension in ["ppt", "pptx"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where:
      • .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"]
         macro "attachments[].file_extension in file_extensions_common_archives"
      any(file.explode(attachments))
        file.explode(attachments).file_extension in ["cdxml", "ps1", "ps1xml", "ps2", "ps2xml", "psc2", "psd1", "psm1", "psrc", "pssc"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: QR code link with base64-encoded recipient address

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

Detects when an image or macro attachment contains QR codes that, when scanned, lead to URLs containing the recipient's email address. This tactic is used to uniquely track or target specific recipients and serve tailored credential phishing pages.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesQR code, Image as content, Social engineering, Evasion, PDF, Macros

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • body
  • body.current_thread
  • recipients
  • recipients.to
  • subject
  • type

Rule body

type.inbound
and 1 of (
  any(ml.nlu_classifier(subject.subject).intents,
      .name == "cred_theft" and .confidence == "high"
  ),
  body.current_thread.text is null,
  any($org_slds, strings.icontains(sender.display_name, .))
)
and any(attachments,
        (
          .file_type in $file_types_images
          or .file_extension in $file_extensions_macros
          or .file_type == "pdf"
        )
        and any(file.explode(.),
                any(recipients.to,
                    .email.domain.valid
                    and any(beta.scan_base64(..scan.qr.url.url,
                                             format="url",
                                             ignore_padding=true
                            ),
                            strings.icontains(., ..email.email)
                    )
                )
        )
)

Detection logic

Scope: inbound message.

Detects when an image or macro attachment contains QR codes that, when scanned, lead to URLs containing the recipient's email address. This tactic is used to uniquely track or target specific recipients and serve tailored credential phishing pages.

  1. inbound message
  2. at least 1 of:
    • any of ml.nlu_classifier(subject.subject).intents where all hold:
      • .name is 'cred_theft'
      • .confidence is 'high'
    • body.current_thread.text is missing
    • any of $org_slds where:
      • strings.icontains(sender.display_name)
  3. 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 of file.explode(.) where:
      • any of recipients.to where all hold:
        • .email.domain.valid
        • any of beta.scan_base64(.scan.qr.url.url) where:
          • strings.icontains(.)

Inspects: attachments[].file_extension, attachments[].file_type, body.current_thread.text, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, sender.display_name, subject.subject, type.inbound. Sensors: beta.scan_base64, file.explode, ml.nlu_classifier, strings.icontains. Reference lists: $file_extensions_macros, $file_types_images, $org_slds.

Indicators matched (3)

FieldMatchValue
ml.nlu_classifier(subject.subject).intents[].nameequalscred_theft
ml.nlu_classifier(subject.subject).intents[].confidenceequalshigh
attachments[].file_typeequalspdf

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        any(recipients.to)
          and
            any(beta.scan_base64(file.explode(attachments).scan.qr.url.url))
              strings.icontains func_call "strings.icontains(beta.scan_base64(file.explode(attachments[])[].scan.qr.url.url)[])"
            recipients.to.email.domain.valid eq "true"
      or
        attachments.file_type eq "pdf"
         macro "attachments[].file_extension in file_extensions_macros"
         macro "attachments[].file_type in file_types_images"
  or
    any(ml.nlu_classifier(subject.subject).intents)
      and
        ml.nlu_classifier(subject.subject).intents.confidence eq "high"
        ml.nlu_classifier(subject.subject).intents.name eq "cred_theft"
    any($org_slds)
      strings.icontains func_call "strings.icontains(sender.display_name)"
    body.current_thread.text is_null
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

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:
      • length(attachments) ≥ 1
      • length(attachments) < 3
    • all of:
      • all of:
        • length(attachments) ≥ 3
        • length(attachments) < 20
      • length(distinct(map(attachments, .file_extension))) is 2
      • all of distinct(...) where:
        • . 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 of filter(attachments) where:
          • any of filter(recipients.to) where:
            • strings.icontains(.file_name)
  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 of file.explode(.) where all hold:
      • .scan.qr.type is 'url'
      • not:
        • .scan.qr.url.domain.domain is 'geico.app.link'
      • any of:
        • any of [ml.link_analysis(.scan.qr.url)] where any holds:
          • .credphish.disposition is 'phishing'
          • any of .redirect_history where:
            • .domain.tld in $suspicious_tlds
          • .effective_url.domain.tld in $suspicious_tlds
          • .effective_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters
          • any of .files_downloaded where any holds:
            • .file_extension in $file_extensions_common_archives
            • .file_extension in $file_extensions_executables
        • any of:
          • .scan.qr.url.domain.root_domain in $url_shorteners
          • all of:
            • .scan.qr.url.domain.root_domain in $social_landing_hosts
            • any of:
              • none of:
                • any of ml.nlu_classifier(body.current_thread.text).intents where:
                  • .name is 'benign'
                • any of ml.nlu_classifier(body.current_thread.text).entities where:
                  • .name is 'disclaimer'
              • not:
                • any of attachments where:
                  • any of file.explode(.) where:
                    • any of ml.nlu_classifier(.scan.ocr.raw).intents where:
                      • .name is 'benign'
              • any of filter(recipients.to) where:
                • strings.icontains(.scan.qr.url.url)
            • not:
              • .scan.qr.url.url starts with 'https://goo.gl/maps'
            • not:
              • .scan.qr.url.url starts with 'https://maps.app.goo.gl'
        • all of:
          • .scan.qr.url.domain.root_domain is 'bing.com'
          • .scan.qr.url.path is '/ck/a'
        • .scan.qr.url.url matches '[^\\x00-\\x7F]'
        • any of:
          • all of:
            • .scan.qr.url.domain.root_domain is 'usap-dc.org'
            • .scan.qr.url.path is '/tracker'
            • .scan.qr.url.query_params starts with 'type=dataset&url=http'
          • any of filter(recipients.to) where any holds:
            • strings.icontains(.scan.qr.url.url)
            • any of strings.scan_base64(.scan.qr.url.url) where:
              • strings.icontains(.)
            • any of strings.scan_base64(.scan.qr.url.fragment) where:
              • strings.icontains(.)
  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)
  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
  any(attachments)
    and
      any(file.explode(attachments))
        and
          or
            and
              or
                not
                  any(attachments)
                    any(file.explode(attachments))
                      any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
                        ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents.name eq "benign"
                not
                  or
                    any(ml.nlu_classifier(body.current_thread.text).entities)
                      ml.nlu_classifier(body.current_thread.text).entities.name eq "disclaimer"
                    any(ml.nlu_classifier(body.current_thread.text).intents)
                      ml.nlu_classifier(body.current_thread.text).intents.name eq "benign"
                any(filter(recipients.to))
                  strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.qr.url.url)"
              not
                file.explode(attachments[])[].scan.qr.url.url starts_with "https://goo.gl/maps"
              not
                file.explode(attachments[])[].scan.qr.url.url starts_with "https://maps.app.goo.gl"
               macro "file.explode(attachments[])[].scan.qr.url.domain.root_domain in social_landing_hosts"
            any([ml.link_analysis(file.explode(attachments).scan.qr.url)])
              or
                any([ml.link_analysis(file.explode(attachments).scan.qr.url)].files_downloaded)
                  or
                     macro "[ml.link_analysis(file.explode(attachments[])[].scan.qr.url)][].files_downloaded[].file_extension in file_extensions_common_archives"
                     macro "[ml.link_analysis(file.explode(attachments[])[].scan.qr.url)][].files_downloaded[].file_extension in file_extensions_executables"
                any([ml.link_analysis(file.explode(attachments).scan.qr.url)].redirect_history)
                   macro "[ml.link_analysis(file.explode(attachments[])[].scan.qr.url)][].redirect_history[].domain.tld in suspicious_tlds"
                [ml.link_analysis(file.explode(attachments[])[].scan.qr.url)][].credphish.disposition eq "phishing"
                 macro "[ml.link_analysis(file.explode(attachments[])[].scan.qr.url)][].effective_url.domain.root_domain in abuse_ch_urlhaus_domains_trusted_reporters"
                 macro "[ml.link_analysis(file.explode(attachments[])[].scan.qr.url)][].effective_url.domain.tld in suspicious_tlds"
            any(filter(recipients.to))
              or
                any(strings.scan_base64(file.explode(attachments).scan.qr.url.fragment))
                  strings.icontains func_call "strings.icontains(strings.scan_base64(file.explode(attachments[])[].scan.qr.url.fragment)[])"
                any(strings.scan_base64(file.explode(attachments).scan.qr.url.url))
                  strings.icontains func_call "strings.icontains(strings.scan_base64(file.explode(attachments[])[].scan.qr.url.url)[])"
                strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.qr.url.url)"
            and
              file.explode(attachments[])[].scan.qr.url.domain.root_domain eq "bing.com"
              file.explode(attachments[])[].scan.qr.url.path eq "/ck/a"
            and
              file.explode(attachments[])[].scan.qr.url.domain.root_domain eq "usap-dc.org"
              file.explode(attachments[])[].scan.qr.url.path eq "/tracker"
              file.explode(attachments[])[].scan.qr.url.query_params starts_with "type=dataset&url=http"
            file.explode(attachments[])[].scan.qr.url.url regex_match "[^\\x00-\\x7F]"
             macro "file.explode(attachments[])[].scan.qr.url.domain.root_domain in url_shorteners"
          not
            file.explode(attachments[])[].scan.qr.url.domain.domain eq "geico.app.link"
          file.explode(attachments[])[].scan.qr.type eq "url"
      or
        attachments.file_type eq "pdf"
         macro "attachments[].file_extension in file_extensions_macros"
         macro "attachments[].file_type in file_types_images"
  or
    and
      or
        any(filter(attachments))
          any(filter(recipients.to))
            strings.icontains func_call "strings.icontains(filter(attachments)[].file_name)"
        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')) length_compare "3"
      attachments length_compare "20"
      attachments length_compare "3"
      distinct(map(attachments, .file_extension)) length_compare "2"
       macro "all(distinct(...))"
    and
      attachments length_compare "1"
      attachments length_compare "3"
  or
    and
      not
        coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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 of file.explode(.) where all hold:
        • .scan.qr.type is 'url'
        • any of recipients.to where all hold:
          • .email.domain.valid
          • any of:
            • strings.icontains(.scan.qr.url.url)
            • any of strings.scan_base64(.scan.qr.url.url) where:
              • strings.icontains(.)
        • .scan.qr.url.url matches '\\.(?:c(?:ompany|you)|sbs)(?:[$#]|\\?a=)'
    • all of:
      • any of:
        • .file_type is 'pdf'
        • .file_type in $file_types_images
      • any of beta.scan_qr(.).items where all hold:
        • .type is set
        • .url.url matches '\\.(?: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
        any(file.explode(attachments))
          and
            any(recipients.to)
              and
                or
                  any(strings.scan_base64(file.explode(attachments).scan.qr.url.url))
                    strings.icontains func_call "strings.icontains(strings.scan_base64(file.explode(attachments[])[].scan.qr.url.url)[])"
                  strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.qr.url.url)"
                recipients.to.email.domain.valid eq "true"
            file.explode(attachments[])[].scan.qr.type eq "url"
            file.explode(attachments[])[].scan.qr.url.url regex_match "\\.(?:c(?:ompany|you)|sbs)(?:[$#]|\\?a=)"
         macro "attachments[].file_extension in file_extensions_macros"
      and
        any(beta.scan_qr(attachments).items)
          and
            beta.scan_qr(attachments[]).items[].type is_not_null
            beta.scan_qr(attachments[]).items[].url.url regex_match "\\.(?:c(?:ompany|you)|sbs)(?:[$#]|\\?a=)"
        or
          attachments.file_type eq "pdf"
           macro "attachments[].file_type in file_types_images"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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) is 1
  3. recipients.to[0].email.domain.valid
  4. any of attachments where any holds:
    • all of:
      • .file_extension in $file_extensions_macros
      • any of file.explode(.) where all hold:
        • .scan.qr.type is 'url'
        • any of recipients.to where all hold:
          • .email.domain.valid
          • any of:
            • strings.icontains(.scan.qr.url.url)
            • any of strings.scan_base64(.scan.qr.url.url) where:
              • strings.icontains(.)
        • strings.count(.scan.qr.url.path, '/') is 2
        • any of:
          • all of:
            • any of:
              • .scan.qr.url.path contains '/$'
              • .scan.qr.url.path contains '/*'
              • .scan.qr.url.path contains '/#'
            • .scan.qr.url.domain.subdomain matches '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'
            • .scan.qr.url.path matches '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'
          • all of:
            • any of:
              • .scan.qr.url.path contains '!'
              • .scan.qr.url.path contains '@'
            • .scan.qr.url.path contains any of 6 patterns
              • /$
              • /*
              • /#
              • %24
              • %2A
              • %23
            • .scan.qr.url.url matches '[!@].*(?:[$*]|%2[A43])'
    • all of:
      • any of:
        • .file_type is 'pdf'
        • .file_type in $file_types_images
      • any of beta.scan_qr(.).items where all hold:
        • .type is set
        • strings.count(.url.path, '/') is 2
        • any of:
          • all of:
            • any of:
              • .url.path contains '/$'
              • .url.path contains '/*'
              • .url.path contains '/#'
            • .url.domain.subdomain matches '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'
            • .url.path matches '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'
          • all of:
            • any of:
              • .url.path contains '!'
              • .url.path contains '@'
            • .url.path contains any of 6 patterns
              • /$
              • /*
              • /#
              • %24
              • %2A
              • %23
            • .url.url matches '[!@].*(?:[$*]|%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
        any(file.explode(attachments))
          and
            any(recipients.to)
              and
                or
                  any(strings.scan_base64(file.explode(attachments).scan.qr.url.url))
                    strings.icontains func_call "strings.icontains(strings.scan_base64(file.explode(attachments[])[].scan.qr.url.url)[])"
                  strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.qr.url.url)"
                recipients.to.email.domain.valid eq "true"
            or
              and
                or
                  file.explode(attachments[])[].scan.qr.url.path contains "!"
                  file.explode(attachments[])[].scan.qr.url.path contains "@"
                or
                  file.explode(attachments[])[].scan.qr.url.path contains "%23"
                  file.explode(attachments[])[].scan.qr.url.path contains "%24"
                  file.explode(attachments[])[].scan.qr.url.path contains "%2A"
                  file.explode(attachments[])[].scan.qr.url.path contains "/#"
                  file.explode(attachments[])[].scan.qr.url.path contains "/$"
                  file.explode(attachments[])[].scan.qr.url.path contains "/*"
                file.explode(attachments[])[].scan.qr.url.url regex_match "[!@].*(?:[$*]|%2[A43])"
              and
                or
                  file.explode(attachments[])[].scan.qr.url.path contains "/#"
                  file.explode(attachments[])[].scan.qr.url.path contains "/$"
                  file.explode(attachments[])[].scan.qr.url.path contains "/*"
                file.explode(attachments[])[].scan.qr.url.domain.subdomain regex_match "^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)"
                file.explode(attachments[])[].scan.qr.url.path regex_match "\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/"
            file.explode(attachments[])[].scan.qr.type eq "url"
            strings.count func_call "strings.count(file.explode(attachments[])[].scan.qr.url.path, \"/\") == 2"
         macro "attachments[].file_extension in file_extensions_macros"
      and
        any(beta.scan_qr(attachments).items)
          and
            or
              and
                or
                  beta.scan_qr(attachments[]).items[].url.path contains "!"
                  beta.scan_qr(attachments[]).items[].url.path contains "@"
                or
                  beta.scan_qr(attachments[]).items[].url.path contains "%23"
                  beta.scan_qr(attachments[]).items[].url.path contains "%24"
                  beta.scan_qr(attachments[]).items[].url.path contains "%2A"
                  beta.scan_qr(attachments[]).items[].url.path contains "/#"
                  beta.scan_qr(attachments[]).items[].url.path contains "/$"
                  beta.scan_qr(attachments[]).items[].url.path contains "/*"
                beta.scan_qr(attachments[]).items[].url.url regex_match "[!@].*(?:[$*]|%2[A43])"
              and
                or
                  beta.scan_qr(attachments[]).items[].url.path contains "/#"
                  beta.scan_qr(attachments[]).items[].url.path contains "/$"
                  beta.scan_qr(attachments[]).items[].url.path contains "/*"
                beta.scan_qr(attachments[]).items[].url.domain.subdomain regex_match "^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)"
                beta.scan_qr(attachments[]).items[].url.path regex_match "\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/"
            beta.scan_qr(attachments[]).items[].type is_not_null
            strings.count func_call "strings.count(beta.scan_qr(attachments[]).items[].url.path, \"/\") == 2"
        or
          attachments.file_type eq "pdf"
           macro "attachments[].file_type in file_types_images"
  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.

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) is 1
  3. recipients.to[0].email.domain.valid
  4. any of attachments where:
    • any of file.parse_eml(.).attachments where any holds:
      • all of:
        • .file_extension in $file_extensions_macros
        • any of file.explode(.) where all hold:
          • .scan.qr.type is 'url'
          • any of recipients.to where all hold:
            • .email.domain.valid
            • any of:
              • strings.icontains(.scan.qr.url.url)
              • any of strings.scan_base64(.scan.qr.url.url) where:
                • strings.icontains(.)
          • strings.count(.scan.qr.url.path, '/') is 2
          • any of:
            • all of:
              • any of:
                • .scan.qr.url.path contains '/$'
                • .scan.qr.url.path contains '/*'
                • .scan.qr.url.path contains '/#'
              • .scan.qr.url.domain.subdomain matches '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'
              • .scan.qr.url.path matches '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'
            • all of:
              • any of:
                • .scan.qr.url.path contains '!'
                • .scan.qr.url.path contains '@'
              • .scan.qr.url.path contains any of 6 patterns
                • /$
                • /*
                • /#
                • %24
                • %2A
                • %23
              • .scan.qr.url.url matches '[!@].*(?:[$*]|%2[A43])'
      • any of beta.scan_qr(.).items where all hold:
        • .type is set
        • strings.count(.url.path, '/') is 2
        • any of:
          • all of:
            • any of:
              • .url.path contains '/$'
              • .url.path contains '/*'
              • .url.path contains '/#'
            • .url.domain.subdomain matches '^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)'
            • .url.path matches '\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/'
          • all of:
            • any of:
              • .url.path contains '!'
              • .url.path contains '@'
            • .url.path contains any of 6 patterns
              • /$
              • /*
              • /#
              • %24
              • %2A
              • %23
            • .url.url matches '[!@].*(?:[$*]|%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)
    any(file.parse_eml(attachments).attachments)
      or
        and
          any(file.explode(file.parse_eml(attachments).attachments))
            and
              any(recipients.to)
                and
                  or
                    any(strings.scan_base64(file.explode(file.parse_eml(attachments).attachments).scan.qr.url.url))
                      strings.icontains func_call "strings.icontains(strings.scan_base64(file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.url)[])"
                    strings.icontains func_call "strings.icontains(file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.url)"
                  recipients.to.email.domain.valid eq "true"
              or
                and
                  or
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "!"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "@"
                  or
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "%23"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "%24"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "%2A"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "/#"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "/$"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "/*"
                  file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.url regex_match "[!@].*(?:[$*]|%2[A43])"
                and
                  or
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "/#"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "/$"
                    file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path contains "/*"
                  file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.domain.subdomain regex_match "^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)"
                  file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path regex_match "\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/"
              file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.type eq "url"
              strings.count func_call "strings.count(file.explode(file.parse_eml(attachments[]).attachments[])[].scan.qr.url.path, \"/\") == 2"
           macro "file.parse_eml(attachments[]).attachments[].file_extension in file_extensions_macros"
        any(beta.scan_qr(file.parse_eml(attachments).attachments).items)
          and
            or
              and
                or
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "!"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "@"
                or
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "%23"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "%24"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "%2A"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "/#"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "/$"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "/*"
                beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.url regex_match "[!@].*(?:[$*]|%2[A43])"
              and
                or
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "/#"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "/$"
                  beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path contains "/*"
                beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.domain.subdomain regex_match "^(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)(?:$|\\.)"
                beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path regex_match "\\/(?:[a-z]+[0-9]{3}|[0-9]{3}[a-z]+)\\/"
            beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].type is_not_null
            strings.count func_call "strings.count(beta.scan_qr(file.parse_eml(attachments[]).attachments[]).items[].url.path, \"/\") == 2"
  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.

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 of file.explode(.) where all hold:
      • any of:
        • .scan.qr.url.username is set
        • .scan.qr.url.password is set
        • coalesce(.scan.qr.url.rewrite.original, .scan.qr.url.url) matches 'https?(?:(?:%3a|\\:)?(?:\\/|%2f){2})[^\\/]+(?:\\s+|%(?:25)?[a-f0-9]{2}|0x[a-f0-9]+){30,}(?:@|%(?:25)?40)[^\\/]+(?:\\/|%(?:25)?2f)'
      • .scan.qr.url.domain.root_domain is not sender.email.domain.root_domain
      • not:
        • any of recipients.to where:
          • .email.domain.root_domain is .scan.qr.url.domain.root_domain
      • not:
        • any of recipients.cc where:
          • .email.domain.root_domain is .scan.qr.url.domain.root_domain
      • strings.parse_email(.scan.qr.url.url).email is missing

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
      any(file.explode(attachments))
        and
          not
            any(recipients.cc)
              recipients.cc.email.domain.root_domain cross_field_compare "file.explode(attachments[])[].scan.qr.url.domain.root_domain"
          not
            any(recipients.to)
              recipients.to.email.domain.root_domain cross_field_compare "file.explode(attachments[])[].scan.qr.url.domain.root_domain"
          or
            coalesce(file.explode(attachments[])[].scan.qr.url.rewrite.original, file.explode(attachments[])[].scan.qr.url.url) regex_match "https?(?:(?:%3a|\\:)?(?:\\/|%2f){2})[^\\/]+(?:\\s+|%(?:25)?[a-f0-9]{2}|0x[a-f0-9]+){30,}(?:@|%(?:25)?40)[^\\/]+(?:\\/|%(?:25)?2f)"
            file.explode(attachments[])[].scan.qr.url.password is_not_null
            file.explode(attachments[])[].scan.qr.url.username is_not_null
          file.explode(attachments[])[].scan.qr.url.domain.root_domain cross_field_compare "sender.email.domain.root_domain"
          strings.parse_email(file.explode(attachments[])[].scan.qr.url.url).email is_null
      or
        attachments.file_type eq "pdf"
         macro "attachments[].file_extension in file_extensions_macros"
         macro "attachments[].file_type in file_types_images"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
        • .file_extension is '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
        any(file.explode(attachments))
          file.explode(attachments).file_extension eq "rdp"
         macro "attachments[].file_extension in file_extensions_common_archives"
    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
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')
    • file.parse_eml(.).subject.subject matches '(shared.{0,30}with you|View Document)'
    • all of:
      • length(file.parse_eml(.).body.links) > 0
      • length(file.parse_eml(.).body.links) < 10
    • file.parse_eml(.).sender.email.email not in $recipient_emails
    • not:
      • file.parse_eml(.).sender.email.local_part matches any of 3 patterns
        • *postmaster*
        • *mailer-daemon*
        • *administrator*
    • not:
      • file.parse_eml(.).subject.subject matches '(undeliverable|read:).*'
    • not:
      • any of file.parse_eml(.).attachments where:
        • .content_type is 'message/delivery-status'
    • any of:
      • all of:
        • file.parse_eml(.).sender.email.domain.root_domain in $high_trust_sender_root_domains
        • any of distinct(...) where:
          • .authentication_results.dmarc matches '*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 of distinct(headers.hops) where:
        • .authentication_results.dmarc matches '*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
          any(distinct(...))
            distinct(...).authentication_results.dmarc ends_with "fail"
          file.parse_eml func_call "file.parse_eml(attachments[]).sender.email.domain.root_domain in high_trust_sender_root_domains"
        file.parse_eml func_call "file.parse_eml(attachments[]).sender.email.domain.root_domain not in high_trust_sender_root_domains"
      not
        any(file.parse_eml(attachments).attachments)
          file.parse_eml(attachments).attachments.content_type eq "message/delivery-status"
      not
        or
          file.parse_eml(attachments[]).sender.email.local_part match "administrator"
          file.parse_eml(attachments[]).sender.email.local_part match "mailer-daemon"
          file.parse_eml(attachments[]).sender.email.local_part match "postmaster"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
      not
        file.parse_eml func_call "file.parse_eml(attachments[]).sender.email.domain.root_domain in org_domains"
      not
        file.parse_eml(attachments[]).subject.subject regex_match "(undeliverable|read:).*"
      attachments.file_type eq "unknown"
      file.parse_eml func_call "file.parse_eml(attachments[]).sender.email.email not in recipient_emails"
      file.parse_eml(attachments[]).body.links length_compare "0"
      file.parse_eml(attachments[]).body.links length_compare "10"
      file.parse_eml(attachments[]).subject.subject regex_match "(shared.{0,30}with you|View Document)"
  or
    and
      any(distinct(headers.hops))
        distinct(headers.hops).authentication_results.dmarc ends_with "fail"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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) is 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 of ml.nlu_classifier(body.current_thread.text).tags where:
      • .name is 'purchase_order'
    • any of attachments where:
      • any of file.explode(.) where:
        • any of ml.nlu_classifier(.scan.ocr.raw).entities where:
          • .text matches '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
  any(attachments)
    any(file.explode(attachments))
      any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).entities)
        ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).entities.text regex_match "department of|office of"
  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(ml.nlu_classifier(body.current_thread.text).tags)
    ml.nlu_classifier(body.current_thread.text).tags.name eq "purchase_order"
  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)"

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 of ml.nlu_classifier(body.current_thread.text).topics where all hold:
    • .name in ('Romance', 'Sexually Explicit Messages')
    • .confidence is not '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 of ml.nlu_classifier(body.current_thread.text).intents where all hold:
        • .name is 'advance_fee'
        • .confidence is not '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(ml.nlu_classifier(body.current_thread.text).intents)
        and
          ml.nlu_classifier(body.current_thread.text).intents.confidence ne "low"
          ml.nlu_classifier(body.current_thread.text).intents.name eq "advance_fee"
      any(headers.reply_to)
         macro "headers.reply_to[].email.domain.root_domain in free_email_providers"
       macro "sender.email.domain.root_domain not in free_email_providers"
    any(body.links)
      body.links.href_url.domain.domain in ["geno.link", "sites.google.com"]
  any(ml.nlu_classifier(body.current_thread.text).topics)
    and
      ml.nlu_classifier(body.current_thread.text).topics.confidence ne "low"
      ml.nlu_classifier(body.current_thread.text).topics.name in ["Romance", "Sexually Explicit Messages"]
  any(attachments)
    attachments.file_type in ["jpg", "png"]
  not
    subject.is_forward eq "true"
  not
    subject.is_reply eq "true"
  type.inbound eq "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"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: RTF file with suspicious link

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

This rule detects RTF attachments directly attached or within an archive, containing an external link to a suspicious low reputation domain.

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
  • recipients
  • recipients.to
  • type

Rule body

type.inbound
and any(attachments,
        (
          .file_extension in~ $file_extensions_common_archives
          or .file_type == "rtf"
        )
        and any(file.explode(.),
                .flavors.mime == 'text/rtf'
                and any(.scan.url.urls,
                        .domain.valid
                        and .domain.subdomain is not null
                        and not (
                          strings.ends_with(.url, "jpeg")
                          or strings.ends_with(.url, "png")
                        )
                        and (
                          (
                            .domain.root_domain not in $tranco_1m
                            and .domain.root_domain not in $umbrella_1m
                          )
                          or (
                            .domain.root_domain in $free_file_hosts
                            or .domain.root_domain in $free_file_hosts
                            or .domain.root_domain in $free_subdomain_hosts
                            or .domain.root_domain in $url_shorteners
                            or .domain.root_domain in $social_landing_hosts
                          )
                          // or the url contains the recipient email and the root_domain is not in tranco
                          or (
                            any(recipients.to,
                                strings.icontains(..url, .email.email)
                            )
                            and (
                              .domain.root_domain not in $tranco_1m
                              and .domain.root_domain not in $umbrella_1m
                            )
                          )
                        )
                )
        )
)
and not profile.by_sender().solicited
and not profile.by_sender().any_messages_benign

Detection logic

Scope: inbound message.

This rule detects RTF attachments directly attached or within an archive, containing an external link to a suspicious low reputation domain.

  1. inbound message
  2. any of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_common_archives
      • .file_type is 'rtf'
    • any of file.explode(.) where all hold:
      • .flavors.mime is 'text/rtf'
      • any of .scan.url.urls where all hold:
        • .domain.valid
        • .domain.subdomain is set
        • none of:
          • .url ends with 'jpeg'
          • .url ends with 'png'
        • any of:
          • all of:
            • .domain.root_domain not in $tranco_1m
            • .domain.root_domain not in $umbrella_1m
          • any of:
            • .domain.root_domain in $free_file_hosts
            • .domain.root_domain in $free_file_hosts
            • .domain.root_domain in $free_subdomain_hosts
            • .domain.root_domain in $url_shorteners
            • .domain.root_domain in $social_landing_hosts
          • all of:
            • any of recipients.to where:
              • strings.icontains(.url)
            • all of:
              • .domain.root_domain not in $tranco_1m
              • .domain.root_domain not in $umbrella_1m
  3. not:
    • profile.by_sender().solicited
  4. not:
    • profile.by_sender().any_messages_benign

Inspects: attachments[].file_extension, attachments[].file_type, recipients.to, recipients.to[].email.email, type.inbound. Sensors: file.explode, profile.by_sender, strings.ends_with, strings.icontains. Reference lists: $file_extensions_common_archives, $free_file_hosts, $free_subdomain_hosts, $social_landing_hosts, $tranco_1m, $umbrella_1m, $url_shorteners.

Indicators matched (2)

FieldMatchValue
attachments[].file_typeequalsrtf
file.explode(attachments[])[].flavors.mimeequalstext/rtf

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.url.urls)
            and
              or
                and
                  any(recipients.to)
                    strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.url.urls[].url)"
                   macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain not in tranco_1m"
                   macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain not in umbrella_1m"
                and
                   macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain not in tranco_1m"
                   macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain not in umbrella_1m"
                 macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in free_file_hosts"
                 macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in free_subdomain_hosts"
                 macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in social_landing_hosts"
                 macro "file.explode(attachments[])[].scan.url.urls[].domain.root_domain in url_shorteners"
              not
                or
                  file.explode(attachments[])[].scan.url.urls[].url ends_with "jpeg"
                  file.explode(attachments[])[].scan.url.urls[].url ends_with "png"
              file.explode(attachments[])[].scan.url.urls[].domain.subdomain is_not_null
              file.explode(attachments[])[].scan.url.urls[].domain.valid eq "true"
          file.explode(attachments[])[].flavors.mime eq "text/rtf"
      or
        attachments.file_type eq "rtf"
         macro "attachments[].file_extension in file_extensions_common_archives"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  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
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where any holds:
      • .flavors.mime in ('application/x-dosexec', 'text/x-msdos-batch', 'application/octet-stream')
      • any of .flavors.yara where:
        • . is 'base64_pe'
      • .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
      any(file.explode(attachments))
        or
          any(file.explode(attachments).flavors.yara)
            file.explode(attachments).flavors.yara eq "base64_pe"
          file.explode(attachments[])[].file_extension in ["bat", "exe", "vbs"]
          file.explode(attachments[])[].flavors.mime in ["application/octet-stream", "application/x-dosexec", "text/x-msdos-batch"]
      attachments.file_type eq "rtf"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: RTF with link to free-hosted Cloudflare Pages

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

Detects inbound emails that contain an RTF attachment. The rule extracts embedded content from the RTF file and inspects any URLs found within it, following redirects and analyzing the final destination page's links. It flags cases where those links point to domains hosted on the free Cloudflare Pages service (pages.dev), a common tactic used to host malicious or deceptive content while evading detection.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree subdomain host

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • type

Rule body

type.inbound
and any(filter(attachments, .file_type == 'rtf'),
        any(file.explode(.),
            any(.scan.url.urls,
                any(ml.link_analysis(.).final_dom.links,
                    .href_url.domain.root_domain in ('pages.dev')
                )
            )
        )
)

Detection logic

Scope: inbound message.

Detects inbound emails that contain an RTF attachment. The rule extracts embedded content from the RTF file and inspects any URLs found within it, following redirects and analyzing the final destination page's links. It flags cases where those links point to domains hosted on the free Cloudflare Pages service (pages.dev), a common tactic used to host malicious or deceptive content while evading detection.

  1. inbound message
  2. any of filter(attachments) where:
    • any of file.explode(.) where:
      • any of .scan.url.urls where:
        • any of ml.link_analysis(.).final_dom.links where:
          • .href_url.domain.root_domain in ('pages.dev')

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

Indicators matched (2)

FieldMatchValue
attachments[].file_typeequalsrtf
ml.link_analysis(file.explode(filter(attachments)[])[].scan.url.urls[]).final_dom.links[].href_url.domain.root_domainmemberpages.dev

Stages and Predicates

Stage 1: mql_rule

and
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      any(file.explode(filter(attachments)).scan.url.urls)
        any(ml.link_analysis(file.explode(filter(attachments)).scan.url.urls).final_dom.links)
          ml.link_analysis(file.explode(filter(attachments)).scan.url.urls).final_dom.links.href_url.domain.root_domain eq "pages.dev"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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) is 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 of filter(attachments) where:
    • any of file.explode(.) where all hold:
      • .scan.strings.strings[0] is 'VIEW PDF'
      • length(.scan.strings.strings) is 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
  any(filter(attachments))
    any(file.explode(filter(attachments)))
      and
        file.explode(filter(attachments)[])[].scan.strings.strings length_compare "1"
        file.explode(filter(attachments)[])[].scan.strings.strings[0] eq "VIEW PDF"
  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"

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 of file.explode(.) where all hold:
      • any of .scan.strings.strings where:
        • . matches 'CMT;The comment below contains SFX script commands'
      • any of .scan.strings.strings where:
        • . matches '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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings eq "CMT;The comment below contains SFX script commands"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings starts_with "Setup="
      attachments.file_extension in ["exe", "sfx"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: Single-page PDF with S3-hosted HTML link

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

Detects inbound messages containing a single-page PDF attachment that includes exactly one URL, which links directly to an HTML file hosted on an Amazon S3 bucket. This technique is commonly used to redirect recipients to credential harvesting pages while leveraging trusted cloud infrastructure to evade detection.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesPDF, Free file host, Evasion

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • type

Rule body

type.inbound
and any(attachments,
        .file_type == "pdf"
        // a single page pdf
        and beta.parse_exif(.).page_count == 1
        and any(file.explode(.),
                length(.scan.pdf.urls) == 1
                and any(.scan.pdf.urls,
                        strings.contains(.path, '.html')
                        and // links directly to a S3 bucket
                        .domain.root_domain == "amazonaws.com"
                        and strings.icontains(.domain.subdomain, "s3")
                )
        )
)

Detection logic

Scope: inbound message.

Detects inbound messages containing a single-page PDF attachment that includes exactly one URL, which links directly to an HTML file hosted on an Amazon S3 bucket. This technique is commonly used to redirect recipients to credential harvesting pages while leveraging trusted cloud infrastructure to evade detection.

  1. inbound message
  2. any of attachments where all hold:
    • .file_type is 'pdf'
    • beta.parse_exif(.).page_count is 1
    • any of file.explode(.) where all hold:
      • length(.scan.pdf.urls) is 1
      • any of .scan.pdf.urls where all hold:
        • .path contains '.html'
        • .domain.root_domain is 'amazonaws.com'
        • .domain.subdomain contains 's3'

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

Indicators matched (4)

FieldMatchValue
attachments[].file_typeequalspdf
strings.containssubstring.html
file.explode(attachments[])[].scan.pdf.urls[].domain.root_domainequalsamazonaws.com
strings.icontainssubstrings3

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.pdf.urls)
            and
              file.explode(attachments[])[].scan.pdf.urls[].domain.root_domain eq "amazonaws.com"
              file.explode(attachments[])[].scan.pdf.urls[].domain.subdomain contains "s3"
              file.explode(attachments[])[].scan.pdf.urls[].path contains ".html"
          file.explode(attachments[])[].scan.pdf.urls length_compare "1"
      attachments.file_type eq "pdf"
      beta.parse_exif func_call "beta.parse_exif(attachments[]).page_count == 1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: Small text file with link containing recipient email address

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

Attach text file is less than 1000 bytes and contains a recipients email address. Seen in the wild carrying credential phishing links.

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
  • recipients
  • recipients.to
  • type

Rule body

type.inbound
and any(attachments,
        .content_type in~ ("text/plain", "text")
        // negate calendar invites
        and not (
          .file_extension == "ics"
          or .content_type in ("application/ics", "text/calendar")
        )
        and any(file.explode(.),
                .size < 1000
                and any(.scan.url.urls,
                        any(recipients.to,
                            strings.icontains(..url, .email.email)
                            and .email.domain.valid
                        )
                )
        )
)

Detection logic

Scope: inbound message.

Attach text file is less than 1000 bytes and contains a recipients email address. Seen in the wild carrying credential phishing links.

  1. inbound message
  2. any of attachments where all hold:
    • .content_type in ('text/plain', 'text')
    • none of:
      • .file_extension is 'ics'
      • .content_type in ('application/ics', 'text/calendar')
    • any of file.explode(.) where all hold:
      • .size < 1000
      • any of .scan.url.urls where:
        • any of recipients.to where all hold:
          • strings.icontains(.url)
          • .email.domain.valid

Inspects: attachments[].content_type, attachments[].file_extension, recipients.to, recipients.to[].email.domain.valid, recipients.to[].email.email, type.inbound. Sensors: file.explode, strings.icontains.

Indicators matched (2)

FieldMatchValue
attachments[].content_typemembertext/plain
attachments[].content_typemembertext

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.url.urls)
            any(recipients.to)
              and
                recipients.to.email.domain.valid eq "true"
                strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.url.urls[].url)"
          file.explode(attachments[])[].size lt "1000"
      not
        or
          attachments.content_type in ["application/ics", "text/calendar"]
          attachments.file_extension eq "ics"
      attachments.content_type in ["text", "text/plain"]
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where:
      • .scan.exiftool.producer is 'Soda PDF'
    • any of file.explode(.) where all hold:
      • any of:
        • .scan.ocr.raw contains 'has been encrypted'
        • .scan.ocr.raw contains 'encrypted pdf file'
        • .scan.ocr.raw contains 'is secured by'
      • .scan.ocr.raw contains '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
      any(file.explode(attachments))
        and
          or
            file.explode(attachments[])[].scan.ocr.raw contains "encrypted pdf file"
            file.explode(attachments[])[].scan.ocr.raw contains "has been encrypted"
            file.explode(attachments[])[].scan.ocr.raw contains "is secured by"
          file.explode(attachments[])[].scan.ocr.raw contains "PDF"
      any(file.explode(attachments))
        file.explode(attachments).scan.exiftool.producer eq "Soda PDF"
      attachments.file_extension eq "pdf"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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:
    • length(attachments) > 0
    • 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.domain.valid
  5. not:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • coalesce(headers.auth_summary.dmarc.pass)

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(attachments[].file_name)"
        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
      coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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
field:"type.inbound" kind:eq value:"true"

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 of filter(attachments) where all hold:
      • any of:
        • all of:
          • any of file.explode(.) where:
            • .scan.ocr.raw contains 'TABLE OF CONTEN'
          • any of file.explode(.) where any holds:
            • .scan.ocr.raw matches '(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction'
            • .scan.ocr.raw contains 'marked in red'
        • any of file.explode(.) where any holds:
          • any of .scan.strings.strings where:
            • any of ['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal'] where:
              • . is .
          • any of .scan.url.urls where all hold:
            • .domain.root_domain in $free_subdomain_hosts
            • .domain.subdomain is set
            • .domain.root_domain not in ('atlassian.net')
      • any of:
        • all of:
          • any of:
            • beta.parse_exif(.).creator contains 'HeadlessChrome'
            • beta.parse_exif(.).creator contains 'Chromium'
          • beta.parse_exif(.).producer contains 'Skia/PDF'
        • all of:
          • any of beta.parse_exif(.).fields where all hold:
            • .key is 'Creator'
            • any of:
              • .value is ''
              • .value starts with 'wkhtmltopdf'
          • any of beta.parse_exif(.).fields where all hold:
            • .key is 'Title'
            • any of:
              • .value is ''
              • .value in ('Company HandBook')
              • .value contains 'Employee Performance Appraisal'
          • beta.parse_exif(.).producer starts with 'QT '
    • any of filter(attachments) where:
      • any of filter(...) where all hold:
        • any of:
          • all of:
            • any of file.explode(.) where:
              • .scan.ocr.raw contains 'TABLE OF CONTEN'
            • any of file.explode(.) where any holds:
              • .scan.ocr.raw matches '(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction'
              • .scan.ocr.raw contains 'marked in red'
          • any of file.explode(.) where any holds:
            • any of .scan.strings.strings where:
              • any of ['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal'] where:
                • . is .
            • any of .scan.url.urls where all hold:
              • .domain.root_domain in $free_subdomain_hosts
              • .domain.subdomain is set
        • any of:
          • all of:
            • any of:
              • beta.parse_exif(.).creator contains 'HeadlessChrome'
              • beta.parse_exif(.).creator contains 'Chromium'
            • beta.parse_exif(.).producer contains 'Skia/PDF'
          • all of:
            • any of beta.parse_exif(.).fields where all hold:
              • .key is 'Creator'
              • any of:
                • .value is ''
                • .value starts with 'wkhtmltopdf'
            • any of beta.parse_exif(.).fields where all hold:
              • .key is 'Title'
              • any of:
                • .value is ''
                • .value in ('Company HandBook')
                • .value contains 'Employee Performance Appraisal'
            • beta.parse_exif(.).producer starts with 'QT '

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: beta.parse_exif, file.explode, file.parse_eml, regex.icontains, strings.contains, strings.icontains, strings.istarts_with. Reference lists: $free_subdomain_hosts.

Indicators matched (21)

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

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(filter(attachments))
      any(filter(...))
        and
          or
            and
              any(beta.parse_exif(filter(...)).fields)
                and
                  or
                    beta.parse_exif(filter(...)[]).fields[].value contains "Employee Performance Appraisal"
                    beta.parse_exif(filter(...)[]).fields[].value eq ""
                    beta.parse_exif(filter(...)[]).fields[].value eq "Company HandBook"
                  beta.parse_exif(filter(...)[]).fields[].key eq "Title"
              any(beta.parse_exif(filter(...)).fields)
                and
                  or
                    beta.parse_exif(filter(...)[]).fields[].value eq ""
                    beta.parse_exif(filter(...)[]).fields[].value starts_with "wkhtmltopdf"
                  beta.parse_exif(filter(...)[]).fields[].key eq "Creator"
              beta.parse_exif(filter(...)[]).producer starts_with "QT "
            and
              or
                beta.parse_exif(filter(...)[]).creator contains "Chromium"
                beta.parse_exif(filter(...)[]).creator contains "HeadlessChrome"
              beta.parse_exif(filter(...)[]).producer contains "Skia/PDF"
          or
            any(file.explode(filter(...)))
              or
                any(file.explode(filter(...)).scan.strings.strings)
                  any(['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal'])
                    file.explode(filter(...)[])[].scan.strings.strings[] cross_field_compare "['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal']"
                any(file.explode(filter(...)).scan.url.urls)
                  and
                    file.explode(filter(...)[])[].scan.url.urls[].domain.subdomain is_not_null
                     macro "file.explode(filter(...)[])[].scan.url.urls[].domain.root_domain in free_subdomain_hosts"
            and
              any(file.explode(filter(...)))
                or
                  file.explode(filter(...)[])[].scan.ocr.raw contains "marked in red"
                  file.explode(filter(...)[])[].scan.ocr.raw regex_match "(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction"
              any(file.explode(filter(...)))
                file.explode(filter(...)).scan.ocr.raw contains "TABLE OF CONTEN"
    any(filter(attachments))
      and
        or
          any(file.explode(filter(attachments)))
            or
              any(file.explode(filter(attachments)).scan.url.urls)
                and
                  not
                    file.explode(filter(attachments)[])[].scan.url.urls[].domain.root_domain eq "atlassian.net"
                  file.explode(filter(attachments)[])[].scan.url.urls[].domain.subdomain is_not_null
                   macro "file.explode(filter(attachments)[])[].scan.url.urls[].domain.root_domain in free_subdomain_hosts"
              any(file.explode(filter(attachments)).scan.strings.strings)
                any(['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal'])
                  file.explode(filter(attachments)[])[].scan.strings.strings[] cross_field_compare "['Employee Acknowledgement', 'Document Summary', 'appraisal overview', 'accessing full appraisal']"
          and
            any(file.explode(filter(attachments)))
              or
                file.explode(filter(attachments)[])[].scan.ocr.raw contains "marked in red"
                file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "(?:[\\r\\n]|^)+(?:\\s*1\\s*(?:\\.|:))?\\s*Introduction"
            any(file.explode(filter(attachments)))
              file.explode(filter(attachments)).scan.ocr.raw contains "TABLE OF CONTEN"
        or
          and
            any(beta.parse_exif(filter(attachments)).fields)
              and
                or
                  beta.parse_exif(filter(attachments)[]).fields[].value contains "Employee Performance Appraisal"
                  beta.parse_exif(filter(attachments)[]).fields[].value eq ""
                  beta.parse_exif(filter(attachments)[]).fields[].value eq "Company HandBook"
                beta.parse_exif(filter(attachments)[]).fields[].key eq "Title"
            any(beta.parse_exif(filter(attachments)).fields)
              and
                or
                  beta.parse_exif(filter(attachments)[]).fields[].value eq ""
                  beta.parse_exif(filter(attachments)[]).fields[].value starts_with "wkhtmltopdf"
                beta.parse_exif(filter(attachments)[]).fields[].key eq "Creator"
            beta.parse_exif(filter(attachments)[]).producer starts_with "QT "
          and
            or
              beta.parse_exif(filter(attachments)[]).creator contains "Chromium"
              beta.parse_exif(filter(attachments)[]).creator contains "HeadlessChrome"
            beta.parse_exif(filter(attachments)[]).producer contains "Skia/PDF"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • .file_extension is 'svg'
      • any of .scan.strings.strings where:
        • . contains 'ActiveXObject'
      • any of .scan.strings.strings where:
        • . contains 'WScript.Shell'
      • any of .scan.strings.strings where:
        • . matches any of 2 patterns
          • *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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.strings.strings)
            or
              file.explode(attachments[])[].scan.strings.strings[] match "Execute"
              file.explode(attachments[])[].scan.strings.strings[] match "Run"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings contains "ActiveXObject"
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings contains "WScript.Shell"
          file.explode(attachments[])[].file_extension eq "svg"
      or
        attachments.file_extension eq "svg"
        attachments.file_type eq "svg"
         macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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'
    • file.parse_text(., encodings=['ascii', 'utf8', 'utf16-le']).text matches '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"
      file.parse_text(attachments[], encodings=['ascii', 'utf8', 'utf16-le']).text regex_match "href\\s*=\\s*[\"\\x27]\\s*(?:&#x?[0-9a-f]+;\\s*){3,}"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: SVG file with hyperlinks and cursor styling

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

Detects inbound messages containing SVG attachments that include clickable hyperlink elements and CSS pointer cursor styling, which may be used to deceive recipients into clicking malicious links disguised as legitimate images.

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

Rule body

type.inbound
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, . == "a"))
        and regex.icontains(file.parse_text(., encodings=["ascii", "utf8"]).text,
                            'cursor\s*=\s*["\x27]pointer'
        )
)

Detection logic

Scope: inbound message.

Detects inbound messages containing SVG attachments that include clickable hyperlink elements and CSS pointer cursor styling, which may be used to deceive recipients into clicking malicious links disguised as legitimate images.

  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'
    • any of file.explode(.) where:
      • any of .scan.xml.tags where:
        • . is 'a'
    • file.parse_text(., encodings=['ascii', 'utf8']).text matches 'cursor\\s*=\\s*["\\x27]pointer'

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, type.inbound. Sensors: file.explode, file.parse_text, regex.icontains.

Indicators matched (5)

FieldMatchValue
attachments[].file_extensionequalssvg
attachments[].content_typememberimage/svg+xml
attachments[].file_typeequalssvg
file.explode(attachments[])[].scan.xml.tags[]equalsa
regex.icontainsregexcursor\s*=\s*["\x27]pointer

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.xml.tags)
          file.explode(attachments).scan.xml.tags eq "a"
      or
        attachments.content_type eq "image/svg+xml"
        attachments.file_extension eq "svg"
        attachments.file_type eq "svg"
      file.parse_text(attachments[], encodings=['ascii', 'utf8']).text regex_match "cursor\\s*=\\s*[\"\\x27]pointer"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
      • any of .scan.xml.tags where:
        • . is 'circle'
      • at least 1 of:
        • any of .scan.xml.tags where:
          • . in ('image', 'a')
        • .scan.qr.data is set
        • any of recipients.to where:
          • strings.icontains(.file_name)
        • any of recipients.to where:
          • strings.icontains(.file_name)

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
      any(file.explode(attachments))
        and
          or
            any(file.explode(attachments).scan.xml.tags)
              file.explode(attachments).scan.xml.tags in ["a", "image"]
            any(recipients.to)
              strings.icontains func_call "strings.icontains(file.explode(attachments[])[].file_name)"
            file.explode(attachments[])[].scan.qr.data is_not_null
          any(file.explode(attachments).scan.xml.tags)
            file.explode(attachments).scan.xml.tags eq "circle"
      or
        attachments.content_type eq "image/svg+xml"
        attachments.file_extension eq "svg"
        attachments.file_type eq "svg"
  attachments length_compare "4"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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
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 of filter(attachments) where:
    • any of filter(...) where all hold:
      • .scan.strings.raw matches '<w:t>Q[1-4]\\S202[5-9]<\\/w:t>'
      • .scan.strings.raw contains '<w:t xml:space="preserve">STATUS </w:t>'
      • .scan.strings.raw contains '<w:t xml:space="preserve">ACKNOWLEDGEMENT </w:t>'
      • any of regex.extract(.scan.strings.raw) where:
        • any of recipients.to where any holds:
          • .named_groups['name'] is .email.local_part
          • .named_groups['name'] is .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
  any(filter(attachments))
    any(filter(...))
      and
        any(regex.extract(filter(...).scan.strings.raw))
          any(recipients.to)
            or
              regex.extract(filter(...)[].scan.strings.raw)[].named_groups['name'] cross_field_compare "recipients.to.display_name"
              regex.extract(filter(...)[].scan.strings.raw)[].named_groups['name'] cross_field_compare "recipients.to.email.local_part"
        filter(...).scan.strings.raw contains "<w:t xml:space=\"preserve\">ACKNOWLEDGEMENT </w:t>"
        filter(...).scan.strings.raw contains "<w:t xml:space=\"preserve\">STATUS </w:t>"
        filter(...).scan.strings.raw regex_match "<w:t>Q[1-4]\\S202[5-9]<\\/w:t>"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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
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) is 1
  3. all of attachments where all hold:
    • any of:
      • .file_extension in $file_extensions_macros
      • .file_type is 'pdf'
    • any of file.explode(.) where:
      • any of ml.nlu_classifier(.scan.ocr.raw).entities where:
        • .text contains '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 of ml.nlu_classifier(body.current_thread.text).entities where all hold:
    • .text is 'usda'
    • .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"
  any(ml.nlu_classifier(body.current_thread.text).entities)
    and
      ml.nlu_classifier(body.current_thread.text).entities.name in ["org", "sender"]
      ml.nlu_classifier(body.current_thread.text).entities.text eq "usda"
  attachments length_compare "1"
  body.current_thread.text contains "bid"
  sender.email.domain.domain contains "usda"
  type.inbound eq "true"
   macro "all(attachments)"

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:
      • regex.count(file.parse_text(.).text) / length(distinct(regex.extract(file.parse_text(.).text, '// [A-Z][ a-z ]+\\.'), .full_match)) ≥ 2
      • regex.count(file.parse_text(.).text, '<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\\. (</[a-z]+>)? +-->') > 2
      • 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 "regex.count(file.parse_text(attachments[]).text, \"<!-- +(<[a-z]+>)? [A-Z][ a-z ]+\\. (</[a-z]+>)? +-->\") > 2"
        regex.count func_call "regex.count(file.parse_text(attachments[]).text, \"<[a-z0-9]+ style=\"display:none;\">(<[a-z]+>)? [A-Z].*\\. </[a-z0-9]+>\") > 2"
         macro "(regex.count(file.parse_text(attachments[]).text) / length(distinct(regex.extract(file.parse_text(attachments[]).text, '// [A-Z][ a-z ]+\\\\.'), attachments[].full_match))) >= 2"
      attachments.size lt "100000"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is '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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.yara.matches)
          file.explode(attachments).scan.yara.matches.name eq "WinRAR_CVE_2025_8088"
      or
        attachments.content_type eq "application/x-rar-compressed"
        attachments.file_extension eq "rar"
        attachments.file_type eq "rar"
      attachments.size lt "10000000"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of filter(attachments) where:
    • any of filter(...) where:
      • any of regex.iextract(.value) where:
        • strings.ends_with(.value)

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
  any(filter(attachments))
    any(filter(...))
      any(regex.iextract(filter(...).value))
        strings.ends_with func_call "strings.ends_with(filter(...)[].value)"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • all of:
        • .depth is 0
        • any of .scan.zip.all_paths where:
          • . matches '.+\\.\\w+\\s\\/.+\\.\\w+\\s\\.\\w+'
      • any of .scan.zip.all_paths where:
        • any of .scan.zip.all_paths where all hold:
          • . is not .
          • 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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.zip.all_paths)
            any(file.explode(attachments).scan.zip.all_paths)
              and
                file.explode(attachments[])[].scan.zip.all_paths[] cross_field_compare "file.explode(attachments[])[].scan.zip.all_paths[]"
                strings.starts_with func_call "strings.starts_with(file.explode(attachments[])[].scan.zip.all_paths[])"
          any(file.explode(attachments).scan.zip.all_paths)
            file.explode(attachments).scan.zip.all_paths regex_match ".+\\.\\w+\\s\\/.+\\.\\w+\\s\\.\\w+"
          file.explode(attachments[])[].depth eq "0"
       macro "attachments[].file_extension in file_extensions_common_archives"
  or
    and
       macro "sender.email.domain.domain not in recipient_domains"
       macro "sender.email.domain.root_domain not in free_email_providers"
    and
       macro "sender.email.domain.root_domain in free_email_providers"
       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
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 of filter(attachments) where:
  • any of file.explode(.) where:
    • any of .scan.yara.matches where:
      • .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

any(filter(attachments))
  any(file.explode(filter(attachments)))
    any(file.explode(filter(attachments)).scan.yara.matches)
      file.explode(filter(attachments)).scan.yara.matches.name eq "zip_cve_2026_0866"

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 of ml.logo_detect(.).brands where all hold:
          • .name is 'Adobe'
          • .confidence in ('medium', 'high')
        • any of ml.logo_detect(file.message_screenshot()).brands where:
          • .name is 'Adobe'
        • any of file.explode(.) where:
          • any of .scan.strings.strings where all hold:
            • . matches 'adobe (acrobat|sign)'
            • not:
              • . matches '(creatortool|producer|creator).{1,5}adobe acrobat'
    • any of attachments where all hold:
      • .file_extension in $file_extensions_macros
      • any of file.explode(.) where all hold:
        • .depth is 0
        • .scan.docx.image_count > 0
      • any of file.explode(.) where:
        • any of .scan.strings.strings where:
          • . matches '*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 of file.explode(.) where all hold:
        • .scan.ocr.raw matches 'scan|camera'
        • .scan.ocr.raw matches '\\bQR\\b|Q\\.R\\.|barcode'
      • any of file.explode(.) where all hold:
        • .scan.qr.type is 'url'
        • any of:
          • any of recipients.to where any holds:
            • all of:
              • .email.domain.valid
              • any of:
                • strings.icontains(.scan.qr.data)
                • any of strings.scan_base64(.scan.qr.data) where:
                  • strings.icontains(.)
            • .display_name contains 'undisclosed'
          • any of recipients.to where:
            • strings.icontains(sender.display_name)
          • any of recipients.to where:
            • strings.icontains(body.current_thread.text)
          • body.current_thread.text is missing
          • body.current_thread.text is ''
          • subject.subject matches '(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)'
          • any of ml.nlu_classifier(body.current_thread.text).intents where all hold:
            • .name is 'cred_theft'
            • .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
  any(attachments)
    and
      or
        any(file.explode(attachments))
          and
            or
              any(recipients.to)
                or
                  and
                    or
                      any(strings.scan_base64(file.explode(attachments).scan.qr.data))
                        strings.icontains func_call "strings.icontains(strings.scan_base64(file.explode(attachments[])[].scan.qr.data)[])"
                      strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.qr.data)"
                    recipients.to.email.domain.valid eq "true"
                  recipients.to.display_name contains "undisclosed"
              any(ml.nlu_classifier(body.current_thread.text).intents)
                and
                  ml.nlu_classifier(body.current_thread.text).intents.confidence eq "high"
                  ml.nlu_classifier(body.current_thread.text).intents.name eq "cred_theft"
              any(recipients.to)
                strings.icontains func_call "strings.icontains(body.current_thread.text)"
              any(recipients.to)
                strings.icontains func_call "strings.icontains(sender.display_name)"
              body.current_thread.text eq ""
              body.current_thread.text is_null
              subject.subject regex_match "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)"
            file.explode(attachments[])[].scan.qr.type eq "url"
        any(file.explode(attachments))
          and
            file.explode(attachments[])[].scan.ocr.raw regex_match "\\bQR\\b|Q\\.R\\.|barcode"
            file.explode(attachments[])[].scan.ocr.raw regex_match "scan|camera"
      or
        attachments.file_type eq "pdf"
         macro "attachments[].file_type in file_extensions_macros"
         macro "attachments[].file_type in file_types_images"
  or
    any(attachments)
      and
        or
          any(file.explode(attachments))
            any(file.explode(attachments).scan.strings.strings)
              and
                not
                  file.explode(attachments[])[].scan.strings.strings[] regex_match "(creatortool|producer|creator).{1,5}adobe acrobat"
                file.explode(attachments[])[].scan.strings.strings[] regex_match "adobe (acrobat|sign)"
          any(ml.logo_detect(attachments).brands)
            and
              ml.logo_detect(attachments[]).brands[].confidence in ["high", "medium"]
              ml.logo_detect(attachments[]).brands[].name eq "Adobe"
          any(ml.logo_detect(file.message_screenshot()).brands)
            ml.logo_detect(file.message_screenshot()).brands.name eq "Adobe"
        or
          attachments.file_type eq "pdf"
           macro "attachments[].file_type in file_types_images"
    any(attachments)
      and
        any(file.explode(attachments))
          any(file.explode(attachments).scan.strings.strings)
            file.explode(attachments).scan.strings.strings match "adobe"
        any(file.explode(attachments))
          and
            file.explode(attachments[])[].depth eq "0"
            file.explode(attachments[])[].scan.docx.image_count gt "0"
         macro "attachments[].file_extension in file_extensions_macros"
  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"]
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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 of ml.logo_detect(.).brands where all hold:
        • .name is 'DocuSign'
        • .confidence in ('medium', 'high')
      • any of ml.logo_detect(file.message_screenshot()).brands where:
        • .name is 'DocuSign'
    • any of file.explode(.) where all hold:
      • any of:
        • all of:
          • .scan.qr.type is set
          • .scan.qr.data matches '\\.'
        • all of:
          • .scan.ocr.raw matches 'scan|camera'
          • .scan.ocr.raw matches '\\bQR\\b|Q\\.R\\.|barcode'
      • not:
        • any of .scan.exiftool.fields where any holds:
          • .key is 'Model'
          • all of:
            • .key is 'Software'
            • .value starts with 'Android'
      • not:
        • any of .scan.exiftool.fields where all hold:
          • .key is 'DeviceManufacturer'
          • .value is '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
      any(file.explode(attachments))
        and
          not
            any(file.explode(attachments).scan.exiftool.fields)
              or
                and
                  file.explode(attachments[])[].scan.exiftool.fields[].key eq "Software"
                  file.explode(attachments[])[].scan.exiftool.fields[].value starts_with "Android"
                file.explode(attachments[])[].scan.exiftool.fields[].key eq "Model"
          not
            any(file.explode(attachments).scan.exiftool.fields)
              and
                file.explode(attachments[])[].scan.exiftool.fields[].key eq "DeviceManufacturer"
                file.explode(attachments[])[].scan.exiftool.fields[].value eq "Apple Computer Inc."
          or
            and
              file.explode(attachments[])[].scan.ocr.raw regex_match "\\bQR\\b|Q\\.R\\.|barcode"
              file.explode(attachments[])[].scan.ocr.raw regex_match "scan|camera"
            and
              file.explode(attachments[])[].scan.qr.data regex_match "\\."
              file.explode(attachments[])[].scan.qr.type is_not_null
      or
        any(ml.logo_detect(attachments).brands)
          and
            ml.logo_detect(attachments[]).brands[].confidence in ["high", "medium"]
            ml.logo_detect(attachments[]).brands[].name eq "DocuSign"
        any(ml.logo_detect(file.message_screenshot()).brands)
          ml.logo_detect(file.message_screenshot()).brands.name eq "DocuSign"
      or
        attachments.file_type eq "pdf"
         macro "attachments[].file_type in file_types_images"
  not
    and
      headers.auth_summary.dmarc.pass eq "true"
      sender.email.domain.root_domain in ["docusign.com", "docusign.net"]
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Brand impersonation: DocuSign branded attachment lure with no DocuSign links

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

Detects DocuSign phishing messages with no DocuSign links, a DocuSign logo or verbage within an image or PDF attachment, from an untrusted sender.

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.current_thread
  • body.links
  • headers
  • headers.hops
  • type

Rule body

type.inbound
and (
  (
    0 < length(attachments) <= 8
    and length(filter(attachments, .file_type in $file_types_images)) > 0
  )
  or (
    length(attachments) > 0
    and all(attachments,
            .file_type in $file_types_images
            or .file_type == 'pdf'
            or (
              .file_extension == "ics"
              or .content_type in ("text/calendar", "application/ics")
            )
    )
  )
)
and (
  // if there are links, ensure they are not docusign links
  (
    length(body.links) != 0
    and any(body.links,
            not strings.ilike(.href_url.domain.root_domain, "docusign.*")
    )
  )
  // sometimes there are no body links and it's all in the PDF attachment
  or length(body.links) == 0
)
and (
  // check the image or pdf attachments for Docusign 
  any(filter(attachments,
             .file_type in $file_types_images or .file_type == 'pdf'
      ),
      (
        any(ml.logo_detect(.).brands, .name == "DocuSign")
        or any(file.explode(.),
               strings.ilike(.scan.ocr.raw, "*DocuSign*")
               and (
                 any(ml.nlu_classifier(.scan.ocr.raw).intents,
                     .name == "cred_theft" and .confidence != "low"
                 )
                 or (
                   regex.icontains(.scan.ocr.raw,
                                   "((re)?view|access|complete(d)?) document(s)?",
                                   '[^d][^o][^cd][^ue]sign(?:\b|ature)',
                                   "important edocs",
                                   // German (Document (check|check|sign|sent))
                                   "Dokument (überprüfen|prüfen|unterschreiben|geschickt)",
                                   // German (important|urgent|immediate)
                                   "(wichtig|dringend|sofort)"
                   )
                   and any(ml.nlu_classifier(.scan.ocr.raw).topics,
                           .name == "E-Signature"
                   )
                   and not strings.count(.scan.ocr.raw, "\n\n\n\n\n\n\n\n\n\n") > 3
                 )
               )
        )
      )
      and not any(file.explode(.),
                  strings.ilike(.scan.ocr.raw,
                                "*DocuSigned By*",
                                "*DocuSign Envelope ID*",
                                "*Certificate Of Completion*",
                                "*Adobe Sign*",
                                // Additional Adobe Acrobat Sign check
                                "*Powered by\nAdobe\nAcrobat Sign*"
                  )
                  or (
                    .depth == 0
                    and (
                      (
                        .scan.exiftool.page_count > 10
                        and length(.scan.strings.strings) > 8000
                      )
                      or (
                        .scan.exiftool.producer == "Acrobat Sign"
                        and any(.scan.exiftool.fields,
                                .key == "SigningReason"
                                and .value == "Certified by Adobe Acrobat Sign"
                        )
                      )
                    )
                  )
                  // negate resume related messages
                  or (
                    any(ml.nlu_classifier(body.current_thread.text).topics,
                        .name == "Professional and Career Development"
                        and .confidence == "high"
                    )
                    and any(ml.nlu_classifier(.scan.ocr.raw).intents,
                            .name == "benign" and .confidence != "low"
                    )
                  )
      )
  )

  // accomidate truncated pngs and GIF files which can cause logodetect/OCR failures
  or (
    any(attachments,
        .file_type =~ "gif"
        //
        // 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.parse_exif(.).fields,
               .key == "Warning" and .value == "Truncated PNG image"
        )
    )
    and (
      any(ml.logo_detect(file.message_screenshot()).brands, .name == "DocuSign")
      //
      // 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 strings.ilike(beta.ocr(file.message_screenshot()).text, "*DocuSign*")
    )
    and (
      (
        any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents,
            .name == "cred_theft" and .confidence != "low"
        )
        or regex.icontains(beta.ocr(file.message_screenshot()).text,
                           "((re)?view|access|complete(d)?) document(s)?",
                           "[^d][^o][^c][^u]sign",
                           "important edocs",
                           // German (Document (check|check|sign|sent))
                           "Dokument (überprüfen|prüfen|unterschreiben|geschickt)",
                           // German (important|urgent|immediate)
                           "(wichtig|dringend|sofort)"
        )
      )
    )
    and not strings.ilike(beta.ocr(file.message_screenshot()).text,
                          "*DocuSigned By*",
                          "*DocuSign Envelope ID*",
                          "*Certificate Of Completion*",
                          "*Adobe Sign*"
    )
  )
)
and (
  not profile.by_sender_email().solicited
  or profile.by_sender_email().prevalence == "new"
  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

// negate docusign 'via' messages
and not (
  any(headers.hops,
      any(.fields,
          .name == "X-Api-Host" and strings.ends_with(.value, "docusign.net")
      )
  )
  and strings.contains(sender.display_name, "via")
)
// negate docusign originated emails
and not any(headers.hops,
            regex.imatch(.received.server.raw, ".+.docusign.(net|com)")
)

// negate replies to docusign notifications
and not any(headers.references, strings.iends_with(., '@camail.docusign.net'))

Detection logic

Scope: inbound message.

Detects DocuSign phishing messages with no DocuSign links, a DocuSign logo or verbage within an image or PDF attachment, from an untrusted sender.

  1. inbound message
  2. any of:
    • all of:
      • all of:
        • length(attachments) > 0
        • length(attachments) ≤ 8
      • length(filter(attachments, .file_type in $file_types_images)) > 0
    • all of:
      • length(attachments) > 0
      • all of attachments where any holds:
        • .file_type in $file_types_images
        • .file_type is 'pdf'
        • any of:
          • .file_extension is 'ics'
          • .content_type in ('text/calendar', 'application/ics')
  3. any of:
    • all of:
      • length(body.links) is not 0
      • any of body.links where:
        • not:
          • .href_url.domain.root_domain matches 'docusign.*'
    • length(body.links) is 0
  4. any of:
    • any of filter(attachments) where all hold:
      • any of:
        • any of ml.logo_detect(.).brands where:
          • .name is 'DocuSign'
        • any of file.explode(.) where all hold:
          • .scan.ocr.raw matches '*DocuSign*'
          • any of:
            • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
              • .name is 'cred_theft'
              • .confidence is not 'low'
            • all of:
              • .scan.ocr.raw matches any of 5 patterns
                • ((re)?view|access|complete(d)?) document(s)?
                • [^d][^o][^cd][^ue]sign(?:\b|ature)
                • important edocs
                • Dokument (überprüfen|prüfen|unterschreiben|geschickt)
                • (wichtig|dringend|sofort)
              • any of ml.nlu_classifier(.scan.ocr.raw).topics where:
                • .name is 'E-Signature'
              • not:
                • strings.count(.scan.ocr.raw, '\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n') > 3
      • not:
        • any of file.explode(.) where any holds:
          • .scan.ocr.raw matches any of 5 patterns
            • *DocuSigned By*
            • *DocuSign Envelope ID*
            • *Certificate Of Completion*
            • *Adobe Sign*
            • *Powered by\nAdobe\nAcrobat Sign*
          • all of:
            • .depth is 0
            • any of:
              • all of:
                • .scan.exiftool.page_count > 10
                • length(.scan.strings.strings) > 8000
              • all of:
                • .scan.exiftool.producer is 'Acrobat Sign'
                • any of .scan.exiftool.fields where all hold:
                  • .key is 'SigningReason'
                  • .value is 'Certified by Adobe Acrobat Sign'
          • all of:
            • any of ml.nlu_classifier(body.current_thread.text).topics where all hold:
              • .name is 'Professional and Career Development'
              • .confidence is 'high'
            • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
              • .name is 'benign'
              • .confidence is not 'low'
    • all of:
      • any of attachments where any holds:
        • .file_type is 'gif'
        • any of beta.parse_exif(.).fields where all hold:
          • .key is 'Warning'
          • .value is 'Truncated PNG image'
      • any of:
        • any of ml.logo_detect(file.message_screenshot()).brands where:
          • .name is 'DocuSign'
        • beta.ocr(file.message_screenshot()).text matches '*DocuSign*'
      • any of:
        • any of ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents where all hold:
          • .name is 'cred_theft'
          • .confidence is not 'low'
        • beta.ocr(file.message_screenshot()).text matches any of 5 patterns
          • ((re)?view|access|complete(d)?) document(s)?
          • [^d][^o][^c][^u]sign
          • important edocs
          • Dokument (überprüfen|prüfen|unterschreiben|geschickt)
          • (wichtig|dringend|sofort)
      • not:
        • beta.ocr(file.message_screenshot()).text matches any of 4 patterns
          • *DocuSigned By*
          • *DocuSign Envelope ID*
          • *Certificate Of Completion*
          • *Adobe Sign*
  5. any of:
    • not:
      • profile.by_sender_email().solicited
    • profile.by_sender_email().prevalence is 'new'
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign
  6. not:
    • profile.by_sender_email().any_messages_benign
  7. not:
    • all of:
      • any of headers.hops where:
        • any of .fields where all hold:
          • .name is 'X-Api-Host'
          • .value ends with 'docusign.net'
      • sender.display_name contains 'via'
  8. not:
    • any of headers.hops where:
      • .received.server.raw matches '.+.docusign.(net|com)'
  9. not:
    • any of headers.references where:
      • . ends with '@camail.docusign.net'

Inspects: attachments[].content_type, attachments[].file_extension, attachments[].file_type, body.current_thread.text, body.links, body.links[].href_url.domain.root_domain, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, headers.hops[].fields[].value, headers.hops[].received.server.raw, headers.references, sender.display_name, type.inbound. Sensors: beta.ocr, beta.parse_exif, file.explode, file.message_screenshot, ml.logo_detect, ml.nlu_classifier, profile.by_sender_email, regex.icontains, regex.imatch, strings.contains, strings.count, strings.ends_with, strings.iends_with, strings.ilike. Reference lists: $file_types_images.

Indicators matched (19)

FieldMatchValue
attachments[].file_typeequalspdf
attachments[].file_extensionequalsics
attachments[].content_typemembertext/calendar
attachments[].content_typememberapplication/ics
ml.logo_detect(filter(attachments)[]).brands[].nameequalsDocuSign
strings.ilikesubstring*DocuSign*
ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].nameequalscred_theft
regex.icontainsregex((re)?view|access|complete(d)?) document(s)?
regex.icontainsregex[^d][^o][^cd][^ue]sign(?:\b|ature)
regex.icontainsregeximportant edocs
regex.icontainsregexDokument (überprüfen|prüfen|unterschreiben|geschickt)
regex.icontainsregex(wichtig|dringend|sofort)
7 more
ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).topics[].nameequalsE-Signature
attachments[].file_typeequalsgif
beta.parse_exif(attachments[]).fields[].keyequalsWarning
beta.parse_exif(attachments[]).fields[].valueequalsTruncated PNG image
ml.logo_detect(file.message_screenshot()).brands[].nameequalsDocuSign
ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents[].nameequalscred_theft
regex.icontainsregex[^d][^o][^c][^u]sign

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(filter(attachments))
      and
        not
          any(file.explode(filter(attachments)))
            or
              and
                or
                  and
                    any(file.explode(filter(attachments)).scan.exiftool.fields)
                      and
                        file.explode(filter(attachments)[])[].scan.exiftool.fields[].key eq "SigningReason"
                        file.explode(filter(attachments)[])[].scan.exiftool.fields[].value eq "Certified by Adobe Acrobat Sign"
                    file.explode(filter(attachments)[])[].scan.exiftool.producer eq "Acrobat Sign"
                  and
                    file.explode(filter(attachments)[])[].scan.exiftool.page_count gt "10"
                    file.explode(filter(attachments)[])[].scan.strings.strings length_compare "8000"
                file.explode(filter(attachments)[])[].depth eq "0"
              and
                any(ml.nlu_classifier(body.current_thread.text).topics)
                  and
                    ml.nlu_classifier(body.current_thread.text).topics.confidence eq "high"
                    ml.nlu_classifier(body.current_thread.text).topics.name eq "Professional and Career Development"
                any(ml.nlu_classifier(file.explode(filter(attachments)).scan.ocr.raw).intents)
                  and
                    ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].confidence ne "low"
                    ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].name eq "benign"
              file.explode(filter(attachments)[])[].scan.ocr.raw match "Adobe Sign"
              file.explode(filter(attachments)[])[].scan.ocr.raw match "Certificate Of Completion"
              file.explode(filter(attachments)[])[].scan.ocr.raw match "DocuSign Envelope ID"
              file.explode(filter(attachments)[])[].scan.ocr.raw match "DocuSigned By"
              file.explode(filter(attachments)[])[].scan.ocr.raw match "Powered by\\nAdobe\\nAcrobat Sign"
        or
          any(file.explode(filter(attachments)))
            and
              or
                and
                  or
                    file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "((re)?view|access|complete(d)?) document(s)?"
                    file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "(wichtig|dringend|sofort)"
                    file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "Dokument (überprüfen|prüfen|unterschreiben|geschickt)"
                    file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "[^d][^o][^cd][^ue]sign(?:\\b|ature)"
                    file.explode(filter(attachments)[])[].scan.ocr.raw regex_match "important edocs"
                  any(ml.nlu_classifier(file.explode(filter(attachments)).scan.ocr.raw).topics)
                    ml.nlu_classifier(file.explode(filter(attachments)).scan.ocr.raw).topics.name eq "E-Signature"
                  not
                    strings.count func_call "strings.count(file.explode(filter(attachments)[])[].scan.ocr.raw, \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\") > 3"
                any(ml.nlu_classifier(file.explode(filter(attachments)).scan.ocr.raw).intents)
                  and
                    ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].confidence ne "low"
                    ml.nlu_classifier(file.explode(filter(attachments)[])[].scan.ocr.raw).intents[].name eq "cred_theft"
              file.explode(filter(attachments)[])[].scan.ocr.raw match "DocuSign"
          any(ml.logo_detect(filter(attachments)).brands)
            ml.logo_detect(filter(attachments)).brands.name eq "DocuSign"
    and
      any(attachments)
        or
          any(beta.parse_exif(attachments).fields)
            and
              beta.parse_exif(attachments[]).fields[].key eq "Warning"
              beta.parse_exif(attachments[]).fields[].value eq "Truncated PNG image"
          attachments.file_type eq "gif"
      or
        any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents)
          and
            ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents.confidence ne "low"
            ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents.name eq "cred_theft"
        beta.ocr(file.message_screenshot()).text regex_match "((re)?view|access|complete(d)?) document(s)?"
        beta.ocr(file.message_screenshot()).text regex_match "(wichtig|dringend|sofort)"
        beta.ocr(file.message_screenshot()).text regex_match "Dokument (überprüfen|prüfen|unterschreiben|geschickt)"
        beta.ocr(file.message_screenshot()).text regex_match "[^d][^o][^c][^u]sign"
        beta.ocr(file.message_screenshot()).text regex_match "important edocs"
      not
        or
          beta.ocr(file.message_screenshot()).text match "Adobe Sign"
          beta.ocr(file.message_screenshot()).text match "Certificate Of Completion"
          beta.ocr(file.message_screenshot()).text match "DocuSign Envelope ID"
          beta.ocr(file.message_screenshot()).text match "DocuSigned By"
      or
        any(ml.logo_detect(file.message_screenshot()).brands)
          ml.logo_detect(file.message_screenshot()).brands.name eq "DocuSign"
        beta.ocr(file.message_screenshot()).text match "DocuSign"
  not
    and
      any(headers.hops)
        any(headers.hops.fields)
          and
            headers.hops.fields[].name eq "X-Api-Host"
            headers.hops.fields[].value ends_with "docusign.net"
      sender.display_name contains "via"
  or
    and
      any(body.links)
        not
          body.links.href_url.domain.root_domain starts_with "docusign."
      body.links length_compare "0"
    body.links length_compare "0"
  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"
    profile.by_sender_email func_call "profile.by_sender_email().prevalence == new"
  or
    and
      attachments length_compare "0"
      attachments length_compare "8"
      filter(attachments, .file_type in $file_types_images) length_compare "0"
    and
      attachments length_compare "0"
       macro "all(attachments)"
  not
    any(headers.hops)
      headers.hops.received.server.raw regex_match ".+.docusign.(net|com)"
  not
    any(headers.references)
      headers.references ends_with "@camail.docusign.net"
  not
    profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
  type.inbound eq "true"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
headers.hopsarray_any(no value, null check)excludes:headers.hops
sender.display_namecontainsviaexcludes:sender.display_name field:"sender.display_name" value:"via"
headers.referencesarray_any(no value, null check)excludes:headers.references

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
beta.ocr(file.message_screenshot()).textregex_match
  • ((re)?view|access|complete(d)?) document(s)?
  • (wichtig|dringend|sofort)
  • Dokument (überprüfen|prüfen|unterschreiben|geschickt)
  • [^d][^o][^c][^u]sign
  • important edocs
field:"beta.ocr(file.message_screenshot()).text" kind:regex_match
beta.ocr(file.message_screenshot()).textwildcard
  • *DocuSign*
field:"beta.ocr(file.message_screenshot()).text" kind:wildcard value:"*DocuSign*"
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of [subject.subject, sender.display_name, body.current_thread.text] where:
    • . matches '(?:\\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 of ml.logo_detect(.).brands where:
        • .name starts with 'Google'
    • any of ml.logo_detect(file.message_screenshot()).brands where:
      • .name starts with '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 of file.explode(.) where all hold:
        • .scan.ocr.raw matches 'scan|camera'
        • .scan.ocr.raw matches '\\bQR\\b|Q\\.R\\.|barcode'
      • any of file.explode(.) where all hold:
        • .scan.qr.type is set
        • .scan.qr.data matches '\\.'
      • all of:
        • beta.parse_exif(file.message_screenshot()).image_height < 2000
        • beta.parse_exif(file.message_screenshot()).image_width < 2000
        • any of beta.scan_qr(file.message_screenshot()).items where all hold:
          • .type is set
          • .data matches '\\.'
  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 of distinct(headers.hops) where:
        • .authentication_results.dmarc matches '*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
  any(attachments)
    and
      or
        and
          any(beta.scan_qr(file.message_screenshot()).items)
            and
              beta.scan_qr(file.message_screenshot()).items.data regex_match "\\."
              beta.scan_qr(file.message_screenshot()).items.type is_not_null
          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"
        any(file.explode(attachments))
          and
            file.explode(attachments[])[].scan.ocr.raw regex_match "\\bQR\\b|Q\\.R\\.|barcode"
            file.explode(attachments[])[].scan.ocr.raw regex_match "scan|camera"
        any(file.explode(attachments))
          and
            file.explode(attachments[])[].scan.qr.data regex_match "\\."
            file.explode(attachments[])[].scan.qr.type is_not_null
      or
        attachments.file_type eq "pdf"
         macro "attachments[].file_type in file_extensions_macros"
         macro "attachments[].file_type in file_types_images"
  or
    any(attachments)
      and
        or
          attachments.file_type eq "pdf"
           macro "attachments[].file_type in file_extensions_macros"
           macro "attachments[].file_type in file_types_images"
        any(ml.logo_detect(attachments).brands)
          ml.logo_detect(attachments).brands.name starts_with "Google"
    any(ml.logo_detect(file.message_screenshot()).brands)
      ml.logo_detect(file.message_screenshot()).brands.name starts_with "Google"
  or
    and
      any(distinct(headers.hops))
        distinct(headers.hops).authentication_results.dmarc ends_with "fail"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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([subject.subject, sender.display_name, body.current_thread.text])
    [subject.subject, sender.display_name, body.current_thread.text] regex_match "(?:\\b2fa\\b|\\bQ.?R\\.?\\s?\\b|MFA|Muti[ -]?Factor|Auth(?:enticat|e|or|ion)?)"
  not
    profile.by_sender func_call "profile.by_sender().any_messages_benign"
  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
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 of ml.logo_detect(.).brands where:
          • .name starts with 'Microsoft'
        • any of file.explode(.) where all hold:
          • .flavors.mime is 'text/xml'
          • any of .scan.strings.strings where:
            • . matches '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 of ml.logo_detect(file.message_screenshot()).brands where:
      • .name starts with 'Microsoft'
    • all of:
      • length(body.current_thread.text) < 300
      • any of filter(attachments) where:
        • any of file.explode(.) where:
          • .scan.ocr.raw matches '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 of file.explode(.) where all hold:
        • .scan.ocr.raw matches 'scan|camera'
        • .scan.ocr.raw matches '\\bQR\\b|Q\\.R\\.|barcode'
      • any of file.explode(.) where all hold:
        • .scan.qr.type is 'url'
        • any of recipients.to where all hold:
          • any of:
            • strings.icontains(.scan.qr.data)
            • any of recipients.to where:
              • strings.icontains(sender.display_name)
            • any of recipients.to where:
              • strings.icontains(body.current_thread.text)
            • body.current_thread.text is missing
            • body.current_thread.text is ''
            • subject.subject matches '(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)'
          • any of:
            • .email.domain.valid
            • .display_name contains '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
  any(attachments)
    and
      or
        any(file.explode(attachments))
          and
            any(recipients.to)
              and
                or
                  any(recipients.to)
                    strings.icontains func_call "strings.icontains(body.current_thread.text)"
                  any(recipients.to)
                    strings.icontains func_call "strings.icontains(sender.display_name)"
                  body.current_thread.text eq ""
                  body.current_thread.text is_null
                  strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.qr.data)"
                  subject.subject regex_match "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)"
                or
                  recipients.to.display_name contains "undisclosed"
                  recipients.to.email.domain.valid eq "true"
            file.explode(attachments[])[].scan.qr.type eq "url"
        any(file.explode(attachments))
          and
            file.explode(attachments[])[].scan.ocr.raw regex_match "\\bQR\\b|Q\\.R\\.|barcode"
            file.explode(attachments[])[].scan.ocr.raw regex_match "scan|camera"
      or
        attachments.file_type eq "pdf"
         macro "attachments[].file_type in file_extensions_macros"
         macro "attachments[].file_type in file_types_images"
  or
    any(attachments)
      and
        or
          any(file.explode(attachments))
            and
              any(file.explode(attachments).scan.strings.strings)
                file.explode(attachments).scan.strings.strings regex_match "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))"
              file.explode(attachments[])[].flavors.mime eq "text/xml"
          any(ml.logo_detect(attachments).brands)
            ml.logo_detect(attachments).brands.name starts_with "Microsoft"
        or
          attachments.file_type eq "pdf"
           macro "attachments[].file_type in file_extensions_macros"
           macro "attachments[].file_type in file_types_images"
    and
      any(filter(attachments))
        any(file.explode(filter(attachments)))
          file.explode(filter(attachments)).scan.ocr.raw regex_match "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))"
      body.current_thread.text length_compare "300"
    any(ml.logo_detect(file.message_screenshot()).brands)
      ml.logo_detect(file.message_screenshot()).brands.name starts_with "Microsoft"
  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"
  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
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:
    • length(attachments) > 0
    • length(attachments) < 3
  4. any of:
    • any of:
      • all of:
        • length(body.current_thread.text) ≥ 0
        • 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)
          • 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 of file.explode(.) where any holds:
      • any of .scan.exiftool.fields where:
        • .value is 'Truncated PNG image'
      • all of:
        • any of ml.logo_detect(.).brands where:
          • .name is set
        • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
          • .name is 'cred_theft'
          • .confidence is '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)"
        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 "all(attachments)"

Indicators

These rows show field, operator, and value matches.

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 of ml.nlu_classifier(file.parse_eml(.).body.current_thread.text).intents where all hold:
        • .name is 'cred_theft'
        • .confidence is 'high'
      • any of file.parse_eml(.).attachments where:
        • any of ml.nlu_classifier(beta.ocr(.).text).intents where all hold:
          • .name is 'cred_theft'
          • .confidence is 'high'
    • not:
      • file.parse_eml(.).sender.email.local_part matches any of 3 patterns
        • *postmaster*
        • *mailer-daemon*
        • *administrator*
    • not:
      • any of file.parse_eml(.).attachments where:
        • .content_type in ('message/delivery-status', 'message/feedback-report')
    • not:
      • all of:
        • length(file.parse_eml(.).attachments) is 0
        • file.parse_eml(.).body.current_thread.text contains '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) is 1
        • any of file.parse_eml(.).headers.hops[0].fields where:
          • .name is 'X-MC-System'
        • any of file.parse_eml(.).headers.hops[0].fields where all hold:
          • .name is 'Content-Type'
          • .value contains '; 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) is 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
          any(file.parse_eml(attachments).headers.hops[0].fields)
            and
              file.parse_eml(attachments[]).headers.hops[0].fields[].name eq "Content-Type"
              file.parse_eml(attachments[]).headers.hops[0].fields[].value contains "; boundary=\"MCBoundary=_"
          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"
          any(file.parse_eml(attachments).headers.hops[0].fields)
            file.parse_eml(attachments).headers.hops[0].fields.name eq "X-MC-System"
          file.parse_eml(attachments[]).headers.hops length_compare "1"
      or
        any(file.parse_eml(attachments).attachments)
          any(ml.nlu_classifier(beta.ocr(file.parse_eml(attachments).attachments).text).intents)
            and
              ml.nlu_classifier(beta.ocr(file.parse_eml(attachments[]).attachments[]).text).intents[].confidence eq "high"
              ml.nlu_classifier(beta.ocr(file.parse_eml(attachments[]).attachments[]).text).intents[].name eq "cred_theft"
        any(ml.nlu_classifier(file.parse_eml(attachments).body.current_thread.text).intents)
          and
            ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].confidence eq "high"
            ml.nlu_classifier(file.parse_eml(attachments[]).body.current_thread.text).intents[].name eq "cred_theft"
      not
        any(file.parse_eml(attachments).attachments)
          file.parse_eml(attachments).attachments.content_type in ["message/delivery-status", "message/feedback-report"]
      not
        and
          file.parse_eml(attachments[]).attachments length_compare "0"
          file.parse_eml(attachments[]).body.current_thread.text contains "Your attachments are currently being scanned by Safe Attachments"
      not
        or
          file.parse_eml(attachments[]).sender.email.local_part match "administrator"
          file.parse_eml(attachments[]).sender.email.local_part match "mailer-daemon"
          file.parse_eml(attachments[]).sender.email.local_part match "postmaster"
      or
        attachments.content_type eq "message/rfc822"
        attachments.file_extension eq "eml"
  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"
       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"

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:)"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where:
      • any of .scan.yara.matches where:
        • .name is 'aes_encryption_keywords'
  3. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • any of distinct(headers.hops) where:
        • .authentication_results.dmarc matches '*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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.yara.matches)
          file.explode(attachments).scan.yara.matches.name eq "aes_encryption_keywords"
      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"]
  or
    and
      any(distinct(headers.hops))
        distinct(headers.hops).authentication_results.dmarc ends_with "fail"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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
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)) ≤ 1
    • strings.contains(.file_name)
  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 of file.explode(.) where any holds:
      • all of:
        • all of:
          • .depth is 1
          • .flavors.mime is 'image/jpeg'
        • all of:
          • .scan.exiftool.image_height is 148
          • .scan.exiftool.image_width is 148
          • .scan.qr.data matches '(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})'
      • all of:
        • any of .scan.strings.strings where:
          • . matches 'Amount(?:\\s*\\w+){0,3}\\s*:?\\s*(?:USD\\s*)?(?:\\$\\s?\\d+|\\d+\\s?\\$?)'
        • any of .scan.strings.strings where:
          • . matches '(\\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
      any(file.explode(attachments))
        or
          and
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings regex_match "(\\bBITCOIN\\b|\\bBTC\\b|\\bLTC\\b|Wallet)"
            any(file.explode(attachments).scan.strings.strings)
              file.explode(attachments).scan.strings.strings regex_match "Amount(?:\\s*\\w+){0,3}\\s*:?\\s*(?:USD\\s*)?(?:\\$\\s?\\d+|\\d+\\s?\\$?)"
          and
            file.explode(attachments[])[].depth eq "1"
            file.explode(attachments[])[].flavors.mime eq "image/jpeg"
            file.explode(attachments[])[].scan.exiftool.image_height eq "148"
            file.explode(attachments[])[].scan.exiftool.image_width eq "148"
            file.explode(attachments[])[].scan.qr.data regex_match "(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})"
      attachments.file_type eq "pdf"
  any(attachments)
    or
      strings.contains func_call "strings.contains(attachments[].file_name)"
      strings.ilevenshtein func_call "strings.ilevenshtein(strings.concat(subject.subject, '.', attachments[].file_extension)) <= 1"
  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"
  type.inbound eq "true"
   macro "sender.email.domain.root_domain in free_email_providers"

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
subject.subjectcross_field_compare
  • body.current_thread.text transforms: op:eq
field:"subject.subject" kind:cross_field_compare value:"body.current_thread.text"
type.inboundeq
  • true transforms: boolean
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 of ml.nlu_classifier(body.current_thread.text).intents where:
        • .name is not '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 of filter(...) where any holds:
        • all of:
          • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
            • .name is 'extortion'
            • .confidence is 'high'
          • any of ml.nlu_classifier(.scan.ocr.raw).entities where:
            • .name is 'financial'
        • at least 3 of:
          • .scan.ocr.raw matches '((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))'
          • .scan.ocr.raw matches 'porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off'
          • .scan.ocr.raw matches 'pervert|perversion|masturbat'
          • .scan.ocr.raw matches any of 2 patterns
            • \d\d hours
            • (?:one|two|three) days?
          • .scan.ocr.raw matches 'permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)'
          • .scan.ocr.raw matches 'sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)'
          • all of:
            • .scan.ocr.raw matches '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)
          • all of:
            • .scan.ocr.raw contains 'contact the police'
            • .scan.ocr.raw matches '(\\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'
          • .scan.ocr.raw matches 'bc1q.{0,50}\\b'
    • all of:
      • .file_extension in ('txt')
      • any of:
        • all of:
          • any of ml.nlu_classifier(file.parse_text(.).text).intents where all hold:
            • .name is 'extortion'
            • .confidence is 'high'
          • any of ml.nlu_classifier(file.parse_text(.).text).entities where:
            • .name is 'financial'
        • at least 3 of:
          • file.parse_text(.).text matches '((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))'
          • file.parse_text(.).text matches 'porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off'
          • file.parse_text(.).text matches 'pervert|perversion|masturbat'
          • file.parse_text(.).text matches any of 2 patterns
            • \d\d hours
            • (?:one|two|three) days?
          • file.parse_text(.).text matches 'permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)'
          • file.parse_text(.).text matches 'sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)'
          • all of:
            • file.parse_text(.).text matches '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)
          • all of:
            • file.parse_text(.).text contains 'contact the police'
            • file.parse_text(.).text matches '(\\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'
          • file.parse_text(.).text matches '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
        any(filter(...))
          or
            and
              not
                any(body.links)
                  and
                    or
                      and
                        body.links.href_url.domain.root_domain eq "mimecastprotect.com"
                        strings.icontains func_call "strings.icontains(body.links[].href_url.query_params)"
                      body.links.href_url.path contains "unsubscribe"
                    body.links.display_text contains "unsubscribe"
              filter(...).scan.ocr.raw regex_match "bitcoin|\\bbtc\\b|blockchain"
            and
              any(ml.nlu_classifier(filter(...).scan.ocr.raw).intents)
                and
                  ml.nlu_classifier(filter(...)[].scan.ocr.raw).intents[].confidence eq "high"
                  ml.nlu_classifier(filter(...)[].scan.ocr.raw).intents[].name eq "extortion"
              any(ml.nlu_classifier(filter(...).scan.ocr.raw).entities)
                ml.nlu_classifier(filter(...).scan.ocr.raw).entities.name eq "financial"
            and
              filter(...).scan.ocr.raw contains "contact the police"
              filter(...).scan.ocr.raw regex_match "(\\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"
            filter(...).scan.ocr.raw regex_match "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))"
            filter(...).scan.ocr.raw regex_match "(?:one|two|three) days?"
            filter(...).scan.ocr.raw regex_match "\\d\\d hours"
            filter(...).scan.ocr.raw regex_match "bc1q.{0,50}\\b"
            filter(...).scan.ocr.raw regex_match "permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)"
            filter(...).scan.ocr.raw regex_match "pervert|perversion|masturbat"
            filter(...).scan.ocr.raw regex_match "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off"
            filter(...).scan.ocr.raw regex_match "sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)"
        or
          attachments.file_type eq "pdf"
           macro "attachments[].file_type in file_types_images"
      and
        or
          and
            not
              any(body.links)
                and
                  or
                    and
                      body.links.href_url.domain.root_domain eq "mimecastprotect.com"
                      strings.icontains func_call "strings.icontains(body.links[].href_url.query_params)"
                    body.links.href_url.path contains "unsubscribe"
                  body.links.display_text contains "unsubscribe"
            file.parse_text(attachments[]).text regex_match "bitcoin|\\bbtc\\b|blockchain"
          and
            any(ml.nlu_classifier(file.parse_text(attachments).text).intents)
              and
                ml.nlu_classifier(file.parse_text(attachments[]).text).intents[].confidence eq "high"
                ml.nlu_classifier(file.parse_text(attachments[]).text).intents[].name eq "extortion"
            any(ml.nlu_classifier(file.parse_text(attachments).text).entities)
              ml.nlu_classifier(file.parse_text(attachments).text).entities.name eq "financial"
          and
            file.parse_text(attachments[]).text contains "contact the police"
            file.parse_text(attachments[]).text regex_match "(\\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"
          file.parse_text(attachments[]).text regex_match "((spy|mal)ware|trojan|remote control|infiltrat(ed|ion))"
          file.parse_text(attachments[]).text regex_match "(?:one|two|three) days?"
          file.parse_text(attachments[]).text regex_match "\\d\\d hours"
          file.parse_text(attachments[]).text regex_match "bc1q.{0,50}\\b"
          file.parse_text(attachments[]).text regex_match "permanently delete|destroy (?:\\w+\\s*){0,4} (?:data|evidence|videos?)"
          file.parse_text(attachments[]).text regex_match "pervert|perversion|masturbat"
          file.parse_text(attachments[]).text regex_match "porn|adult (web)?site|webcam|masturbating|jerking off|pleasuring yourself|getting off"
          file.parse_text(attachments[]).text regex_match "sen[dt]\\s*(?:\\w+\\s*){0,2}\\s*to\\s*(?:\\w+\\s*){0,3}\\s*.{0,10}(contacts|media|family|friends)"
        attachments.file_extension eq "txt"
  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
      any(ml.nlu_classifier(body.current_thread.text).intents)
        ml.nlu_classifier(body.current_thread.text).intents.name ne "benign"
      ml.nlu_classifier(body.current_thread.text).intents length_compare "0"
    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
field:"type.inbound" kind:eq value:"true"

Free subdomain link with credential theft indicators

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

Message contains a suspicious Recipients pattern, a link that uses a free subdomain provider, and has credential theft language on the linked page.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree subdomain host

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.links
  • recipients
  • recipients.to
  • sender.email
  • type

Rule body

type.inbound
and any(body.links,
        .href_url.domain.root_domain in $free_subdomain_hosts
        and .href_url.domain.subdomain is not null
        and .href_url.domain.subdomain != "www"
)
and (
  (
    (
      length(recipients.to) == 0
      or all(recipients.to, .display_name == "Undisclosed recipients")
    )
    and length(recipients.cc) == 0
    and length(recipients.bcc) == 0
  )
  or (
    length(recipients.to) == 1
    and any(recipients.to, .email.email == sender.email.email)
  )
  or (
    length(recipients.to) == 0
    and length(recipients.cc) == 0
    and length(recipients.bcc) > 0
  )
)
and any(body.links,
        any(file.explode(ml.link_analysis(.).screenshot),
            any(ml.nlu_classifier(.scan.ocr.raw).intents,
                .name == "cred_theft" and .confidence != "low"
            )
        )
)

Detection logic

Scope: inbound message.

Message contains a suspicious Recipients pattern, a link that uses a free subdomain provider, and has credential theft language on the linked page.

  1. inbound message
  2. any of body.links where all hold:
    • .href_url.domain.root_domain in $free_subdomain_hosts
    • .href_url.domain.subdomain is set
    • .href_url.domain.subdomain is not 'www'
  3. any of:
    • all of:
      • any of:
        • length(recipients.to) is 0
        • all of recipients.to where:
          • .display_name is 'Undisclosed recipients'
      • length(recipients.cc) is 0
      • length(recipients.bcc) is 0
    • all of:
      • length(recipients.to) is 1
      • any of recipients.to where:
        • .email.email is sender.email.email
    • all of:
      • length(recipients.to) is 0
      • length(recipients.cc) is 0
      • length(recipients.bcc) > 0
  4. any of body.links where:
    • any of file.explode(...) where:
      • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
        • .name is 'cred_theft'
        • .confidence is not 'low'

Inspects: body.links, body.links[].href_url.domain.root_domain, body.links[].href_url.domain.subdomain, recipients.bcc, recipients.cc, recipients.to, recipients.to[].display_name, recipients.to[].email.email, sender.email.email, type.inbound. Sensors: file.explode, ml.link_analysis, ml.nlu_classifier. Reference lists: $free_subdomain_hosts.

Indicators matched (2)

FieldMatchValue
recipients.to[].display_nameequalsUndisclosed recipients
ml.nlu_classifier(file.explode(...)[].scan.ocr.raw).intents[].nameequalscred_theft

Stages and Predicates

Stage 1: mql_rule

and
  any(body.links)
    any(file.explode(...))
      any(ml.nlu_classifier(file.explode(...).scan.ocr.raw).intents)
        and
          ml.nlu_classifier(file.explode(...)[].scan.ocr.raw).intents[].confidence ne "low"
          ml.nlu_classifier(file.explode(...)[].scan.ocr.raw).intents[].name eq "cred_theft"
  or
    and
      or
        recipients.to length_compare "0"
         macro "all(recipients.to)"
      recipients.bcc length_compare "0"
      recipients.cc length_compare "0"
    and
      any(recipients.to)
        recipients.to.email.email cross_field_compare "sender.email.email"
      recipients.to length_compare "1"
    and
      recipients.bcc length_compare "0"
      recipients.cc length_compare "0"
      recipients.to length_compare "0"
  any(body.links)
    and
      body.links.href_url.domain.subdomain is_not_null
      body.links.href_url.domain.subdomain ne "www"
       macro "body.links[].href_url.domain.root_domain in free_subdomain_hosts"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of file.explode(.) where all hold:
        • .size < 10000
        • length(.scan.strings.strings) < 20
        • any of recipients.to where all hold:
          • any of .scan.strings.strings where:
            • strings.icontains(.)
          • .email.domain.valid
    • any of attachments where all hold:
      • .file_extension in $file_extensions_common_archives
      • any of file.explode(.) where all hold:
        • any of:
          • .file_extension in ('html', 'htm', 'shtml', 'dhtml')
          • .file_type is 'html'
          • .content_type is 'text/html'
        • .size < 10000
        • length(.scan.strings.strings) < 20
        • any of recipients.to where all hold:
          • any of .scan.strings.strings where:
            • strings.icontains(.)
          • .email.domain.valid
  3. not:
    • any of attachments where:
      • any of file.parse_eml(.).attachments where:
        • .content_type is '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)
  7. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • coalesce(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, 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
        any(file.explode(attachments))
          and
            any(recipients.to)
              and
                any(file.explode(attachments).scan.strings.strings)
                  strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.strings.strings[])"
                recipients.to.email.domain.valid eq "true"
            or
              attachments.content_type eq "text/html"
              attachments.file_type eq "html"
              file.explode(attachments[])[].file_extension in ["dhtml", "htm", "html", "shtml"]
            file.explode(attachments[])[].scan.strings.strings length_compare "20"
            file.explode(attachments[])[].size lt "10000"
         macro "attachments[].file_extension in file_extensions_common_archives"
    any(attachments)
      and
        any(file.explode(attachments))
          and
            any(recipients.to)
              and
                any(file.explode(attachments).scan.strings.strings)
                  strings.icontains func_call "strings.icontains(file.explode(attachments[])[].scan.strings.strings[])"
                recipients.to.email.domain.valid eq "true"
            file.explode(attachments[])[].scan.strings.strings length_compare "20"
            file.explode(attachments[])[].size lt "10000"
        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"
  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"
  or
    and
      not
        coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       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
        coalesce func_call "coalesce(headers.auth_summary.dmarc.pass)"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    any(attachments)
      any(file.parse_eml(attachments).attachments)
        file.parse_eml(attachments).attachments.content_type eq "message/delivery-status"
  not
    any(attachments)
      attachments.content_type in ["message/delivery-status", "text/calendar"]
  type.inbound eq "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"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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 of [body.html.display_text, body.current_thread.text, body.plain.raw] where all hold:
    • length(.) < 2500
    • any of:
      • . contains 'Scanned by Gmail'
      • all of:
        • all of:
          • regex.icount(., '\\.pdf|\\.(doc|xls|ppt)x?') > 0
          • regex.icount(., '\\.pdf|\\.(doc|xls|ppt)x?') < 3
        • any of body.links where:
          • .display_text matches 'd[ao0]wnl[ao0]{2}d all'
        • length(body.links) < 4
    • . matches '[KM]b\\b'
  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
  any([body.html.display_text, body.current_thread.text, body.plain.raw])
    and
      or
        and
          any(body.links)
            body.links.display_text regex_match "d[ao0]wnl[ao0]{2}d all"
          body.links length_compare "4"
          regex.icount func_call "regex.icount([body.html.display_text, body.current_thread.text, body.plain.raw][], \"\\.pdf|\\.(doc|xls|ppt)x?\") < 3"
          regex.icount func_call "regex.icount([body.html.display_text, body.current_thread.text, body.plain.raw][], \"\\.pdf|\\.(doc|xls|ppt)x?\") > 0"
        [body.html.display_text, body.current_thread.text, body.plain.raw] contains "Scanned by Gmail"
      [body.html.display_text, body.current_thread.text, body.plain.raw] length_compare "2500"
      [body.html.display_text, body.current_thread.text, body.plain.raw] regex_match "[KM]b\\b"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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)
     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
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 of file.explode(.) where:
      • .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
      any(file.explode(attachments))
         macro "file.explode(attachments[])[].scan.hash.sha256 in abuse_ch_malwarebazaar_sha256_trusted_reporters"
       macro "attachments[].file_extension in file_extensions_common_archives"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • any of:
        • .file_extension is 'ics'
        • .flavors.mime is 'text/calendar'
      • any of .scan.ics.calendars where:
        • any of .components where all hold:
          • .uid is missing
          • .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
      any(file.explode(attachments))
        and
          any(file.explode(attachments).scan.ics.calendars)
            any(file.explode(attachments).scan.ics.calendars.components)
              and
                file.explode(attachments[])[].scan.ics.calendars[].components[].type in ["VEVENT", "VFREEBUSY", "VJOURNAL", "VTODO"]
                file.explode(attachments[])[].scan.ics.calendars[].components[].uid is_null
          or
            file.explode(attachments[])[].file_extension eq "ics"
            file.explode(attachments[])[].flavors.mime eq "text/calendar"
      or
        attachments.content_type eq "text/calendar"
        attachments.file_extension eq "ics"
         macro "attachments[].file_extension in file_extensions_common_archives"
  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
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 of file.explode(.) where:
      • any of .scan.pdf.urls where all hold:
        • .query_params starts with 'q=%68%74%74%70'
        • any of:
          • .query_params contains '.%70%68%70'
          • .query_params contains '%2e%7a%69%70'
        • .domain.root_domain is '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
      any(file.explode(attachments))
        any(file.explode(attachments).scan.pdf.urls)
          and
            or
              file.explode(attachments[])[].scan.pdf.urls[].query_params contains "%2e%7a%69%70"
              file.explode(attachments[])[].scan.pdf.urls[].query_params contains ".%70%68%70"
            file.explode(attachments[])[].scan.pdf.urls[].domain.root_domain eq "google.ae"
            file.explode(attachments[])[].scan.pdf.urls[].query_params starts_with "q=%68%74%74%70"
      attachments.file_type eq "pdf"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
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 of file.explode(.) where all hold:
      • all of:
        • length(.scan.url.urls) > 0
        • length(.scan.url.urls) < 20
      • length(distinct(.scan.url.urls, .domain.root_domain)) < 10
      • all of .scan.url.urls where:
        • .domain.root_domain is not 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 of $suspicious_subjects where:
      • 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 of file.explode(.) where any holds:
        • any of .scan.url.urls where:
          • .url ends with '.exe'
        • any of ml.nlu_classifier(.scan.ocr.raw).intents where:
          • .name is '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 of file.explode(.) where:
      • any of .scan.url.urls where all hold:
        • any of:
          • ml.link_analysis(., mode='aggressive').final_dom.display_text contains 'cloudflare'
          • all of:
            • ml.link_analysis(., mode='aggressive').final_dom.raw contains 'https://challenges.cloudflare.com/turnstile/'
            • length(ml.link_analysis(., mode='aggressive').final_dom.display_text) < 200
        • none of:
          • all of:
            • ml.link_analysis(., mode='aggressive').final_dom.display_text matches '*error code*'
            • any of ml.link_analysis(., mode='aggressive').final_dom.links where:
              • .href_url.query_params contains 'utm_source=errorcode'
          • ml.link_analysis(., mode='aggressive').final_dom.display_text matches 'cookie.{0,50}Cloudflare'
          • ml.link_analysis(.).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
  any(attachments)
    and
      any(file.explode(attachments))
        any(file.explode(attachments).scan.url.urls)
          and
            not
              or
                and
                  any(ml.link_analysis(file.explode(attachments).scan.url.urls, mode='aggressive').final_dom.links)
                    ml.link_analysis(file.explode(attachments).scan.url.urls, mode='aggressive').final_dom.links.href_url.query_params contains "utm_source=errorcode"
                  ml.link_analysis(file.explode(attachments[])[].scan.url.urls[], mode='aggressive').final_dom.display_text match "error code"
                ml.link_analysis func_call "ml.link_analysis(file.explode(attachments[])[].scan.url.urls[]).effective_url.domain.root_domain in (marketbeat.com)"
                ml.link_analysis(file.explode(attachments[])[].scan.url.urls[], mode='aggressive').final_dom.display_text regex_match "cookie.{0,50}Cloudflare"
            or
              and
                ml.link_analysis(file.explode(attachments[])[].scan.url.urls[], mode='aggressive').final_dom.display_text length_compare "200"
                ml.link_analysis(file.explode(attachments[])[].scan.url.urls[], mode='aggressive').final_dom.raw contains "https://challenges.cloudflare.com/turnstile/"
              ml.link_analysis(file.explode(attachments[])[].scan.url.urls[], mode='aggressive').final_dom.display_text contains "cloudflare"
      or
        attachments.content_type eq "application/pdf"
        attachments.file_extension eq "pdf"
        attachments.file_type in ["doc", "docx", "pdf", "xls", "xlsx"]
         macro "attachments[].file_extension in file_extensions_macros"
  or
    any(attachments)
      and
        any(file.explode(attachments))
          or
            any(file.explode(attachments).scan.url.urls)
              file.explode(attachments).scan.url.urls.url ends_with ".exe"
            any(ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents)
              ml.nlu_classifier(file.explode(attachments).scan.ocr.raw).intents.name eq "cred_theft"
        or
          attachments.content_type eq "application/pdf"
          attachments.file_extension eq "pdf"
          attachments.file_type in ["doc", "docx", "pdf", "xls", "xlsx"]
           macro "attachments[].file_extension in file_extensions_macros"
    any($suspicious_subjects)
      strings.icontains func_call "strings.icontains(subject.subject)"
    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"
  any(attachments)
    and
      any(file.explode(attachments))
        and
          distinct(file.explode(attachments[])[].scan.url.urls, file.explode(attachments[])[].domain.root_domain) length_compare "10"
          file.explode(attachments[])[].scan.url.urls length_compare "0"
          file.explode(attachments[])[].scan.url.urls length_compare "20"
           macro "all(file.explode(attachments[])[].scan.url.urls)"
      or
        attachments.content_type eq "application/pdf"
        attachments.file_extension eq "pdf"
        attachments.file_type in ["doc", "docx", "pdf", "xls", "xlsx"]
         macro "attachments[].file_extension in file_extensions_macros"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     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"

Exclusions

The rule actively suppresses these predicates.

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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
sender.display_nameregex_match
  • /bHR/b
  • Admin
  • Administrator
  • Alert
  • Assistant
  • Benefits
  • Billing
  • Bonus
  • CEO
  • CFO
  • CIO
  • CTO
  • Chairman
  • Claim
  • Confirm
  • Critical
  • Customer Service
  • Deal
  • Director
  • Discount
  • Exclusive
  • Executive
  • Fax
  • Free
  • Gift
  • Helpdesk
  • Human Resources
  • Immediate
  • Important
  • Info
  • Information
  • Invoice
  • Legal
  • Lottery
  • Management
  • Manager
  • Member Services
  • Notification
  • Offer
  • Operations
  • +33 more values (see full rule source)
field:"sender.display_name" kind:regex_match
subject.subjectregex_match
  • 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
  • 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 v[il]o[li]at
  • account.*de-?activat
  • account.*locked
  • account.*re-verification
  • account.*security
  • account.*suspension
  • account.has.been
  • account.has.expired
  • account.will.be.blocked
  • action.*required
  • 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
  • +84 more values (see full rule source)
field:"subject.subject" kind:regex_match
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

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"
         macro "attachments[].file_extension in file_extensions_macros"
      ml.macro_classifier func_call "ml.macro_classifier(attachments[]).confidence in (high)"
      ml.macro_classifier func_call "ml.macro_classifier(attachments[]).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
field:"type.inbound" kind:eq value:"true"