EXPLORE
← Back to Explore
sublimemediumRule

Callback phishing via Zoho service abuse

Callback phishing campaigns have been observed abusing Zoho Invoice services to send fraudulent invoices with callback phishing contents.

MITRE ATT&CK

defense-evasioninitial-access

Detection Query

type.inbound

// Legitimate Zoho sending infratructure
and (
  sender.email.domain.root_domain in ('zohoinvoice.com')
  // check for SPF or DMARC passed
  and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
)
and (
  // Callback Phishing in body (brand names required)
  (
    length(attachments) == 0

    // brand names are required.
    and regex.icontains(body.current_thread.text,
                        (
                          "mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock"
                        )
    )
    and 3 of (
      strings.ilike(body.current_thread.text, '*purchase*'),
      strings.ilike(body.current_thread.text, '*payment*'),
      strings.ilike(body.current_thread.text, '*transaction*'),
      strings.ilike(body.current_thread.text, '*subscription*'),
      strings.ilike(body.current_thread.text, '*antivirus*'),
      strings.ilike(body.current_thread.text, '*order*'),
      strings.ilike(body.current_thread.text, '*support*'),
      strings.ilike(body.current_thread.text, '*help line*'),
      strings.ilike(body.current_thread.text, '*receipt*'),
      strings.ilike(body.current_thread.text, '*invoice*'),
      strings.ilike(body.current_thread.text, '*call*'),
      strings.ilike(body.current_thread.text, '*cancel*'),
      strings.ilike(body.current_thread.text, '*renew*'),
      strings.ilike(body.current_thread.text, '*refund*')
    )
    // phone number regex
    and any([body.current_thread.text, subject.subject],
            regex.icontains(., '\b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b')
    )
  )
  // all attachments are PDFs with callback phishing indicators Brands Required
  or (
    length(attachments) < 3
    and all(attachments, .file_extension == "pdf")
    // the attachment is a pdf with 1 page, and at least 60 ocr chars
    and any(attachments,
            (
              .file_extension == "pdf"
              and any(file.explode(.), .scan.exiftool.page_count < 3)
              and any(file.explode(.), length(.scan.ocr.raw) > 60)

              // 4 of the following strings are found        
              and (
                any(file.explode(.),
                    4 of (
                      strings.icontains(.scan.ocr.raw, "purchase"),
                      strings.icontains(.scan.ocr.raw, "payment"),
                      strings.icontains(.scan.ocr.raw, "transaction"),
                      strings.icontains(.scan.ocr.raw, "subscription"),
                      strings.icontains(.scan.ocr.raw, "antivirus"),
                      strings.icontains(.scan.ocr.raw, "order"),
                      strings.icontains(.scan.ocr.raw, "support"),
                      strings.icontains(.scan.ocr.raw, "help line"),
                      strings.icontains(.scan.ocr.raw, "receipt"),
                      strings.icontains(.scan.ocr.raw, "invoice"),
                      strings.icontains(.scan.ocr.raw, "call"),
                      strings.icontains(.scan.ocr.raw, "helpdesk"),
                      strings.icontains(.scan.ocr.raw, "cancel"),
                      strings.icontains(.scan.ocr.raw, "renew"),
                      strings.icontains(.scan.ocr.raw, "refund"),
                      strings.icontains(.scan.ocr.raw, "amount"),
                      strings.icontains(.scan.ocr.raw, "crypto"),
                      strings.icontains(.scan.ocr.raw, "wallet address"),
                      regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
                      regex.icontains(.scan.ocr.raw,
                                      '(\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4})'
                      ),
                      regex.icontains(.scan.ocr.raw,
                                      '\+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4}'
                      )
                    )

                    // 1 of the following strings is found, representing common Callback brands          
                    and (
                      1 of (
                        strings.icontains(.scan.ocr.raw, "geek squad"),
                        strings.icontains(.scan.ocr.raw, "lifelock"),
                        strings.icontains(.scan.ocr.raw, "best buy"),
                        strings.icontains(.scan.ocr.raw, "mcafee"),
                        strings.icontains(.scan.ocr.raw, "norton"),
                        strings.icontains(.scan.ocr.raw, "ebay"),
                        strings.icontains(.scan.ocr.raw, "paypal"),
                      )
                      // add additional logic for common language for paypal, which is a valid payment method
                      and not regex.icontains(.scan.ocr.raw,
                                              "paypal[^\n]+accepted"
                      )
                      and not regex.icontains(.scan.ocr.raw,
                                              "payment.{0,30}(via|by) paypal"
                      )
                      and not regex.icontains(.scan.ocr.raw,
                                              '\d{2,4} norton'
                      ) // an address, example: 1234 Norton Road
                    )
                )
                or any(ml.logo_detect(.).brands,
                       .name in ("PayPal", "Norton", "GeekSquad", "Ebay")
                )
              )
            )
    )
  )
)

Data Sources

Email MessagesEmail HeadersEmail Attachments

Platforms

