EXPLORE
← Back to Explore
sublimehighRule

Callback phishing via Adobe Sign comment

This rule inspects messages originating from legitimate Adobe Sign infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number.

MITRE ATT&CK

defense-evasioninitial-access

Detection Query

type.inbound
and length(attachments) == 0
and (
  not profile.by_sender().solicited
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
)
// Legitimate Docusign sending infratructure
and sender.email.domain.root_domain == 'adobesign.com'
and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
and (
  // this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
  regex.icontains(strings.replace_confusables(body.current_thread.text),
                  '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
  )
  or any(ml.logo_detect(file.message_screenshot()).brands,
         .name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T")
  )
)
and (
  (
    // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
    // however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
    // caused by messages which mention cancelling or otherwise managing a subscription
    // it is also synced and below for message_screenshot OCR output
    3 of (
      strings.icontains(body.current_thread.text, 'purchase'),
      strings.icontains(body.current_thread.text, 'payment'),
      strings.icontains(body.current_thread.text, 'transaction'),
      strings.icontains(body.current_thread.text, 'subscription'),
      strings.icontains(body.current_thread.text, 'antivirus'),
      strings.icontains(body.current_thread.text, 'order'),
      strings.icontains(body.current_thread.text, 'support'),
      strings.icontains(body.current_thread.text, 'help line'),
      strings.icontains(body.current_thread.text, 'receipt'),
      strings.icontains(body.current_thread.text, 'invoice'),
      strings.icontains(body.current_thread.text, 'call'),
      strings.icontains(body.current_thread.text, 'cancel'),
      strings.icontains(body.current_thread.text, 'renew'),
      strings.icontains(body.current_thread.text, 'refund'),
      regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
      strings.icontains(body.current_thread.text, "+1"),
      strings.icontains(body.current_thread.text, "amount"),
      strings.icontains(body.current_thread.text, "charged"),
      strings.icontains(body.current_thread.text, "crypto"),
      strings.icontains(body.current_thread.text, "wallet address"),
      regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
    )
    // phone number regex
    and regex.icontains(body.current_thread.text,
                        '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
                        '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
    )
  )
  or (
    // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
    // and above for current_thread.text
    //
    // 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
    //
    3 of (
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
      strings.icontains(beta.ocr(file.message_screenshot()).text,
                        'subscription'
      ),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
      regex.icontains(beta.ocr(file.message_screenshot()).text,
                      "(?:reach|contact) us at"
      ),
      strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
      strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
      strings.icontains(beta.ocr(file.message_screenshot()).text,
                        'wallet address'
      ),
      regex.icontains(beta.ocr(file.message_screenshot()).text,
                      '\$\d{3}\.\d{2}\b'
      ),
    )
    // phone number regex
    and regex.icontains(beta.ocr(file.message_screenshot()).text,
                        '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
                        '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
    )

    // negate messages with previous threads.  While callback phishing with thread hijacking or with current_thread 
    // padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
    and not regex.icount(beta.ocr(file.message_screenshot()).text,
                         '(?:from|to|sent|date|cc|subject):'
    ) > 3
    // this notation of previous threads often only occurs once
    and not regex.icontains(beta.ocr(file.message_screenshot()).text,
                            'wrote:[\r\n]'
    )
  )
)

Data Sources

Email MessagesEmail HeadersEmail Attachments

Platforms

email
Raw Content
name: "Callback phishing via Adobe Sign comment"
description: |
  This rule inspects messages originating from legitimate Adobe Sign infrastructure, with content matching Callback Phishing criteria, in the body, requiring at least one brand name, as well as 3 matching Callback Phishing terms and a phone number. 
