SharePoint OTP for filename matching org name

Detects Microsoft One-Time Passcode (OTP) messages where the shared document’s filename matches the sending organization's name. This typically indicates the recipient has verified their email address and is about to access a SharePoint file. Matching the document name to the sender's org is a pattern observed in multi-stage credential phishing campaigns, where attackers use branded file names to increase credibility and lure users into interacting with malicious content.

Sublime rule (View on GitHub)

 1name: "SharePoint OTP for filename matching org name"
 2description: "Detects Microsoft One-Time Passcode (OTP) messages where the shared document’s filename matches the sending organization's name. This typically indicates the recipient has verified their email address and is about to access a SharePoint file. Matching the document name to the sender's org is a pattern observed in multi-stage credential phishing campaigns, where attackers use branded file names to increase credibility and lure users into interacting with malicious content."
 3type: "rule"
 4severity: "medium"
 5source: |
 6  type.inbound
 7  // Microsoft sender
 8  and sender.email.domain.root_domain == "microsoft.com"
 9  // message ID contains the proper format for OTP messeges
10  and (
11    (
12      strings.istarts_with(headers.message_id, '<OneTimePasscode-')
13      and strings.iends_with(headers.message_id, '@odspnotify>')
14    )
15    // deal with Google thinking the message ID is "broke"
16    or (
17      strings.icontains(headers.message_id, 'SMTPIN_ADDED_BROKEN')
18      and any(headers.hops,
19          any(.fields,
20              .name == "X-Google-Original-Message-ID"
21              and strings.istarts_with(.value, '<OneTimePasscode-')
22              and strings.iends_with(.value, '@odspnotify>')
23          )
24      )
25    )
26  )
27  // make sure the body has the phrase we need to get the document name
28  and strings.icontains(body.current_thread.text,
29                        'For security purposes, you must enter the code below to verify your account to access'
30  )
31  // extract the filename and org name from the body and see if they are equal
32  and any(regex.iextract(body.current_thread.text,
33                         'For security purposes, you must enter the code below to verify your account to access (?P<doc_name>.*)\. The code will only work for.*This email is generated through (?P<org_name>.*)''s use of Microsoft 365\.'
34          ),
35          .named_groups["doc_name"] =~ .named_groups["org_name"]
36  )
37    
38
39attack_types:
40  - "Credential Phishing"
41tactics_and_techniques:
42  - "Impersonation: Brand"
43  - "Social engineering"
44detection_methods:
45  - "Content analysis"
46  - "Header analysis"
47id: "89911cbd-8865-5781-be99-04aa28660c0c"
to-top