Detection rules › Sublime MQL

Link: Suspicious SharePoint document name

Severity
low
Type
rule
Source
github.com/sublime-security/sublime-rules

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.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesFree file host, Evasion

Event coverage

Rule body MQL

type.inbound
and strings.ilike(subject.subject, "*shared*", "*invit*")
and strings.ilike(body.current_thread.text,
                  "*shared a file with you*",
                  "*shared with you*",
                  "*invited you to access a file*"
)
and not strings.ilike(body.current_thread.text, "invited you to edit")
and (
  // use the display text of the link to determine the name of the file
  any(filter(body.links,
             (
               .href_url.domain.root_domain == "sharepoint.com"
               or .href_url.domain.root_domain == "1drv.ms"
               // handle urls with mimecast rewriting
               or (
                 .href_url.domain.root_domain == 'mimecastprotect.com'
                 and strings.icontains(.href_url.query_params,
                                       '.sharepoint.com'
                 )
               )
             )
             and .display_text != "Open"
             and not .href_url.domain.domain in $tenant_domains
      ),

      // the file name does not include lowercase letters, while allowing for non letter chars
      regex.match(.display_text, '^[^a-z]+$')

      // file sharing service references
      or strings.icontains(.display_text, 'dropbox')
      or strings.icontains(.display_text, 'docusign')

      // file name lures
      // secure theme
      or regex.icontains(.display_text, 'secured?.*(?:file|document|docs|fax)')
      or regex.icontains(.display_text, 'important.*(?:file|document|docs|fax)')
      or regex.icontains(.display_text, 'shared?.*(?:file|document|docs|fax)')
      or regex.icontains(.display_text, 'protected.*(?:file|document|docs|fax)')
      or regex.icontains(.display_text, 'encrypted.*(?:file|document|docs|fax)')

      // scanner theme
      or strings.icontains(.display_text, 'scanne[rd]_')
      // image themed
      or strings.icontains(.display_text, '_IMG_')
      or regex.icontains(.display_text, '^IMG[_-](?:\d|\W)+$')

      // digits
      or regex.icontains(.display_text, 'doc(?:ument)?\s?\d+$')
      or regex.icontains(.display_text, '^\d+$')

      // onedrive theme
      or strings.icontains(.display_text, 'one_docx')
      or strings.icontains(.display_text, 'OneDrive')
      or regex.icontains(.display_text, 'A document.*One.?Drive')

      // action in file name
      or strings.icontains(.display_text, 'click here')
      or strings.icontains(.display_text, 'Download PDF')
      or strings.icontains(.display_text, 'Validate')
      or strings.icontains(.display_text, 'sent you ')

      // limited file name to "confidential"
      or .display_text =~ 'Confidentiality'
      or .display_text =~ 'Confidential'

      // invoice themes
      or any(ml.nlu_classifier(.display_text).entities, .name == "financial")
      or strings.icontains(.display_text, 'payment')
      or strings.icontains(.display_text, 'invoice')
      or regex.icontains(.display_text, 'INV(?:_|\s)?\d+$')
      // starts with INV_ or INV\x20
      or regex.icontains(.display_text, '^INV(?:_|\s)')
      or regex.icontains(.display_text, 'P[O0]\W+?\d+$')
      or strings.icontains(.display_text, 'receipt')
      or strings.icontains(.display_text, 'billing')
      or (
        strings.icontains(.display_text, 'statement')
        and not .display_text =~ "Privacy Statement"
      )
      or strings.icontains(.display_text, 'Past Due')
      or regex.icontains(.display_text, 'Remit(tance)?')
      or strings.icontains(.display_text, 'Purchase Order')

      // contract language
      or strings.icontains(.display_text, 'settlement')
      or strings.icontains(.display_text, 'contract agreement')
      or regex.icontains(.display_text, 'Pr[0o]p[0o]sal')
      or strings.icontains(.display_text, 'contract doc')

      // generic document name AND additional suspicious indicator
      or (
        regex.imatch(.display_text, 'documents?')
        and (
          // Find the share comment in the HTML and check for reply/forward "impersonation"
          regex.icontains(body.html.raw,
                          '<p style="font-size:16px;color:#323130;margin:40px 20px 28px">(re|fwd?)'
          )
        )
      )

      // Payroll/HR
      // section also used in abuse_dropbox_sus_names.yml with modified input
      or strings.icontains(.display_text, 'Payroll')
      or strings.icontains(.display_text, 'Employee Pay\b')
      or strings.icontains(.display_text, 'Salary')
      or strings.icontains(.display_text, 'Benefit Enrollment')
      or strings.icontains(.display_text, 'Employee Handbook')
      or strings.icontains(.display_text, 'Reimbursement Approved')
      or regex.icontains(.display_text,
                         '(?:Faculty|Staff)\s*(?:\w+\s+){0,3}\s*Eval(?:uation)?'
      )

      // pattern of `sld - open items`
      or strings.istarts_with(.display_text,
                              strings.concat(sender.email.domain.sld, ' - ')
      )
  )
)
and (
  // and sender has never had email sent to them
  profile.by_sender().solicited == false
  // often times no-reply is soliticed due to various behaviors
  or sender.email.email == "no-reply@sharepointonline.com"
)