type: "rule"
severity: "high"
source: |
  type.inbound
  and length(attachments) == 0
  and (
    not profile.by_sender().solicited
    or (
      profile.by_sender().any_messages_malicious_or_spam
      and not profile.by_sender().any_messages_benign
    )
  )
  // Legitimate Docusign sending infratructure
  and sender.email.domain.root_domain == 'adobesign.com'
  and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
  and (
    // this section is synced with attachment_callback_phish_with_pdf.yml and attachment_callback_phish_with_img.yml
    regex.icontains(strings.replace_confusables(body.current_thread.text),
                    '(p.{0,3}a.{0,3}y.{0,3}p.{0,3}a.{0,3}l|ma?c.?fee|n[o0]rt[o0]n|geek.{0,5}squad|ebay|symantec|best buy|lifel[o0]c|secure anywhere|starz|utilities premium|pc security|at&t)'
    )
    or any(ml.logo_detect(file.message_screenshot()).brands,
           .name in ("PayPal", "Norton", "GeekSquad", "Ebay", "McAfee", "AT&T")
    )
  )
  and (
    (
      // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
      // however, the 3 of logic and requiring a phone number is specific to this rule in order to reduce FPs
      // caused by messages which mention cancelling or otherwise managing a subscription
      // it is also synced and below for message_screenshot OCR output
      3 of (
        strings.icontains(body.current_thread.text, 'purchase'),
        strings.icontains(body.current_thread.text, 'payment'),
        strings.icontains(body.current_thread.text, 'transaction'),
        strings.icontains(body.current_thread.text, 'subscription'),
        strings.icontains(body.current_thread.text, 'antivirus'),
        strings.icontains(body.current_thread.text, 'order'),
        strings.icontains(body.current_thread.text, 'support'),
        strings.icontains(body.current_thread.text, 'help line'),
        strings.icontains(body.current_thread.text, 'receipt'),
        strings.icontains(body.current_thread.text, 'invoice'),
        strings.icontains(body.current_thread.text, 'call'),
        strings.icontains(body.current_thread.text, 'cancel'),
        strings.icontains(body.current_thread.text, 'renew'),
        strings.icontains(body.current_thread.text, 'refund'),
        regex.icontains(body.current_thread.text, "(?:reach|contact) us at"),
        strings.icontains(body.current_thread.text, "+1"),
        strings.icontains(body.current_thread.text, "amount"),
        strings.icontains(body.current_thread.text, "charged"),
        strings.icontains(body.current_thread.text, "crypto"),
        strings.icontains(body.current_thread.text, "wallet address"),
        regex.icontains(body.current_thread.text, '\$\d{3}\.\d{2}\b'),
      )
      // phone number regex
      and regex.icontains(body.current_thread.text,
                          '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
                          '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
      )
    )
    or (
      // this seciton is synced with attachment_callback_phish_with_img.yml and attachment_callback_phish_with_pdf.yml
      // and above for current_thread.text
      //
      // 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
      //
      3 of (
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'purchase'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'payment'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'transaction'),
        strings.icontains(beta.ocr(file.message_screenshot()).text,
                          'subscription'
        ),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'antivirus'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'order'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'support'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'help line'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'receipt'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'invoice'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'call'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'helpdesk'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'cancel'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'renew'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'refund'),
        regex.icontains(beta.ocr(file.message_screenshot()).text,
                        "(?:reach|contact) us at"
        ),
        strings.icontains(beta.ocr(file.message_screenshot()).text, '+1'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'amount'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'charged'),
        strings.icontains(beta.ocr(file.message_screenshot()).text, 'crypto'),
        strings.icontains(beta.ocr(file.message_screenshot()).text,
                          'wallet address'
        ),
        regex.icontains(beta.ocr(file.message_screenshot()).text,
                        '\$\d{3}\.\d{2}\b'
        ),
      )
      // phone number regex
      and regex.icontains(beta.ocr(file.message_screenshot()).text,
                          '\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}',
                          '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
      )
  
      // negate messages with previous threads.  While callback phishing with thread hijacking or with current_thread 
      // padded with whitespace and previous threads in the message has been observed, the intetion of using OCR is for image embedded callbacks
      and not regex.icount(beta.ocr(file.message_screenshot()).text,
                           '(?:from|to|sent|date|cc|subject):'
      ) > 3
      // this notation of previous threads often only occurs once
      and not regex.icontains(beta.ocr(file.message_screenshot()).text,
                              'wrote:[\r\n]'
      )
    )
  )
attack_types:
  - "Callback Phishing"
tactics_and_techniques:
  - "Evasion"
  - "Impersonation: Brand"
  - "Out of band pivot"
  - "Social engineering"
detection_methods:
  - "Content analysis"
  - "Computer Vision"
  - "Header analysis"
  - "Sender analysis"
  - "URL analysis"
id: "7eb4516d-f358-5c22-b527-34db0a532df9"