Reconnaissance: Large unknown recipient list
Recon messages, a form of deliverability testing, are used to validate whether a recipient address is valid or not, potentially preceding an attack.
There's a large number of recipients that are unknown to the organization, no links or attachments, and a short body and subject from an unknown sender.
Sublime rule (View on GitHub)
1name: "Reconnaissance: Large unknown recipient list"
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 There's a large number of recipients that are unknown to the organization, 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.to) > 10
12 and length(filter(recipients.to,
13 .email.domain.domain not in $org_domains
14 and .email.email not in $recipient_emails
15 and (
16 .email.domain.valid
17 or strings.icontains(.display_name, "undisclosed")
18 )
19 )
20 ) >= 10
21 )
22 and (
23 length(subject.subject) <= 10
24 or subject.subject == body.current_thread.text
25 or (subject.is_reply and length(body.previous_threads) == 0)
26 )
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 or network.whois(.display_url.domain).days_old < 30
36 )
37 ) == length(body.links)
38 )
39 and (
40 length(attachments) == 0
41 or (
42 length(attachments) == 1
43 and any(attachments,
44 .file_type in ("pdf", "png", "jpg", "tif", "heif", "doc", "docx")
45 and any(file.explode(.),
46 length(.scan.ocr.raw) < 20
47 or length(.scan.strings.strings) == 1
48 )
49 )
50 )
51 )
52 and (
53 body.current_thread.text is null
54 or length(body.current_thread.text) < 50
55 // body length without disclaimer is shorter than 50 characters
56 or (
57 any(map(filter(ml.nlu_classifier(body.current_thread.text).entities,
58 .name == "disclaimer"
59 ),
60 .text
61 ),
62 (length(body.current_thread.text) - length(.)) < 50
63 )
64 )
65 )
66 and profile.by_sender().prevalence != "common"
67 and not profile.by_sender().solicited
68 and not profile.by_sender().any_messages_benign
69
70 // negate highly trusted sender domains unless they fail DMARC authentication
71 and (
72 (
73 sender.email.domain.root_domain in $high_trust_sender_root_domains
74 and not headers.auth_summary.dmarc.pass
75 )
76 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
77 )
78tags:
79 - "Attack surface reduction"
80 - "Deliverability testing"
81attack_types:
82 - "Reconnaissance"
83detection_methods:
84 - "Content analysis"
85 - "Header analysis"
86 - "Sender analysis"
87id: "24783a28-b6e2-5cca-9f6d-19c2cdfa6a9a"