email
Raw Content
name: "Callback phishing via Zoho service abuse"
description: "Callback phishing campaigns have been observed abusing Zoho Invoice services to send fraudulent invoices with callback phishing contents."
type: "rule"
severity: "medium"
source: |
  type.inbound
  
  // Legitimate Zoho sending infratructure
  and (
    sender.email.domain.root_domain in ('zohoinvoice.com')
    // check for SPF or DMARC passed
    and (headers.auth_summary.spf.pass or headers.auth_summary.dmarc.pass)
  )
  and (
    // Callback Phishing in body (brand names required)
    (
      length(attachments) == 0
  
      // brand names are required.
      and regex.icontains(body.current_thread.text,
                          (
                            "mcafee|norton|geek.{0,5}squad|paypal|ebay|symantec|best buy|lifelock"
                          )
      )
      and 3 of (
        strings.ilike(body.current_thread.text, '*purchase*'),
        strings.ilike(body.current_thread.text, '*payment*'),
        strings.ilike(body.current_thread.text, '*transaction*'),
        strings.ilike(body.current_thread.text, '*subscription*'),
        strings.ilike(body.current_thread.text, '*antivirus*'),
        strings.ilike(body.current_thread.text, '*order*'),
        strings.ilike(body.current_thread.text, '*support*'),
        strings.ilike(body.current_thread.text, '*help line*'),
        strings.ilike(body.current_thread.text, '*receipt*'),
        strings.ilike(body.current_thread.text, '*invoice*'),
        strings.ilike(body.current_thread.text, '*call*'),
        strings.ilike(body.current_thread.text, '*cancel*'),
        strings.ilike(body.current_thread.text, '*renew*'),
        strings.ilike(body.current_thread.text, '*refund*')
      )
      // phone number regex
      and any([body.current_thread.text, subject.subject],
              regex.icontains(., '\b\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}\b')
      )
    )
    // all attachments are PDFs with callback phishing indicators Brands Required
    or (
      length(attachments) < 3
      and all(attachments, .file_extension == "pdf")
      // the attachment is a pdf with 1 page, and at least 60 ocr chars
      and any(attachments,
              (
                .file_extension == "pdf"
                and any(file.explode(.), .scan.exiftool.page_count < 3)
                and any(file.explode(.), length(.scan.ocr.raw) > 60)
  
                // 4 of the following strings are found        
                and (
                  any(file.explode(.),
                      4 of (
                        strings.icontains(.scan.ocr.raw, "purchase"),
                        strings.icontains(.scan.ocr.raw, "payment"),
                        strings.icontains(.scan.ocr.raw, "transaction"),
                        strings.icontains(.scan.ocr.raw, "subscription"),
                        strings.icontains(.scan.ocr.raw, "antivirus"),
                        strings.icontains(.scan.ocr.raw, "order"),
                        strings.icontains(.scan.ocr.raw, "support"),
                        strings.icontains(.scan.ocr.raw, "help line"),
                        strings.icontains(.scan.ocr.raw, "receipt"),
                        strings.icontains(.scan.ocr.raw, "invoice"),
                        strings.icontains(.scan.ocr.raw, "call"),
                        strings.icontains(.scan.ocr.raw, "helpdesk"),
                        strings.icontains(.scan.ocr.raw, "cancel"),
                        strings.icontains(.scan.ocr.raw, "renew"),
                        strings.icontains(.scan.ocr.raw, "refund"),
                        strings.icontains(.scan.ocr.raw, "amount"),
                        strings.icontains(.scan.ocr.raw, "crypto"),
                        strings.icontains(.scan.ocr.raw, "wallet address"),
                        regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
                        regex.icontains(.scan.ocr.raw,
                                        '(\+\d|1.(\()?\d{3}(\))?\D\d{3}\D\d{4})'
                        ),
                        regex.icontains(.scan.ocr.raw,
                                        '\+?(\d{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}\d{3}[\s\.\-⋅]{0,5}\d{4}'
                        )
                      )
  
                      // 1 of the following strings is found, representing common Callback brands          
                      and (
                        1 of (
                          strings.icontains(.scan.ocr.raw, "geek squad"),
                          strings.icontains(.scan.ocr.raw, "lifelock"),
                          strings.icontains(.scan.ocr.raw, "best buy"),
                          strings.icontains(.scan.ocr.raw, "mcafee"),
                          strings.icontains(.scan.ocr.raw, "norton"),
                          strings.icontains(.scan.ocr.raw, "ebay"),
                          strings.icontains(.scan.ocr.raw, "paypal"),
                        )
                        // add additional logic for common language for paypal, which is a valid payment method
                        and not regex.icontains(.scan.ocr.raw,
                                                "paypal[^\n]+accepted"
                        )
                        and not regex.icontains(.scan.ocr.raw,
                                                "payment.{0,30}(via|by) paypal"
                        )
                        and not regex.icontains(.scan.ocr.raw,
                                                '\d{2,4} norton'
                        ) // an address, example: 1234 Norton Road
                      )
                  )
                  or any(ml.logo_detect(.).brands,
                         .name in ("PayPal", "Norton", "GeekSquad", "Ebay")
                  )
                )
              )
      )
    )
  )
attack_types:
  - "Callback Phishing"
tactics_and_techniques:
  - "Evasion"
  - "Free email provider"
  - "Impersonation: Brand"
  - "Social engineering"
detection_methods:
  - "Computer Vision"
  - "Content analysis"
  - "Header analysis"
  - "Optical Character Recognition"
id: "61e351ec-0d21-5cb4-822f-bb6b99a21c07"