diff --git a/detection-rules/unrelated_sharepoint_link.yml b/detection-rules/unrelated_sharepoint_link.yml new file mode 100644 index 00000000000..b302180c392 --- /dev/null +++ b/detection-rules/unrelated_sharepoint_link.yml @@ -0,0 +1,113 @@ +name: "Sharepoint Link Likely Unrelated to Sender" +description: "Detects when a sender links to a Sharepoint file where the subdomain significantly differs from the sender's domain. The rule checks for OneNote, PDF, or unknown file types and includes various domain validation checks." +type: "rule" +severity: "medium" +source: | + type.inbound + + and 0 < length(body.links) < 10 + and any(filter(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) + + // it is either a OneNote or PDF file, or unknown + and ( + strings.icontains(.href_url.path, '/:o:/') + or strings.icontains(.href_url.path, '/:b:/') + or strings.icontains(.href_url.path, '/:u:/') + ) + + // a future negation like this would be great + // and any($org_domains, .domain.subdomain != ..href_url.domain.subdomain) + ) + + // 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 + ) +tags: + - "Attack surface reduction" +attack_types: + - "BEC/Fraud" + - "Credential Phishing" +tactics_and_techniques: + - "Impersonation: Employee" + - "Lookalike domain" + - "OneNote" + - "PDF" + - "Social engineering" +detection_methods: + - "URL analysis" + - "Sender analysis" + - "Header analysis" + - "HTML analysis" +id: "6870f489-5581-53f0-a6f7-a03e259fb073" +testing_pr: 2230 +testing_sha: 4059bf56bf8205c946ac5a78d55376b31d69de20