Detection logic

Scope: inbound message.

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.

  1. inbound message
  2. subject.subject matches any of 2 patterns
    • *shared*
    • *invit*
  3. body.current_thread.text matches any of 3 patterns
    • *shared a file with you*
    • *shared with you*
    • *invited you to access a file*
  4. not:
    • body.current_thread.text matches 'invited you to edit'
  5. any of filter(body.links) where any holds:
    • .display_text matches '^[^a-z]+$'
    • .display_text contains 'dropbox'
    • .display_text contains 'docusign'
    • .display_text matches 'secured?.*(?:file|document|docs|fax)'
    • .display_text matches 'important.*(?:file|document|docs|fax)'
    • .display_text matches 'shared?.*(?:file|document|docs|fax)'
    • .display_text matches 'protected.*(?:file|document|docs|fax)'
    • .display_text matches 'encrypted.*(?:file|document|docs|fax)'
    • .display_text contains 'scanne[rd]_'
    • .display_text contains '_IMG_'
    • .display_text matches '^IMG[_-](?:\\d|\\W)+$'
    • .display_text matches 'doc(?:ument)?\\s?\\d+$'
    • .display_text matches '^\\d+$'
    • .display_text contains 'one_docx'
    • .display_text contains 'OneDrive'
    • .display_text matches 'A document.*One.?Drive'
    • .display_text contains 'click here'
    • .display_text contains 'Download PDF'
    • .display_text contains 'Validate'
    • .display_text contains 'sent you '
    • .display_text is 'Confidentiality'
    • .display_text is 'Confidential'
    • any of ml.nlu_classifier(.display_text).entities where:
      • .name is 'financial'
    • .display_text contains 'payment'
    • .display_text contains 'invoice'
    • .display_text matches 'INV(?:_|\\s)?\\d+$'
    • .display_text matches '^INV(?:_|\\s)'
    • .display_text matches 'P[O0]\\W+?\\d+$'
    • .display_text contains 'receipt'
    • .display_text contains 'billing'
    • all of:
      • .display_text contains 'statement'
      • not:
        • .display_text is 'Privacy Statement'
    • .display_text contains 'Past Due'
    • .display_text matches 'Remit(tance)?'
    • .display_text contains 'Purchase Order'
    • .display_text contains 'settlement'
    • .display_text contains 'contract agreement'
    • .display_text matches 'Pr[0o]p[0o]sal'
    • .display_text contains 'contract doc'
    • all of:
      • .display_text matches 'documents?'
      • body.html.raw matches '<p style="font-size:16px;color:#323130;margin:40px 20px 28px">(re|fwd?)'
    • .display_text contains 'Payroll'
    • .display_text contains 'Employee Pay\\b'
    • .display_text contains 'Salary'
    • .display_text contains 'Benefit Enrollment'
    • .display_text contains 'Employee Handbook'
    • .display_text contains 'Reimbursement Approved'
    • .display_text matches '(?:Faculty|Staff)\\s*(?:\\w+\\s+){0,3}\\s*Eval(?:uation)?'
    • strings.istarts_with(.display_text)
  6. any of:
    • profile.by_sender().solicited is False
    • sender.email.email is 'no-reply@sharepointonline.com'

