Detection rules › Sublime MQL

Sublime MQL rules: eml

Attachment: EML with SharePoint files shared from GoDaddy federated tenants

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

Detects EML attachments containing SharePoint links with 'netorg' subdomain patterns, which may indicate suspicious redirection tactics or domain abuse.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Impersonation: Brand, Social engineering

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • type

Rule body

type.inbound
and length(filter(attachments,
                  .file_extension == "eml" or .content_type == "message/rfc822"
           )
) == 1
and any(attachments,
        any(file.parse_eml(.).body.links,
            strings.starts_with(.href_url.domain.subdomain, 'netorg')
            and .href_url.domain.root_domain == "sharepoint.com"
        )
)

Detection logic

Scope: inbound message.

Detects EML attachments containing SharePoint links with 'netorg' subdomain patterns, which may indicate suspicious redirection tactics or domain abuse.

  1. inbound message
  2. length(filter(attachments, .file_extension == 'eml' or .content_type == 'message/rfc822')) is 1
  3. any of attachments where:
    • any of file.parse_eml(.).body.links where all hold:
      • .href_url.domain.subdomain starts with 'netorg'
      • .href_url.domain.root_domain is 'sharepoint.com'

Inspects: attachments[].content_type, attachments[].file_extension, type.inbound. Sensors: file.parse_eml, strings.starts_with.

Indicators matched (4)

FieldMatchValue
attachments[].file_extensionequalseml
attachments[].content_typeequalsmessage/rfc822
strings.starts_withprefixnetorg
file.parse_eml(attachments[]).body.links[].href_url.domain.root_domainequalssharepoint.com

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    any(file.parse_eml(attachments).body.links)
      and
        file.parse_eml(attachments[]).body.links[].href_url.domain.root_domain eq "sharepoint.com"
        file.parse_eml(attachments[]).body.links[].href_url.domain.subdomain starts_with "netorg"
  filter(attachments, .file_extension == 'eml' or .content_type == 'message/rfc822') length_compare "1"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"

Attachment: EML with Sharepoint link likely unrelated to sender

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

Detects EML attachments containing SharePoint links where the subdomain differs significantly from the sender's domain, potentially indicating SharePoint impersonation or domain spoofing tactics.

Threat classification

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

CategoryValues
Attack typesBEC/Fraud, Credential Phishing
Tactics and techniquesImpersonation: Brand, Social engineering, Evasion

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • attachments
  • body
  • body.html
  • headers
  • headers.auth_summary
  • headers.domains
  • sender.email
  • type

Rule body

type.inbound
and length(filter(attachments,
                  .file_extension == "eml" or .content_type == "message/rfc822"
           )
) == 1
and any(attachments,
        any(filter(file.parse_eml(.).body.links,
                   .href_url.domain.root_domain == 'sharepoint.com'
            ),
            // Normalize Levenshtein distance by string length (0 = identical, 0.7+ = different)
            // Working with what we have in MQL, considering we dont have max() or any other forms of string distancing
            (
              (
                strings.iends_with(.href_url.domain.subdomain,
                                   '-my'
                ) // common Sharepoint subdomain suffix
                and (
                  (
                    strings.ilevenshtein(.href_url.domain.subdomain,
                                         sender.email.domain.sld
                    ) - 3 // subtract aforementioned suffix for more accurate calculation
                  ) / (
                    (
                      (length(.href_url.domain.subdomain) - 3) + length(sender.email.domain.sld
                      )
 + (
                        (
                          (length(.href_url.domain.subdomain) - 3) - length(sender.email.domain.sld
                          )
                        ) + (
                          length(sender.email.domain.sld) - (
                            length(.href_url.domain.subdomain) - 3
                          )
                        )
                      )
                    ) / 2.0 // to ensure we keep the result as a float
                  )
                ) > 0.7 // customizable threshold
              )
              or (
                not strings.iends_with(.href_url.domain.subdomain,
                                       '-my'
                ) // no suffix, continue with original calculation
                and (
                  strings.ilevenshtein(.href_url.domain.subdomain,
                                       sender.email.domain.sld
                  ) / (
                    (
                      length(.href_url.domain.subdomain) + length(sender.email.domain.sld
                      )
 + (
                        (
                          length(.href_url.domain.subdomain) - length(sender.email.domain.sld
                          )
                        ) + (
                          length(sender.email.domain.sld) - length(.href_url.domain.subdomain
                          )
                        )
                      )
                    ) / 2.0 // to ensure we keep the result as a float
                  )
                ) > 0.7 // customizable threshold
              )
            )
            and not strings.icontains(.href_url.path, sender.email.local_part)
            and not any($org_slds,
                        strings.icontains(..href_url.domain.subdomain, .)
            )

            // it is either a OneNote or PDF file, or unknown
            and regex.icontains(.href_url.path, '\/:[obu]:\/(?:p|g\/personal)')
        )
)
// a way to negate long threads
// the full thread must be less than 6 times the length of the current thread
and length(body.html.inner_text) < 6 * length(body.current_thread.text)
and sender.email.domain.root_domain not in (
  "sharepoint.com",
  "sharepointonline.com"
)

// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
// negate instances where proofpoint sends a review of a reported message via analyzer 
and not (
  any(headers.domains, .root_domain == "pphosted.com")
  and headers.auth_summary.spf.pass
  and headers.auth_summary.dmarc.pass
) 

Detection logic

Scope: inbound message.

Detects EML attachments containing SharePoint links where the subdomain differs significantly from the sender's domain, potentially indicating SharePoint impersonation or domain spoofing tactics.

  1. inbound message
  2. length(filter(attachments, .file_extension == 'eml' or .content_type == 'message/rfc822')) is 1
  3. any of attachments where:
    • any of filter(...) where all hold:
      • any of:
        • all of:
          • .href_url.domain.subdomain ends with '-my'
          • strings.ilevenshtein(.href_url.domain.subdomain) - 3 / length(.href_url.domain.subdomain) - 3 + length(sender.email.domain.sld) + length(.href_url.domain.subdomain) - 3 - length(sender.email.domain.sld) + length(sender.email.domain.sld) - length(.href_url.domain.subdomain) - 3 / 2.0 > 0.7
        • all of:
          • not:
            • .href_url.domain.subdomain ends with '-my'
          • strings.ilevenshtein(.href_url.domain.subdomain) / length(.href_url.domain.subdomain) + length(sender.email.domain.sld) + length(.href_url.domain.subdomain) - length(sender.email.domain.sld) + length(sender.email.domain.sld) - length(.href_url.domain.subdomain) / 2.0 > 0.7
      • not:
        • strings.icontains(.href_url.path)
      • not:
        • any of $org_slds where:
          • strings.icontains(.href_url.domain.subdomain)
      • .href_url.path matches '\\/:[obu]:\\/(?:p|g\\/personal)'
  4. length(body.html.inner_text) < 6 * length(body.current_thread.text)
  5. sender.email.domain.root_domain not in ('sharepoint.com', 'sharepointonline.com')
  6. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • not:
        • headers.auth_summary.dmarc.pass
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  7. not:
    • all of:
      • any of headers.domains where:
        • .root_domain is 'pphosted.com'
      • headers.auth_summary.spf.pass
      • headers.auth_summary.dmarc.pass

Inspects: attachments[].content_type, attachments[].file_extension, body.html.inner_text, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.pass, headers.domains, headers.domains[].root_domain, sender.email.domain.root_domain, sender.email.local_part, type.inbound. Sensors: file.parse_eml, regex.icontains, strings.icontains, strings.iends_with. Reference lists: $high_trust_sender_root_domains, $org_slds.

Indicators matched (5)

FieldMatchValue
attachments[].file_extensionequalseml
attachments[].content_typeequalsmessage/rfc822
file.parse_eml(attachments[]).body.links[].href_url.domain.root_domainequalssharepoint.com
strings.iends_withsuffix-my
regex.icontainsregex\/:[obu]:\/(?:p|g\/personal)

Stages and Predicates

Stage 1: mql_rule

and
  any(attachments)
    any(filter(...))
      and
        or
          and
            not
              filter(...).href_url.domain.subdomain ends_with "-my"
             macro "(strings.ilevenshtein(filter(...)[].href_url.domain.subdomain) / (((length(filter(...)[].href_url.domain.subdomain) + length(sender.email.domain.sld)) + ((length(filter(...)[].href_url.domain.subdomain) - length(sender.email.domain.sld)) + (length(sender.email.domain.sld) - length(filter(...)[].href_url.domain.subdomain)))) / 2.0)) > 0.7"
          and
            filter(...).href_url.domain.subdomain ends_with "-my"
             macro "((strings.ilevenshtein(filter(...)[].href_url.domain.subdomain) - 3) / ((((length(filter(...)[].href_url.domain.subdomain) - 3) + length(sender.email.domain.sld)) + (((length(filter(...)[].href_url.domain.subdomain) - 3) - length(sender.email.domain.sld)) + (length(sender.email.domain.sld) - (length(filter(...)[].href_url.domain.subdomain) - 3)))) / 2.0)) > 0.7"
        not
          any($org_slds)
            strings.icontains func_call "strings.icontains(filter(...)[].href_url.domain.subdomain)"
        not
          strings.icontains func_call "strings.icontains(filter(...)[].href_url.path)"
        filter(...).href_url.path regex_match "\\/:[obu]:\\/(?:p|g\\/personal)"
  or
    and
      not
        headers.auth_summary.dmarc.pass eq "true"
       macro "sender.email.domain.root_domain in high_trust_sender_root_domains"
     macro "sender.email.domain.root_domain not in high_trust_sender_root_domains"
  not
    and
      any(headers.domains)
        headers.domains.root_domain eq "pphosted.com"
      headers.auth_summary.dmarc.pass eq "true"
      headers.auth_summary.spf.pass eq "true"
  not
    sender.email.domain.root_domain in ["sharepoint.com", "sharepointonline.com"]
  filter(attachments, .file_extension == 'eml' or .content_type == 'message/rfc822') length_compare "1"
  type.inbound eq "true"
   macro "length(body.html.inner_text) < (6 * length(body.current_thread.text))"

Exclusions

The rule actively suppresses these predicates.

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"