Suspicious invoice reference with missing or image-only attachments

This rule flags emails that reference invoices or payments but have suspicious characteristics: attachments are either missing or only images. It also checks for misleading links disguised as attachments and the presence of invoice-related keywords. The rule looks for potential credential theft or unusual requests, making it a strong indicator of phishing attempts.

Sublime rule (View on GitHub)

 1name: "Suspicious invoice reference with missing or image-only attachments"
 2description: "This rule flags emails that reference invoices or payments but have suspicious characteristics: attachments are either missing or only images. It also checks for misleading links disguised as attachments and the presence of invoice-related keywords. The rule looks for potential credential theft or unusual requests, making it a strong indicator of phishing attempts."
 3type: "rule"
 4severity: "high"
 5source: |
 6  type.inbound
 7  
 8  // more than 0 but less than 20 links
 9  and 0 < length(body.links) < 20
10  
11  // all attachments are images or there are 0 attachments
12  and (
13    length(attachments) > 0 and all(attachments, .file_type in $file_types_images)
14    or length(attachments) == 0
15  )
16  
17  // subject contains payment/invoice language
18  and (
19    any(ml.nlu_classifier(subject.subject).tags, .name in ("payment", "invoice"))
20    or regex.contains(subject.subject,
21                      '(?:\binv(?:oice|o)\b|in_v|in-voice|pay(?:ment|mnt)|pymt|\brec(?:eipt|pt|iept)\b|rcpt|confirm(?:ation)|cnfrm|cnf|po\b|p\.o\.|purch(?:ase)?-?order|\bord(?:er)?\b|bill(?:ing)|billing-info|transact(?:ion)|txn|trx|\bstmt\b|\bstmnt\b|remit(?:tance)|rmt|remndr|remind|\bdue(?:-date)\b|ovrdue|overdue|\bbal(?:ance)\b|\bpaid(?:-invoice)\b)',
22                      // suspicious invoice format
23                      '\d{6}\b.{10,30}(\d{2}\.){3}pdf'
24    )
25  )
26  
27  // link display text ends in a file extension or contain common payment terms
28  and (
29    any(body.links,
30        regex.imatch(.display_text,
31                     '.*\.(?:doc|docm|docx|dot|dotm|pdf|ppa|ppam|ppsm|ppt|pptm|pptx|wbk|xla|xlam|xlm|xls|xlsb|xlsm|xlsx|xlt|xltm)$'
32        )
33    )
34    or any(body.links,
35           regex.icontains(.display_text,
36                           '(?:\binv(?:oice|o)\b|in_v|in-voice|pay(?:ment|mnt)|pymt|\brec(?:eipt|pt|iept)\b|rcpt|req(?:uest)|rqst|\brq\b|\bpo\b|p\.o\.|purch(?:ase)?-?order|\bord(?:er)?\b|bill(?:ing)|billing-info|transact(?:ion)|txn|trx|\bstmt\b|\bstmnt\b|remit(?:tance)|rmt|remndr|remind|\bdue(?:-date)\b|ovrdue|overdue|\bbal(?:ance)\b|\bpaid(?:-invoice)\b)'
37           )
38    )
39  )
40  // the body references an attachment 
41  and (
42    strings.contains(body.current_thread.text, "attach")
43    // negate warning banners warning about the attachment(s)
44    and (
45      not (
46        (
47          regex.count(body.current_thread.text, "attach") == 1
48          and regex.icontains(body.current_thread.text,
49                              "(caution|warning).{0,30}attach"
50          )
51        )
52        or ( // WeTransfer expiry warning notification
53          sender.email.email == "noreply@wetransfer.com"
54          and any(body.links,
55                  .display_text == "Don't send me these expiry reminders anymore"
56          )
57        )
58      )
59    )
60  )
61  
62  // body text is determined to contain cred_theft language by nlu or contains a request with suspicious keywords
63  and (
64    any(ml.nlu_classifier(body.current_thread.text).intents,
65        .name == "cred_theft"
66    )
67    or any(ml.nlu_classifier(body.current_thread.text).entities,
68           .name == "request"
69           and (
70             strings.icontains(.text, "kindly")
71             or strings.icontains(.text, "please see attached")
72           )
73    )
74  )
75  // negate highly trusted sender domains unless they fail DMARC authentication
76  and (
77    (
78      sender.email.domain.root_domain in $high_trust_sender_root_domains
79      and not headers.auth_summary.dmarc.pass
80    )
81    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
82  )
83  and not profile.by_sender().solicited  
84
85attack_types:
86  - "Credential Phishing"
87tactics_and_techniques:
88  - "Social engineering"
89detection_methods:
90  - "Content analysis"
91  - "Computer Vision"
92  - "File analysis"
93  - "Natural Language Understanding"
94  - "Sender analysis"
95id: "466c1680-b9ff-5bd0-baf8-e65cca99d18b"
to-top