Detection rules › Sublime MQL

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

Event coverage

Rule body MQL

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

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
strings.likesubstring*postmaster*
strings.likesubstring*mailer-daemon*
strings.likesubstring*administrator*
regex.icontainsregex^(undeliverable|read:)
attachments[].content_typeequalsmessage/delivery-status