Detection rules › Sublime MQL

Brand impersonation: Mailgun

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

Impersonation of the Mailgun Email delivery platform.

Threat classification

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

CategoryValues
Attack typesCredential Phishing, BEC/Fraud
Tactics and techniquesImpersonation: Brand

Event coverage

Rule body MQL

type.inbound
and (
  any([
        sender.display_name,
        sender.email.domain.domain,
        sender.email.local_part,
        subject.subject
      ],
      regex.icontains(strings.replace_confusables(.), "ma[il][il]gun")
  )
  or regex.icontains(body.html.raw,
                     '<title>.*mailgun.*</title>',
                     'alt\s*=\s*"\s*Mailgun\s*Logo\s*"'
  )
  or regex.icontains(body.current_thread.text,
                     '[©®]\s*(20\d\d\s*)?Mailgun',
                     'mailgun\s*[©®]'
  )
  or any(ml.logo_detect(file.message_screenshot()).brands,
         .name == "Mailgun" and .confidence in ("medium", "high")
  )
)
and not (
  // sent from mailgun actual
  (
    sender.email.domain.root_domain in (
      'mailgun.com',
      'mailgun.net', // official mailgun domains
      'sinch.com', // parent company of Mailgun
      'mailgunwarmup.com', // an unrelated b2b firm
      'emailonacid.com', // another sinch email product 
      'elior-na.com', // a domain with a simliar logo that catches on logo_detect
      'brembo.com' // a domain with a simliar logo that catches on logo_detect
    )
    and headers.auth_summary.dmarc.pass
  )
  // and not where the recipient include the domain with a simliar logo
  // and where that recipient shows up in a previous thread
  or (
    any(recipients.to,
        .email.domain.root_domain in ("elior-na.com", "brembo.com")
    )
    and any(filter(recipients.to,
                   .email.domain.root_domain in ("elior-na.com", "brembo.com")
            ),
            (
              strings.icontains(body.html.display_text,
                                strings.concat("From: ", .email.email)
              )
              or strings.icontains(body.html.display_text,
                                   strings.concat("From: ", .display_name)
              )
            )
    )
  )
  or 
  // some domains have "mailgun" as a subdomain and are sent via mailgun
  // these are unlikely to be impersonations
  (
    (
      strings.icontains(sender.email.domain.domain, "mailgun")
      or strings.icontains(sender.email.local_part, "mailgun")
    )
    and (
      // if mailgun action was in the header.hops very likely not impersonation
      any(headers.domains, .root_domain in ('mailgun.com', 'mailgun.net'))
      // but if not and there are 4 or more X-Mailgun headers, likely not impersonation
      or sum(map(filter(headers.hops, .index < 2),
                 length(filter(.fields,
                               strings.starts_with(.name, "X-Mailgun-")
                        )
                 )
             )
      ) >= 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
)

Detection logic

Scope: inbound message.

Impersonation of the Mailgun Email delivery platform.

  1. inbound message
  2. any of:
    • any of [sender.display_name, sender.email.domain.domain, sender.email.local_part, subject.subject] where:
      • strings.replace_confusables(.) matches 'ma[il][il]gun'
    • body.html.raw matches any of 2 patterns
      • <title>.*mailgun.*</title>
      • alt\s*=\s*"\s*Mailgun\s*Logo\s*"
    • body.current_thread.text matches any of 2 patterns
      • [©®]\s*(20\d\d\s*)?Mailgun
      • mailgun\s*[©®]
    • any of ml.logo_detect(file.message_screenshot()).brands where all hold:
      • .name is 'Mailgun'
      • .confidence in ('medium', 'high')
  3. none of:
    • all of:
      • sender.email.domain.root_domain in ('mailgun.com', 'mailgun.net', 'sinch.com', 'mailgunwarmup.com', 'emailonacid.com', 'elior-na.com', 'brembo.com')
      • headers.auth_summary.dmarc.pass
    • all of:
      • any of recipients.to where:
        • .email.domain.root_domain in ('elior-na.com', 'brembo.com')
      • any of filter(recipients.to) where any holds:
        • strings.icontains(body.html.display_text)
        • strings.icontains(body.html.display_text)
    • all of:
      • any of:
        • sender.email.domain.domain contains 'mailgun'
        • sender.email.local_part contains 'mailgun'
      • any of:
        • any of headers.domains where:
          • .root_domain in ('mailgun.com', 'mailgun.net')
        • sum(map(filter(headers.hops, .index < 2), length(filter(.fields, strings.starts_with(.name, 'X-Mailgun-'))))) ≥ 3
  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: body.current_thread.text, body.html.display_text, body.html.raw, headers.auth_summary.dmarc.pass, headers.domains, headers.domains[].root_domain, headers.hops, headers.hops[].index, recipients.to, recipients.to[].email.domain.root_domain, sender.display_name, sender.email.domain.domain, sender.email.domain.root_domain, sender.email.local_part, subject.subject, type.inbound. Sensors: file.message_screenshot, ml.logo_detect, regex.icontains, strings.concat, strings.icontains, strings.replace_confusables, strings.starts_with. Reference lists: $high_trust_sender_root_domains.

Indicators matched (21)

FieldMatchValue
regex.icontainsregexma[il][il]gun
regex.icontainsregex<title>.*mailgun.*</title>
regex.icontainsregexalt\s*=\s*"\s*Mailgun\s*Logo\s*"
regex.icontainsregex[©®]\s*(20\d\d\s*)?Mailgun
regex.icontainsregexmailgun\s*[©®]
ml.logo_detect(file.message_screenshot()).brands[].nameequalsMailgun
ml.logo_detect(file.message_screenshot()).brands[].confidencemembermedium
ml.logo_detect(file.message_screenshot()).brands[].confidencememberhigh
sender.email.domain.root_domainmembermailgun.com
sender.email.domain.root_domainmembermailgun.net
sender.email.domain.root_domainmembersinch.com
sender.email.domain.root_domainmembermailgunwarmup.com
9 more
sender.email.domain.root_domainmemberemailonacid.com
sender.email.domain.root_domainmemberelior-na.com
sender.email.domain.root_domainmemberbrembo.com
recipients.to[].email.domain.root_domainmemberelior-na.com
recipients.to[].email.domain.root_domainmemberbrembo.com
strings.icontainssubstringmailgun
headers.domains[].root_domainmembermailgun.com
headers.domains[].root_domainmembermailgun.net
strings.starts_withprefixX-Mailgun-