Detection rules › Sublime MQL

Callback phishing: Branded invoice from sender/reply-to domain less than 30 days old

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

This rule checks for invoicing content from a sender, reply-to domain or return-path domain less than 30d old. It also checks the body or the OCR'd screenshot for key words commonly abused in fraudulent invoicing attacks.

Threat classification

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

CategoryValues
Attack typesCallback Phishing
Tactics and techniquesImpersonation: Brand, Out of band pivot, Social engineering

Event coverage

Rule body MQL

type.inbound
// reply to domain that's less than 30d old and doesn't match the sender
and (
  (
    length(headers.reply_to) > 0
    and all(headers.reply_to,
            network.whois(.email.domain).days_old <= 30
            and .email.email != sender.email.email
    )
  )

  // or the return path or sender domain is less than 30d old 
  or network.whois(headers.return_path.domain).days_old <= 30
  or network.whois(sender.email.domain).days_old <= 30
)

// invoicing with high confidence
and any(ml.nlu_classifier(body.current_thread.text).tags,
        .name == "invoice" and .confidence == "high"
)

// commonly abused brands in body
and (
  strings.ilike(body.current_thread.text,
                "*mcafee*",
                "*norton*",
                "*geek squad*",
                "*paypal*",
                "*ebay*",
                "*symantec*",
                "*best buy*",
                "*lifelock*",
                "*virus*"
  )

  // commonly abused brand logo
  or any(ml.logo_detect(file.message_screenshot()).brands,
         .name in ("PayPal", "Norton", "GeekSquad", "Ebay")
  )

  // check message screenshot ocr for commonly abused brands
  //
  // This rule makes use of a beta feature and is subject to change without notice
  // using the beta feature in custom rules is not suggested until it has been formally released
  //    
  or 1 of (
    strings.icontains(beta.ocr(file.message_screenshot()).text, "geek squad"),
    strings.icontains(beta.ocr(file.message_screenshot()).text, "lifelock"),
    strings.icontains(beta.ocr(file.message_screenshot()).text, "best buy"),
    strings.icontains(beta.ocr(file.message_screenshot()).text, "mcafee"),
    strings.icontains(beta.ocr(file.message_screenshot()).text, "norton"),
    strings.icontains(beta.ocr(file.message_screenshot()).text, "ebay"),
    strings.icontains(beta.ocr(file.message_screenshot()).text, "paypal"),
    strings.icontains(beta.ocr(file.message_screenshot()).text, "virus"),
  )
)

// phone number regex
and regex.icontains(body.current_thread.text,
                    '\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}'
)
and not profile.by_sender().solicited
and not profile.by_sender().any_messages_benign

Detection logic

Scope: inbound message.

This rule checks for invoicing content from a sender, reply-to domain or return-path domain less than 30d old. It also checks the body or the OCR'd screenshot for key words commonly abused in fraudulent invoicing attacks.

  1. inbound message
  2. any of:
    • all of:
      • length(headers.reply_to) > 0
      • all of headers.reply_to where all hold:
        • network.whois(.email.domain).days_old ≤ 30
        • .email.email is not sender.email.email
    • network.whois(headers.return_path.domain).days_old ≤ 30
    • network.whois(sender.email.domain).days_old ≤ 30
  3. any of ml.nlu_classifier(body.current_thread.text).tags where all hold:
    • .name is 'invoice'
    • .confidence is 'high'
  4. any of:
    • body.current_thread.text matches any of 9 patterns
      • *mcafee*
      • *norton*
      • *geek squad*
      • *paypal*
      • *ebay*
      • *symantec*
      • *best buy*
      • *lifelock*
      • *virus*
    • any of ml.logo_detect(file.message_screenshot()).brands where:
      • .name in ('PayPal', 'Norton', 'GeekSquad', 'Ebay')
    • at least 1 of 8: beta.ocr(file.message_screenshot()).text contains any of 8 patterns
      • geek squad
      • lifelock
      • best buy
      • mcafee
      • norton
      • ebay
      • paypal
      • virus
  5. body.current_thread.text matches '\\+?(\\d{1}.)?\\(?\\d{3}?\\)?.\\d{3}.?\\d{4}'
  6. not:
    • profile.by_sender().solicited
  7. not:
    • profile.by_sender().any_messages_benign

Inspects: body.current_thread.text, headers.reply_to, headers.reply_to[].email.domain, headers.reply_to[].email.email, headers.return_path.domain, sender.email.domain, sender.email.email, type.inbound. Sensors: beta.ocr, file.message_screenshot, ml.logo_detect, ml.nlu_classifier, network.whois, profile.by_sender, regex.icontains, strings.icontains, strings.ilike.

Indicators matched (24)

FieldMatchValue
ml.nlu_classifier(body.current_thread.text).tags[].nameequalsinvoice
ml.nlu_classifier(body.current_thread.text).tags[].confidenceequalshigh
strings.ilikesubstring*mcafee*
strings.ilikesubstring*norton*
strings.ilikesubstring*geek squad*
strings.ilikesubstring*paypal*
strings.ilikesubstring*ebay*
strings.ilikesubstring*symantec*
strings.ilikesubstring*best buy*
strings.ilikesubstring*lifelock*
strings.ilikesubstring*virus*
ml.logo_detect(file.message_screenshot()).brands[].namememberPayPal
12 more
ml.logo_detect(file.message_screenshot()).brands[].namememberNorton
ml.logo_detect(file.message_screenshot()).brands[].namememberGeekSquad
ml.logo_detect(file.message_screenshot()).brands[].namememberEbay
strings.icontainssubstringgeek squad
strings.icontainssubstringlifelock
strings.icontainssubstringbest buy
strings.icontainssubstringmcafee
strings.icontainssubstringnorton
strings.icontainssubstringebay
strings.icontainssubstringpaypal
strings.icontainssubstringvirus
regex.icontainsregex\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}