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"

Related rules

to-top