Link: Suspicious SharePoint document name
The detection rule is intended to match on emails sent from SharePoint indicating a shared file to the recipient that contain suspicious content within the document name. The Link display text is leveraged to identify the name of the shared file.
Sublime rule (View on GitHub)
1name: "Link: Suspicious SharePoint document name"
2description: "The detection rule is intended to match on emails sent from SharePoint indicating a shared file to the recipient that contain suspicious content within the document name. The Link display text is leveraged to identify the name of the shared file."
3type: "rule"
4severity: "low"
5source: |
6 type.inbound
7 and strings.ilike(subject.subject, "*shared*", "*invit*")
8 and strings.ilike(body.current_thread.text,
9 "*shared a file with you*",
10 "*shared with you*",
11 "*invited you to access a file*"
12 )
13 and not strings.ilike(body.current_thread.text, "invited you to edit")
14 and (
15 // use the display text of the link to determine the name of the file
16 any(filter(body.links,
17 (
18 .href_url.domain.root_domain == "sharepoint.com"
19 or .href_url.domain.root_domain == "1drv.ms"
20 // handle urls with mimecast rewriting
21 or (
22 .href_url.domain.root_domain == 'mimecastprotect.com'
23 and strings.icontains(.href_url.query_params,
24 '.sharepoint.com'
25 )
26 )
27 )
28 and .display_text != "Open"
29 ),
30
31 // the file name does not include lowercase letters, while allowing for non letter chars
32 regex.match(.display_text, '^[^a-z]+$')
33
34 // file sharing service references
35 or strings.icontains(.display_text, 'dropbox')
36 or strings.icontains(.display_text, 'docusign')
37
38 // file name lures
39 // secure theme
40 or regex.icontains(.display_text, 'secured?.*(?:file|document|docs|fax)')
41 or regex.icontains(.display_text, 'important.*(?:file|document|docs|fax)')
42 or regex.icontains(.display_text, 'shared?.*(?:file|document|docs|fax)')
43 or regex.icontains(.display_text, 'protected.*(?:file|document|docs|fax)')
44 or regex.icontains(.display_text, 'encrypted.*(?:file|document|docs|fax)')
45
46 // scanner theme
47 or strings.icontains(.display_text, 'scanne[rd]_')
48 // image themed
49 or strings.icontains(.display_text, '_IMG_')
50 or regex.icontains(.display_text, '^IMG[_-](?:\d|\W)+$')
51
52 // digits
53 or regex.icontains(.display_text, 'doc(?:ument)?\s?\d+$')
54 or regex.icontains(.display_text, '^\d+$')
55
56 // onedrive theme
57 or strings.icontains(.display_text, 'one_docx')
58 or strings.icontains(.display_text, 'OneDrive')
59 or regex.icontains(.display_text, 'A document.*One.?Drive')
60
61 // action in file name
62 or strings.icontains(.display_text, 'click here')
63 or strings.icontains(.display_text, 'Download PDF')
64 or strings.icontains(.display_text, 'Validate')
65
66 // limited file name to "confidential"
67 or .display_text =~ 'Confidentiality'
68 or .display_text =~ 'Confidential'
69
70 // invoice themes
71 or any(ml.nlu_classifier(.display_text).entities, .name == "financial")
72 or strings.icontains(.display_text, 'payment')
73 or strings.icontains(.display_text, 'invoice')
74 or regex.icontains(.display_text, 'INV(?:_|\s)?\d+$')
75 // starts with INV_ or INV\x20
76 or regex.icontains(.display_text, '^INV(?:_|\s)')
77 or regex.icontains(.display_text, 'P[O0]\W+?\d+$')
78 or strings.icontains(.display_text, 'receipt')
79 or strings.icontains(.display_text, 'billing')
80 or (
81 strings.icontains(.display_text, 'statement')
82 and not .display_text =~ "Privacy Statement"
83 )
84 or strings.icontains(.display_text, 'Past Due')
85 or regex.icontains(.display_text, 'Remit(tance)?')
86 or strings.icontains(.display_text, 'Purchase Order')
87
88 // contract language
89 or strings.icontains(.display_text, 'settlement')
90 or strings.icontains(.display_text, 'contract agreement')
91 or regex.icontains(.display_text, 'Pr[0o]p[0o]sal')
92 or strings.icontains(.display_text, 'contract doc')
93
94 // generic document name AND additional suspicious indicator
95 or (
96 regex.imatch(.display_text, 'documents?')
97 and (
98 // Find the share comment in the HTML and check for reply/forward "impersonation"
99 regex.icontains(body.html.raw, '<p style="font-size:16px;color:#323130;margin:40px 20px 28px">(re|fwd?)')
100 )
101 )
102
103 // Payroll/HR
104 // section also used in abuse_dropbox_sus_names.yml with modified input
105 or strings.icontains(.display_text, 'Payroll')
106 or strings.icontains(.display_text, 'Employee Pay\b')
107 or strings.icontains(.display_text, 'Salary')
108 or strings.icontains(.display_text, 'Benefit Enrollment')
109 or strings.icontains(.display_text, 'Employee Handbook')
110 or strings.icontains(.display_text, 'Reimbursement Approved')
111 or regex.icontains(.display_text, '(?:Faculty|Staff)\s*(?:\w+\s+){0,3}\s*Eval(?:uation)?')
112 )
113 )
114
115 // and it's not an internal share
116 and not any(headers.hops,
117 any(.fields,
118 .name == "X-MS-Exchange-CrossTenant-AuthAs"
119 and .value == "Internal"
120 )
121 )
122 and (
123 // and sender has never had email sent to them
124 profile.by_sender().solicited == false
125 // often times no-reply is soliticed due to various behaviors
126 or sender.email.email == "no-reply@sharepointonline.com"
127 )
128
129attack_types:
130 - "Credential Phishing"
131tactics_and_techniques:
132 - "Free file host"
133 - "Evasion"
134detection_methods:
135 - "Content analysis"
136id: "f95fee6e-8127-5888-a9a9-4bbeabfe33a3"