Reconnaissance: All recipients cc/bcc'd or undisclosed
Recon messages, a form of deliverability testing, are used to validate whether a recipient address is valid or not, potentially preceding an attack.
All recipients are bcc'd or undisclosed, with no links or attachments, and a short body and subject from an unknown sender.
Sublime rule (View on GitHub)
1name: "Reconnaissance: All recipients cc/bcc'd or undisclosed"
2description: |
3 Recon messages, a form of deliverability testing, are used to validate whether a recipient address is valid or not, potentially preceding an attack.
4
5 All recipients are bcc'd or undisclosed, with no links or attachments, and a short body and subject from an unknown sender.
6type: "rule"
7severity: "low"
8source: |
9 type.inbound
10 and (
11 length(recipients.bcc) > 0
12 or length(recipients.cc) > 0
13 or any(recipients.to, strings.ilike(.display_name, "undisclosed?recipients"))
14 )
15 and (
16 length(subject.base) <= 10
17 or (
18 (
19 strings.ilike(subject.base, "*checking*", "*testing*")
20 or subject.base == body.current_thread.text
21 )
22 and length(subject.base) <= 25
23 )
24 )
25 and length(attachments) == 0
26 // and there are no links. Or all the links are to aka.ms or an extraction from a warning banner that match the senders domain
27 and (
28 length(body.links) == 0
29 or length(filter(body.links,
30 (
31 .display_text is null
32 and .display_url.url == sender.email.domain.root_domain
33 )
34 or .href_url.domain.domain == "aka.ms"
35 )
36 ) == length(body.links)
37 )
38 and (
39 body.current_thread.text is null
40 or length(body.current_thread.text) < 50
41 or (
42 length(body.current_thread.text) < 900
43 // or body is most likely all warning banner ending with a generic greeting
44 and regex.imatch(body.current_thread.text, '.*(hi|hello)')
45 )
46 // body length without disclaimer is shorter than 50 characters
47 or (
48 any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,
49 .name == "disclaimer"
50 ),
51 .text
52 ),
53 (length(body.current_thread.text) - length(.)) < 50
54 )
55 )
56 // matching nlu_classifier 'bec' to smaller messages less than 200
57 or (
58 any(ml.nlu_classifier(body.current_thread.text).intents,
59 .name == "bec" and .confidence in ("high", "medium")
60 )
61 and length(body.current_thread.text) < 200
62 and not regex.icontains(body.html.raw,
63 '(?:<div data-smartmail=|gmail_signature(?:_[^"]*)?)'
64 ) // not condition to exclude smaller messages with a legitimate email signature
65 and length(body.previous_threads) == 0 // excluding messages with simple responses to other threads
66 )
67 )
68 and profile.by_sender().prevalence != "common"
69 and not profile.by_sender().solicited
70 and not profile.by_sender().any_messages_benign
71
72 // negate highly trusted sender domains unless they fail DMARC authentication
73 and (
74 (
75 sender.email.domain.root_domain in $high_trust_sender_root_domains
76 and not headers.auth_summary.dmarc.pass
77 )
78 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
79 )
80tags:
81 - "Attack surface reduction"
82 - "Deliverability testing"
83attack_types:
84 - "Reconnaissance"
85detection_methods:
86 - "Content analysis"
87 - "Header analysis"
88 - "Sender analysis"
89id: "420f60d3-5d10-5384-9253-9521a758e799"