Credential Phishing: Fake Password Expiration from New and Unsolicited sender
This rule looks for password expiration verbiage in the subject and body. Requiring between 1 - 9 links, a short body, and NLU in addition to statically specified term anchors. High trust senders are also negated.
Sublime rule (View on GitHub)
1name: "Credential Phishing: Fake Password Expiration from New and Unsolicited sender"
2description: "This rule looks for password expiration verbiage in the subject and body. Requiring between 1 - 9 links, a short body, and NLU in addition to statically specified term anchors. High trust senders are also negated."
3type: "rule"
4severity: "medium"
5source: |
6 type.inbound
7
8 // few links
9 and 0 < length(body.links) < 10
10
11 // no attachments or suspicious attachment
12 and (
13 length(attachments) == 0
14 or any(attachments,
15 .file_type in ("pdf", "doc", "docx")
16 and any(file.explode(.),
17 .scan.entropy.entropy > 7 and length(.scan.ocr.raw) < 20
18 )
19 )
20 )
21
22 // body contains expire, expiration, loose, lose
23 and (
24 regex.icontains(body.current_thread.text,
25 '(expir(e)?(ation|s)|\blo(o)?se\b|office 365|re.{0,3}confirm)'
26 )
27 and not strings.icontains(body.current_thread.text, 'link expires in ')
28 )
29
30 // subject or body contains account or access
31 and any([subject.subject, body.current_thread.text],
32 regex.icontains(body.current_thread.text, "account|access|your email")
33 )
34
35 // subject or body must contains password
36 and any([subject.subject, body.current_thread.text],
37 regex.icontains(body.current_thread.text, '\bpassword\b')
38 )
39 and (
40 any(ml.nlu_classifier(body.current_thread.text).intents,
41 .name == "cred_theft" and .confidence == "high"
42 )
43 or length(filter([
44 "password",
45 "expiration",
46 "expire",
47 "expiring",
48 "kindly",
49 "renew",
50 "review",
51 "click below",
52 "kicked out",
53 "prevent",
54 "required now",
55 "immediate action",
56 "security update",
57 "blocked",
58 "locked",
59 "interruption"
60 ],
61 strings.icontains(body.current_thread.text, .)
62 )
63 ) >= 3
64 )
65
66 // body length between 200 and 2000
67 and 200 < length(body.current_thread.text) < 2000
68
69 // and no false positives and not solicited
70 and (
71 not profile.by_sender().any_false_positives
72 and not profile.by_sender().solicited
73 )
74
75 // not a reply
76 and (
77 length(headers.references) == 0
78 or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To")))
79 )
80
81 // negate highly trusted sender domains unless they fail DMARC authentication
82 and (
83 (
84 sender.email.domain.root_domain in $high_trust_sender_root_domains
85 and (
86 any(distinct(headers.hops, .authentication_results.dmarc is not null),
87 strings.ilike(.authentication_results.dmarc, "*fail")
88 )
89 )
90 )
91 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
92 )
93
94attack_types:
95 - "Credential Phishing"
96tactics_and_techniques:
97 - "Social engineering"
98detection_methods:
99 - "Content analysis"
100 - "Natural Language Understanding"
101 - "Sender analysis"
102id: "5d9c3a75-5f57-5d0c-a07f-0f300bbde076"