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    )
23  )
24  
25  // link display text ends in a file extension or contain common payment terms
26  and (
27    any(body.links,
28        regex.imatch(.display_text,
29                     '.*\.(?:doc|docm|docx|dot|dotm|pdf|ppa|ppam|ppsm|ppt|pptm|pptx|wbk|xla|xlam|xlm|xls|xlsb|xlsm|xlsx|xlt|xltm)$'
30        )
31    )
32    or any(body.links,
33           regex.icontains(.display_text,
34                           '(?:\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)'
35           )
36    )
37  )
38  // the body references an attachment 
39  and (
40    strings.contains(body.current_thread.text, "attach")
41    // negate warning banners warning about the attachment(s)
42    and (
43      not (
44        (
45          regex.count(body.current_thread.text, "attach") == 1
46          and regex.icontains(body.current_thread.text,
47                              "(caution|warning).{0,30}attach"
48          )
49        )
50        or ( // WeTransfer expiry warning notification
51          sender.email.email == "noreply@wetransfer.com"
52          and any(body.links,
53                  .display_text == "Don't send me these expiry reminders anymore"
54          )
55        )
56      )
57    )
58  )
59  
60  // body text is determined to contain cred_theft language by nlu or contains a request with the word kindly
61  and (
62    any(ml.nlu_classifier(body.current_thread.text).intents,
63        .name == "cred_theft"
64    )
65    or any(ml.nlu_classifier(body.current_thread.text).entities,
66           .name == "request" and strings.icontains(.text, "kindly")
67    )
68  )
69  and not profile.by_sender().solicited  
70
71attack_types:
72  - "Credential Phishing"
73tactics_and_techniques:
74  - "Social engineering"
75detection_methods:
76  - "Content analysis"
77  - "Computer Vision"
78  - "File analysis"
79  - "Natural Language Understanding"
80  - "Sender analysis"
81id: "466c1680-b9ff-5bd0-baf8-e65cca99d18b"
to-top