Detection rules › Sublime MQL

Brand Impersonation: Stripe

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

Impersonation of Stripe, usually for credential theft.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, Lookalike domain, Social engineering

Event coverage

Rule body MQL

type.inbound
and (
  // Display name after replacing unicode confusables is stripe
  (
    sender.display_name =~ 'stripe'
    or (
      strings.istarts_with(sender.display_name, 'stripe ')
      and not sender.display_name in~ (
        'Stripe & Stare',
        'Stripe and Stare',
        'Stripe Events'
      )
    )
    or strings.replace_confusables(sender.display_name) =~ 'stripe'
    // fake stripe invoice in attached picture
    or (
      any(attachments,
          .file_type in $file_types_images
          and any(file.explode(.),
                  strings.ilike(.scan.ocr.raw, "*stripe*")
                  and any(ml.nlu_classifier(.scan.ocr.raw).intents,
                          .name in ("callback_scam")
                          and .confidence in ("medium", "high")
                  )
          )
      )
    )
  )
  or (
    // the edit distance is 1 or 2
    strings.ilevenshtein(strings.replace_confusables(sender.display_name),
                         'stripe'
    ) <= 2
    // the length is the same as "stripe"
    and length(sender.display_name) == 6
    // and not one of these english words that matches the edit distance
    and not sender.display_name in~ (
      "strive",
      "stride",
      "strife",
      "strike",
      "strobe",
      "stroke",
      "streps",
      "string",
      "scribe",
      "straye", // a shoe company?
      "storie", // storiesbystorie.com
      "stryke", // a cybersecurity and compliance company
      "stryve", // a food/snack company stryve.com
      "shrine", // common word
      "s.ride", // cab/taxi company
      "striim", // ai/data company
      "striim.com", // same as above
      "skribe" // ai/legal company
    )
  )
)
and sender.email.domain.root_domain not in~ ('stripe.com')
and sender.email.email not in $recipient_emails

// Stripe adds a custom header
// don't match messages with the header
and not any(headers.hops, any(.fields, .name == "X-Stripe-EID"))

// 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 Stripe, usually for credential theft.

  1. inbound message
  2. any of:
    • any of:
      • sender.display_name is 'stripe'
      • all of:
        • sender.display_name starts with 'stripe '
        • not:
          • sender.display_name in ('Stripe & Stare', 'Stripe and Stare', 'Stripe Events')
      • strings.replace_confusables(sender.display_name) is 'stripe'
      • any of attachments where all hold:
        • .file_type in $file_types_images
        • any of file.explode(.) where all hold:
          • .scan.ocr.raw matches '*stripe*'
          • any of ml.nlu_classifier(.scan.ocr.raw).intents where all hold:
            • .name in ('callback_scam')
            • .confidence in ('medium', 'high')
    • all of:
      • strings.replace_confusables(sender.display_name) is similar to 'stripe'
      • length(sender.display_name) is 6
      • not:
        • sender.display_name in ('strive', 'stride', 'strife', 'strike', 'strobe', 'stroke', 'streps', 'string', 'scribe', 'straye', 'storie', 'stryke', 'stryve', 'shrine', 's.ride', 'striim', 'striim.com', 'skribe')
  3. sender.email.domain.root_domain not in ('stripe.com')
  4. sender.email.email not in $recipient_emails
  5. not:
    • any of headers.hops where:
      • any of .fields where:
        • .name is 'X-Stripe-EID'
  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, headers.auth_summary.dmarc.pass, headers.hops, headers.hops[].fields, headers.hops[].fields[].name, sender.display_name, sender.email.domain.root_domain, sender.email.email, type.inbound. Sensors: file.explode, ml.nlu_classifier, strings.ilevenshtein, strings.ilike, strings.istarts_with, strings.replace_confusables. Reference lists: $file_types_images, $high_trust_sender_root_domains, $recipient_emails.

Indicators matched (30)

FieldMatchValue
sender.display_nameequalsstripe
strings.istarts_withprefixstripe
sender.display_namememberStripe & Stare
sender.display_namememberStripe and Stare
sender.display_namememberStripe Events
strings.ilikesubstring*stripe*
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].namemembercallback_scam
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidencemembermedium
ml.nlu_classifier(file.explode(attachments[])[].scan.ocr.raw).intents[].confidencememberhigh
strings.ilevenshteinfuzzystripe
sender.display_namememberstrive
sender.display_namememberstride
18 more
sender.display_namememberstrife
sender.display_namememberstrike
sender.display_namememberstrobe
sender.display_namememberstroke
sender.display_namememberstreps
sender.display_namememberstring
sender.display_namememberscribe
sender.display_namememberstraye
sender.display_namememberstorie
sender.display_namememberstryke
sender.display_namememberstryve
sender.display_namemembershrine
sender.display_namemembers.ride
sender.display_namememberstriim
sender.display_namememberstriim.com
sender.display_namememberskribe
sender.email.domain.root_domainmemberstripe.com
headers.hops[].fields[].nameequalsX-Stripe-EID