Detection rules › Sublime MQL

Impersonation: Suspected supplier impersonation with suspicious content

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

This rule detects supplier impersonation by checking for: similar linked domains to the sender, non-freemail senders using freemail infrastructure, sender domains less than 90 days old, unsolicited communication or no prior interaction with the reply-to address, and a suspicious body.

Threat classification

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

CategoryValues
Attack typesBEC/Fraud
Tactics and techniquesEvasion, Free email provider, Lookalike domain, Social engineering

Event coverage

Rule body MQL

type.inbound

// a linked domain is similar but not the same as the sender domain
and any(body.links,
        length(.href_url.domain.sld) > 3
        and 0 < strings.levenshtein(.href_url.domain.sld,
                                    sender.email.domain.sld
        ) <= 2
        and not sender.email.domain.root_domain == "onmicrosoft.com"

        // looking for lookalike domains above, typically the registrars won't match
        and network.whois(sender.email.domain).registrar_name != network.whois(.href_url.domain
        ).registrar_name

        // and one of the domains is less than 30 days old
        and (
          network.whois(sender.email.domain).days_old < 30
          or network.whois(.href_url.domain).days_old < 30
        )
)
// the sender is not a freemail, but the message or the in-reply-to indicates it traversed a freemail infrastructure, likely an auto forwarding rule. Or the sender or reply-to domain is new
and (
  sender.email.domain.root_domain not in $free_email_providers
  and (
    any(headers.references,
        any($free_email_providers, strings.contains(.., .))
        and not strings.ends_with(., "outlook.com")
    )
    or (
      any($free_email_providers,
          strings.contains(headers.in_reply_to, .)
          and not strings.ends_with(headers.in_reply_to, 'outlook.com')
      )
      // with the suspicious traversal tolerate 90 days
      and network.whois(sender.email.domain).days_old < 90
    )
    or any(headers.reply_to,
           network.whois(.email.domain).days_old < 30
           and .email.email != sender.email.email
    )
  )
)

//  not solicited, nor ever communicated with
and (
  not profile.by_sender_domain().solicited
  // reply-to is not in $recipient_emails
  or any(headers.reply_to, .email.email not in $recipient_emails)
)
and (
  2 of (
    // language attempting to engage
    (
      any(ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities,
          .name == "request"
      )
      and any(ml.nlu_classifier(coalesce(body.plain.raw,
                                         body.current_thread.text
                                )
              ).entities,
              .name == "financial"
      )
    ),
    // payment tag high confidence
    any(ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).tags,
        .name == "payment" and .confidence == "high"
    ),
    // invoicing language
    any(ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).tags,
        .name == "invoice"
    ),

    // urgency request
    any(ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities,
        .name == "urgency"
    )
  )
)

Detection logic

Scope: inbound message.

This rule detects supplier impersonation by checking for: similar linked domains to the sender, non-freemail senders using freemail infrastructure, sender domains less than 90 days old, unsolicited communication or no prior interaction with the reply-to address, and a suspicious body.

  1. inbound message
  2. any of body.links where all hold:
    • length(.href_url.domain.sld) > 3
    • all of:
      • strings.levenshtein(.href_url.domain.sld) > 0
      • strings.levenshtein(.href_url.domain.sld) ≤ 2
    • not:
      • sender.email.domain.root_domain is 'onmicrosoft.com'
    • network.whois(sender.email.domain).registrar_name is not network.whois(.href_url.domain).registrar_name
    • any of:
      • network.whois(sender.email.domain).days_old < 30
      • network.whois(.href_url.domain).days_old < 30
  3. all of:
    • sender.email.domain.root_domain not in $free_email_providers
    • any of:
      • any of headers.references where all hold:
        • any of $free_email_providers where:
          • strings.contains(.)
        • not:
          • . ends with 'outlook.com'
      • all of:
        • any of $free_email_providers where all hold:
          • strings.contains(headers.in_reply_to)
          • not:
            • headers.in_reply_to ends with 'outlook.com'
        • network.whois(sender.email.domain).days_old < 90
      • any of headers.reply_to where all hold:
        • network.whois(.email.domain).days_old < 30
        • .email.email is not sender.email.email
  4. any of:
    • not:
      • profile.by_sender_domain().solicited
    • any of headers.reply_to where:
      • .email.email not in $recipient_emails
  5. at least 2 of:
    • all of:
      • any of ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities where:
        • .name is 'request'
      • any of ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities where:
        • .name is 'financial'
    • any of ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).tags where all hold:
      • .name is 'payment'
      • .confidence is 'high'
    • any of ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).tags where:
      • .name is 'invoice'
    • any of ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities where:
      • .name is 'urgency'

Inspects: body.current_thread.text, body.links, body.links[].href_url.domain, body.links[].href_url.domain.sld, body.plain.raw, headers.in_reply_to, headers.references, headers.reply_to, headers.reply_to[].email.domain, headers.reply_to[].email.email, sender.email.domain, sender.email.domain.root_domain, sender.email.domain.sld, sender.email.email, type.inbound. Sensors: ml.nlu_classifier, network.whois, profile.by_sender_domain, strings.contains, strings.ends_with, strings.levenshtein. Reference lists: $free_email_providers, $recipient_emails.

Indicators matched (8)

FieldMatchValue
sender.email.domain.root_domainequalsonmicrosoft.com
strings.ends_withsuffixoutlook.com
ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities[].nameequalsrequest
ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities[].nameequalsfinancial
ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).tags[].nameequalspayment
ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).tags[].confidenceequalshigh
ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).tags[].nameequalsinvoice
ml.nlu_classifier(coalesce(body.plain.raw, body.current_thread.text)).entities[].nameequalsurgency