Inspects: body.current_thread.text, body.html.raw, body.links, body.links[].display_text, body.links[].href_url.domain.domain, body.links[].href_url.domain.root_domain, body.links[].href_url.query_params, sender.email.domain.sld, sender.email.email, subject.subject, type.inbound. Sensors: ml.nlu_classifier, profile.by_sender, regex.icontains, regex.imatch, regex.match, strings.concat, strings.icontains, strings.ilike, strings.istarts_with. Reference lists: $tenant_domains.

Indicators matched (59)

FieldMatchValue
strings.ilikesubstring*shared*
strings.ilikesubstring*invit*
strings.ilikesubstring*shared a file with you*
strings.ilikesubstring*shared with you*
strings.ilikesubstring*invited you to access a file*
strings.ilikesubstringinvited you to edit
body.links[].href_url.domain.root_domainequalssharepoint.com
body.links[].href_url.domain.root_domainequals1drv.ms
body.links[].href_url.domain.root_domainequalsmimecastprotect.com
strings.icontainssubstring.sharepoint.com
regex.matchregex^[^a-z]+$
strings.icontainssubstringdropbox
47 more
strings.icontainssubstringdocusign
regex.icontainsregexsecured?.*(?:file|document|docs|fax)
regex.icontainsregeximportant.*(?:file|document|docs|fax)
regex.icontainsregexshared?.*(?:file|document|docs|fax)
regex.icontainsregexprotected.*(?:file|document|docs|fax)
regex.icontainsregexencrypted.*(?:file|document|docs|fax)
strings.icontainssubstringscanne[rd]_
strings.icontainssubstring_IMG_
regex.icontainsregex^IMG[_-](?:\d|\W)+$
regex.icontainsregexdoc(?:ument)?\s?\d+$
regex.icontainsregex^\d+$
strings.icontainssubstringone_docx
strings.icontainssubstringOneDrive
regex.icontainsregexA document.*One.?Drive
strings.icontainssubstringclick here
strings.icontainssubstringDownload PDF
strings.icontainssubstringValidate
strings.icontainssubstringsent you
filter(body.links)[].display_textequalsConfidentiality
filter(body.links)[].display_textequalsConfidential
ml.nlu_classifier(filter(body.links)[].display_text).entities[].nameequalsfinancial
strings.icontainssubstringpayment
strings.icontainssubstringinvoice
regex.icontainsregexINV(?:_|\s)?\d+$
regex.icontainsregex^INV(?:_|\s)
regex.icontainsregexP[O0]\W+?\d+$
strings.icontainssubstringreceipt
strings.icontainssubstringbilling
strings.icontainssubstringstatement
filter(body.links)[].display_textequalsPrivacy Statement
strings.icontainssubstringPast Due
regex.icontainsregexRemit(tance)?
strings.icontainssubstringPurchase Order
strings.icontainssubstringsettlement
strings.icontainssubstringcontract agreement
regex.icontainsregexPr[0o]p[0o]sal
strings.icontainssubstringcontract doc
regex.imatchregexdocuments?
regex.icontainsregex<p style="font-size:16px;color:#323130;margin:40px 20px 28px">(re|fwd?)
strings.icontainssubstringPayroll
strings.icontainssubstringEmployee Pay\b
strings.icontainssubstringSalary
strings.icontainssubstringBenefit Enrollment
strings.icontainssubstringEmployee Handbook
strings.icontainssubstringReimbursement Approved
regex.icontainsregex(?:Faculty|Staff)\s*(?:\w+\s+){0,3}\s*Eval(?:uation)?
sender.email.emailequalsno-reply@sharepointonline.com