Attachment: Callback Phishing solicitation via pdf file

A fraudulent invoice/receipt found in a pdf attachment. Callback Phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.

Sublime rule (View on GitHub)

  1name: "Attachment: Callback Phishing solicitation via pdf file"
  2description: |
  3  A fraudulent invoice/receipt found in a pdf attachment.
  4  Callback Phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. 
  5  The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment.  
  6type: "rule"
  7severity: "high"
  8source: |
  9  type.inbound
 10  and (
 11    not profile.by_sender().solicited
 12    or (
 13      profile.by_sender().any_messages_malicious_or_spam
 14      and not profile.by_sender().any_false_positives
 15    )
 16  )
 17  
 18  // single attachment
 19  and length(attachments) == 1
 20  
 21  // sender is freemail
 22  and (
 23    sender.email.domain.root_domain in $free_email_providers
 24    // the sender is a common service, which has likely been sent through a DL
 25    or (
 26      sender.email.domain.root_domain in $tranco_50k
 27      and all(recipients.to, .email.domain.domain not in $org_domains)
 28    )
 29  )
 30  // the attachment is a pdf with less than 3 pages, and at least 60 ocr chars
 31  and any(attachments,
 32          (
 33            .file_extension == "pdf"
 34            // get the length of the attached pdf
 35            and any(file.explode(.),
 36                    .depth == 0 and .scan.exiftool.page_count < 3
 37            )
 38            // check that any _single_ result in the file.explode matches these conditions
 39            // a second file.explode is required because the OCR is generated at a different depth within 
 40            // the file.explode results
 41            and (
 42              any(file.explode(.),
 43                  length(.scan.ocr.raw) > 60
 44                  // 4 of the following strings are found        
 45                  and 4 of (
 46                    // this section is synced with attachment_callback_phish_with_pdf.yml and body_callback_phishing_no_attachment.yml
 47                    strings.icontains(.scan.ocr.raw, "purchase"),
 48                    strings.icontains(.scan.ocr.raw, "payment"),
 49                    strings.icontains(.scan.ocr.raw, "transaction"),
 50                    strings.icontains(.scan.ocr.raw, "subscription"),
 51                    strings.icontains(.scan.ocr.raw, "antivirus"),
 52                    strings.icontains(.scan.ocr.raw, "order"),
 53                    strings.icontains(.scan.ocr.raw, "support"),
 54                    strings.icontains(.scan.ocr.raw, "help line"),
 55                    strings.icontains(.scan.ocr.raw, "receipt"),
 56                    strings.icontains(.scan.ocr.raw, "invoice"),
 57                    strings.icontains(.scan.ocr.raw, "call"),
 58                    strings.icontains(.scan.ocr.raw, "helpdesk"),
 59                    strings.icontains(.scan.ocr.raw, "cancel"),
 60                    strings.icontains(.scan.ocr.raw, "renew"),
 61                    strings.icontains(.scan.ocr.raw, "refund"),
 62                    regex.icontains(.scan.ocr.raw, "(?:reach|contact) us at"),
 63                    strings.icontains(.scan.ocr.raw, "+1"),
 64                    strings.icontains(.scan.ocr.raw, "amount"),
 65                    strings.icontains(.scan.ocr.raw, "charged"),
 66                    strings.icontains(.scan.ocr.raw, "crypto"),
 67                    strings.icontains(.scan.ocr.raw, "wallet address"),
 68                    regex.icontains(.scan.ocr.raw, '\$\d{3}\.\d{2}\b'),
 69                    regex.icontains(.scan.ocr.raw,
 70                                    '(\+[ilo0-9]|1.(\()?[ilo0-9]{3}(\))?\D[ilo0-9]{3}\D[ilo0-9]{4})',
 71                                    '\+?([ilo0-9]{1,2})?\s?\(?\d{3}\)?[\s\.\-⋅]{0,5}[ilo0-9]{3}[\s\.\-⋅]{0,5}[ilo0-9]{4}'
 72                    ),
 73                  )
 74                  and (
 75                    // this section is synced with attachment_callback_phish_with_img.yml and body_callback_phishing_no_attachment.yml
 76                    regex.icontains(.scan.ocr.raw,
 77                                    '(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)'
 78                    )
 79                    // suspicious attachment name from the attachment object not file.explode() output
 80                    or regex.icontains(..file_name, 'INV(?:_|\s)?\d+(.pdf)$')
 81                  )
 82                  // Negate bank statements
 83                  and not (
 84                    2 of (
 85                      strings.icontains(.scan.ocr.raw, "opening balance"),
 86                      strings.icontains(.scan.ocr.raw, "closing balance"),
 87                      strings.icontains(.scan.ocr.raw, "direct debit"),
 88                      strings.icontains(.scan.ocr.raw, "interest"),
 89                      strings.icontains(.scan.ocr.raw, "account balance"),
 90                    )
 91                  )
 92              )
 93              // this section is synced with attachment_callback_phish_with_img.yml and body_callback_phishing_no_attachment.yml
 94              or any(ml.logo_detect(.).brands,
 95                     .name in (
 96                       "PayPal",
 97                       "Norton",
 98                       "GeekSquad",
 99                       "Ebay",
100                       "McAfee",
101                       "AT&T"
102                     )
103              )
104            )
105          )
106  )
107  and (
108    (
109      (
110        length(headers.references) > 0
111        or not any(headers.hops,
112                   any(.fields, strings.ilike(.name, "In-Reply-To"))
113        )
114      )
115      and not (
116        (
117          strings.istarts_with(subject.subject, "RE:")
118          or strings.istarts_with(subject.subject, "RES:")
119          or strings.istarts_with(subject.subject, "R:")
120          or strings.istarts_with(subject.subject, "ODG:")
121          or strings.istarts_with(subject.subject, "答复:")
122          or strings.istarts_with(subject.subject, "AW:")
123          or strings.istarts_with(subject.subject, "TR:")
124          or strings.istarts_with(subject.subject, "FWD:")
125          or regex.imatch(subject.subject,
126                          '(\[[^\]]+\]\s?){0,3}(re|fwd?|automat.*)\s?:.*'
127          )
128        )
129      )
130    )
131    or (length(headers.references) == 0 or length(body.current_thread.text) < 10)
132  )  
133attack_types:
134  - "Callback Phishing"
135tactics_and_techniques:
136  - "Evasion"
137  - "Free email provider"
138  - "Out of band pivot"
139  - "PDF"
140  - "Social engineering"
141detection_methods:
142  - "Exif analysis"
143  - "File analysis"
144  - "Optical Character Recognition"
145  - "Sender analysis"
146id: "ac33f097-af20-554c-b29a-56f21be1b285"
to-top