Detection rules › Sublime MQL

Sublime MQL rules: urlhaus

URLhaus: Malicious domain in message body or pdf attachment (trusted reporters)

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

Detects URLhaus domains submitted by trusted reporters in message bodies or pdf attachments

Threat Classification

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

CategoryValues
Attack typesCredential Phishing, Malware/Ransomware
Tactics and techniquesPDF

Telemetry Coverage

PlatformRecord / event type
SublimeInbound email message

Message Attributes

  • attachments
  • body
  • body.links
  • type

Rule Body

type.inbound
and (
  any(body.links,
      // filter potentially known good domains
      // prevents FPs on entries such as drive[.]google[.]com, or
      // other accidental pushes to the List
      .href_url.domain.domain not in $free_file_hosts
      and .href_url.domain.root_domain not in $free_file_hosts
      and .href_url.domain.domain not in $tranco_1m
      and .href_url.domain.domain not in $umbrella_1m

      // this ensures we don't flag on legit FQDNs that
      // aren't in the Tranco 1M, but their root domains are
      // eg: support[.]google[.]com
      and .href_url.domain.root_domain not in $tranco_1m
      and .href_url.domain.root_domain not in $umbrella_1m
      and .href_url.domain.root_domain not in $free_subdomain_hosts
      and .href_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters
  )
  or any(attachments,
         .file_type == "pdf"
         and any(file.explode(.),
                 any(.scan.pdf.urls,
                     // filter potentially known good domains
                     // prevents FPs on entries such as drive[.]google[.]com, or
                     // other accidental pushes to the List
                     .domain.domain not in $free_file_hosts
                     and .domain.root_domain not in $free_file_hosts
                     and .domain.domain not in $free_subdomain_hosts
                     and .domain.domain not in $tranco_1m
                     and .domain.domain not in $umbrella_1m

                     // this ensures we don't flag on legit FQDNs that
                     // aren't in the Tranco 1M, but their root domains are
                     // eg: support[.]google[.]com
                     and .domain.root_domain not in $tranco_1m
                     and .domain.root_domain not in $umbrella_1m
                     and .domain.domain in $abuse_ch_urlhaus_domains_trusted_reporters
                 )
         )
  )
)

Detection Logic

Scope: inbound message.

Detects URLhaus domains submitted by trusted reporters in message bodies or pdf attachments

  1. inbound message
  2. any of:
    • any of body.links where all hold:
      • .href_url.domain.domain not in $free_file_hosts
      • .href_url.domain.root_domain not in $free_file_hosts
      • .href_url.domain.domain not in $tranco_1m
      • .href_url.domain.domain not in $umbrella_1m
      • .href_url.domain.root_domain not in $tranco_1m
      • .href_url.domain.root_domain not in $umbrella_1m
      • .href_url.domain.root_domain not in $free_subdomain_hosts
      • .href_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters
    • any of attachments where all hold:
      • .file_type is 'pdf'
      • any(file.explode(.), any(.scan.pdf.urls, // filter potentially known good domains // prevents FPs on entries such as drive[.]google[.]com, or // other accidental pushes to the List .domain.domain not in $free_file_hosts and .domain.root_domain not in $free_file_hosts and .domain.domain not in $free_subdomain_hosts and .domain.domain not in $tranco_1m and .domain.domain not in $umbrella_1m // this ensures we don't flag on legit FQDNs that // aren't in the Tranco 1M, but their root domains are // eg: support[.]google[.]com and .domain.root_domain not in $tranco_1m and .domain.root_domain not in $umbrella_1m and .domain.domain in $abuse_ch_urlhaus_domains_trusted_reporters ) )

Inspects: attachments[].file_type, body.links, body.links[].href_url.domain.domain, body.links[].href_url.domain.root_domain, type.inbound. Sensors: file.explode. Reference lists: $abuse_ch_urlhaus_domains_trusted_reporters, $free_file_hosts, $free_subdomain_hosts, $tranco_1m, $umbrella_1m.

Indicators Matched (1)

FieldMatchValue
attachments[].file_typeequalspdf

Stages and Predicates

Stage 1: mql_rule

and
  or
    any(attachments)
      and
        attachments.file_type eq "pdf"
         macro "any(file.explode(.),\n                 any(.scan.pdf.urls,\n                     // filter potentially known good domains\n                     // prevents FPs on entries such as drive[.]google[.]com, or\n                     // other accidental pushes to the List\n                     .domain.domain not in $free_file_hosts\n                     and .domain.root_domain not in $free_file_hosts\n                     and .domain.domain not in $free_subdomain_hosts\n                     and .domain.domain not in $tranco_1m\n                     and .domain.domain not in $umbrella_1m\n\n                     // this ensures we don't flag on legit FQDNs that\n                     // aren't in the Tranco 1M, but their root domains are\n                     // eg: support[.]google[.]com\n                     and .domain.root_domain not in $tranco_1m\n                     and .domain.root_domain not in $umbrella_1m\n                     and .domain.domain in $abuse_ch_urlhaus_domains_trusted_reporters\n                 )\n         )"
    any(body.links)
      and
        body.links.href_url.domain.domain macro "body.links[].href_url.domain.domain not in free_file_hosts"
        body.links.href_url.domain.domain macro "body.links[].href_url.domain.domain not in tranco_1m"
        body.links.href_url.domain.domain macro "body.links[].href_url.domain.domain not in umbrella_1m"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain in abuse_ch_urlhaus_domains_trusted_reporters"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain not in free_file_hosts"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain not in free_subdomain_hosts"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain not in tranco_1m"
        body.links.href_url.domain.root_domain macro "body.links[].href_url.domain.root_domain not in umbrella_1m"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

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

Back to all Sublime MQL rules