Link: Display Text Matches Subject Line
Message with short body text contains a single link where the display text matches the subject line. The link is deceptive and the recipient patterns are unusual, such as the recipient's address appearing in the body or undisclosed recipients being used.
Sublime rule (View on GitHub)
1name: "Link: Display Text Matches Subject Line"
2description: "Message with short body text contains a single link where the display text matches the subject line. The link is deceptive and the recipient patterns are unusual, such as the recipient's address appearing in the body or undisclosed recipients being used."
3type: "rule"
4severity: "medium"
5source: |
6 type.inbound
7
8 // short body
9 and length(body.current_thread.text) < 1500
10
11 // suspicious recipient patterns
12 and (
13 // recipient email is contained within the body
14 (
15 length(recipients.to) == 1
16 and all(recipients.to,
17 strings.icontains(body.current_thread.text, .email.email)
18 )
19 )
20 // the sender is the recipient
21 or sender.email.email in map(recipients.to, .email.email)
22 // none of the recipients are valid (generally undisclosed recipients)
23 or not all(recipients.to, .email.domain.valid)
24 )
25 // few overall links
26 and length(body.links) < 10
27 // none of the links are unsubscribe links
28 and not any(body.links,
29 strings.icontains(.display_text, 'unsub')
30 or strings.icontains(.href_url.url, 'unsub')
31 or strings.icontains(.display_text, 'optout')
32 or strings.icontains(.href_url.url, 'optout')
33 or strings.icontains(.display_text, 'subscription')
34 // google confidential email use the subject as a link
35 or .href_url.domain.domain == "confidential-mail.google.com"
36 )
37
38 // even fewer links which are
39 and 0 < length(filter(body.links,
40 // not related to the sender domain
41 .href_url.domain.root_domain != sender.email.domain.root_domain
42 // not related to the recipient domain
43 and not any(recipients.to,
44 .email.domain.root_domain == ..href_url.domain.root_domain
45 )
46 // filter out links common in signatures
47 and not .href_url.domain.root_domain in (
48 "facebook.com",
49 "instagram.com",
50 'twitter.com',
51 'x.com'
52 )
53 // do not contain a display_text (TP samples have the display_text of the subject)
54 // // this removes domains found in signatures
55 and .display_text is not null
56 // not the aka.ms in warning banners
57 and not .href_url.domain.domain == "aka.ms"
58 )
59 ) <= 3
60
61 // exactly one link with display text that matches the subject
62 and length(filter(body.links, subject.subject =~ .display_text)) == 1
63 and (
64 // the link with the display_text of the subject
65 any(filter(body.links, subject.subject =~ .display_text),
66 // when visited is phishing
67 ml.link_analysis(.).credphish.disposition == "phishing"
68 or ml.link_analysis(.).final_dom.display_text == "Verify you are human"
69 )
70 // or the body is cred_theft
71 or any(ml.nlu_classifier(body.current_thread.text).intents,
72 .name == "cred_theft"
73 )
74 )
75
76 // the display text of a link is the subject
77 and subject.subject in map(body.links, .display_text)
78
79 // exclude common in signup links/password resets which are observed in links all the time
80 and not (
81 strings.icontains(subject.subject, 'confirm')
82 or strings.icontains(subject.subject, 'activate')
83 or strings.icontains(subject.subject, 'reset')
84 or strings.icontains(subject.subject, 'unlock')
85 or strings.icontains(subject.subject, 'login')
86 or strings.icontains(subject.subject, 'log in')
87 )
88attack_types:
89 - "BEC/Fraud"
90 - "Credential Phishing"
91tactics_and_techniques:
92 - "Social engineering"
93 - "Evasion"
94detection_methods:
95 - "Header analysis"
96 - "Content analysis"
97 - "Natural Language Understanding"
98 - "URL analysis"
99id: "ba722cf0-b94e-55d2-b29a-df6fab80a164"