From 5720a6b6a242a988efe6ba19ca78e19a1067fc88 Mon Sep 17 00:00:00 2001 From: Sublime Rule Testing Bot Date: Wed, 11 Dec 2024 14:45:05 +0000 Subject: [PATCH] Sync from PR#2177 Create link_sharepoint_attached_eml.yml by @zoomequipd https://github.com/sublime-security/sublime-rules/pull/2177 Source SHA decc15bf08cf61fe1ae4095b3d241409de6b1e7f Triggered by @zoomequipd --- .../link_sharepoint_attached_eml.yml | 96 +------------------ 1 file changed, 2 insertions(+), 94 deletions(-) diff --git a/detection-rules/link_sharepoint_attached_eml.yml b/detection-rules/link_sharepoint_attached_eml.yml index 5f3bba430bd..b3f813a1088 100644 --- a/detection-rules/link_sharepoint_attached_eml.yml +++ b/detection-rules/link_sharepoint_attached_eml.yml @@ -2,99 +2,7 @@ name: "Link: SharePoint Nested Message Forgery" description: "This detection rule identifies messages with an EML attachment containing SharePoint links, where the inner and outer messages share multiple matching characteristics, suggesting message content manipulation." type: "rule" severity: "medium" -source: | - type.inbound - and not any(body.links, .href_url.domain.root_domain == "sharepoint.com") - and any( - // filter to just eml attachments - filter(attachments, - .content_type == "message/rfc822" or .file_extension == "eml" - ), - // any body links go to sharepoint - any(file.parse_eml(.).body.links, - .href_url.domain.root_domain == "sharepoint.com" - and regex.icontains(.href_url.path, '/:[a-z]:/') - ) - and 2 of ( - // the recipients of the outer and inner messages are the same - // or there is no outer recipients - ( - ( - all(map(file.parse_eml(.).recipients.to, .email.email), - . in map(recipients.to, .email.email) - ) - and all(map(file.parse_eml(.).recipients.bcc, .email.email), - . in map(recipients.bcc, .email.email) - ) - and all(map(file.parse_eml(.).recipients.cc, .email.email), - . in map(recipients.cc, .email.email) - ) - // make sure the are the same length - and sum([ - length(recipients.to), - length(recipients.bcc), - length(recipients.cc) - ] - ) == sum([ - length(file.parse_eml(.).recipients.to), - length(file.parse_eml(.).recipients.bcc), - length(file.parse_eml(.).recipients.cc) - ] - ) - ) - or length(recipients.to) == 0 - or all(recipients.to, .email.email == "") - ), - // the sender of the outer and inner messages are the same - file.parse_eml(.).sender.email.email == sender.email.email, - - // the subject of the outer and inner messages are the same - strings.icontains(subject.subject, file.parse_eml(.).subject.subject), - - // the inner message has the recipient and sender as the same address - // without any other recipients and matches the outer message sender - ( - sum( - [ - length(filter(file.parse_eml(.).recipients.to, .email.email != "")), - length(filter(file.parse_eml(.).recipients.bcc, .email.email != "")), - length(filter(file.parse_eml(.).recipients.cc, .email.email != "")) - ] - ) == 1 - and ( - all(file.parse_eml(.).recipients.to, - .email.email == file.parse_eml(..).sender.email.email - ) - ) - and file.parse_eml(.).sender.email.email == sender.email.email - ), - - // the outer recipieint is the sender of the inner message - ( - sum( - [ - length(filter(file.parse_eml(.).recipients.to, .email.email != "")), - length(filter(file.parse_eml(.).recipients.bcc, .email.email != "")), - length(filter(file.parse_eml(.).recipients.cc, .email.email != "")) - ] - ) == 1 - and all(recipients.to, - .email.email == file.parse_eml(..).sender.email.email - ) - ) - ) - ) - - // exclude bounce backs & read receipts - and not strings.like(sender.email.local_part, - "*postmaster*", - "*mailer-daemon*", - "*administrator*" - ) - and not regex.icontains(subject.subject, "^(undeliverable|read:)") - and not any(attachments, .content_type == "message/delivery-status") - // if the "References" is in the body of the message, it's probably a bounce - and not any(headers.references, strings.contains(body.html.display_text, .)) +source: "type.inbound\nand not any(body.links, .href_url.domain.root_domain == \"sharepoint.com\")\n// ensure there is only a single .eml attachment\nand length(filter(attachments,\n (\n .content_type == \"message/rfc822\"\n or .file_extension == \"eml\"\n )\n )\n) == 1\nand any(\n // filter to just eml attachments\n filter(attachments,\n (.content_type == \"message/rfc822\" or .file_extension == \"eml\")\n ),\n // any body links go to sharepoint\n any(file.parse_eml(.).body.links,\n .href_url.domain.root_domain == \"sharepoint.com\"\n and regex.icontains(.href_url.path, '/:[a-z]:/')\n )\n and 2 of (\n // the recipients of the outer and inner messages are the same\n // or there is no outer recipients\n (\n (\n all(map(file.parse_eml(.).recipients.to, .email.email),\n . in map(recipients.to, .email.email)\n )\n and all(map(file.parse_eml(.).recipients.bcc, .email.email),\n . in map(recipients.bcc, .email.email)\n )\n and all(map(file.parse_eml(.).recipients.cc, .email.email),\n . in map(recipients.cc, .email.email)\n )\n // make sure the are the same length\n and sum([\n length(recipients.to),\n length(recipients.bcc),\n length(recipients.cc)\n ]\n ) == sum([\n length(file.parse_eml(.).recipients.to),\n length(file.parse_eml(.).recipients.bcc),\n length(file.parse_eml(.).recipients.cc)\n ]\n )\n )\n or length(recipients.to) == 0\n or all(recipients.to, .email.email == \"\")\n ),\n // the sender of the outer and inner messages are the same\n file.parse_eml(.).sender.email.email == sender.email.email,\n\n // the subject of the outer and inner messages are the same\n strings.icontains(subject.subject, file.parse_eml(.).subject.subject),\n\n // the inner message has the recipient and sender as the same address\n // without any other recipients and matches the outer message sender\n (\n sum([\n length(filter(file.parse_eml(.).recipients.to,\n .email.email != \"\"\n )\n ),\n length(filter(file.parse_eml(.).recipients.bcc,\n .email.email != \"\"\n )\n ),\n length(filter(file.parse_eml(.).recipients.cc,\n .email.email != \"\"\n )\n )\n ]\n ) == 1\n and (\n all(file.parse_eml(.).recipients.to,\n .email.email == file.parse_eml(..).sender.email.email\n )\n )\n and file.parse_eml(.).sender.email.email == sender.email.email\n ),\n\n // the outer recipieint is the sender of the inner message\n (\n sum([\n length(filter(file.parse_eml(.).recipients.to,\n .email.email != \"\"\n )\n ),\n length(filter(file.parse_eml(.).recipients.bcc,\n .email.email != \"\"\n )\n ),\n length(filter(file.parse_eml(.).recipients.cc,\n .email.email != \"\"\n )\n )\n ]\n ) == 1\n and all(recipients.to,\n .email.email == file.parse_eml(..).sender.email.email\n )\n ),\n \n // the attached message contains a very low number of hops, as if it was never sent\n (\n length(file.parse_eml(.).headers.hops) <= 2\n or file.parse_eml(.).headers.return_path.email is null\n )\n )\n)\n\n// exclude bounce backs & read receipts\nand not strings.like(sender.email.local_part,\n \"*postmaster*\",\n \"*mailer-daemon*\",\n \"*administrator*\"\n)\nand not regex.icontains(subject.subject, \"^(undeliverable|read:)\")\nand not any(attachments, .content_type == \"message/delivery-status\")\n// if the \"References\" is in the body of the message, it's probably a bounce\nand not any(headers.references, strings.contains(body.html.display_text, .))\n" attack_types: - "Credential Phishing" tactics_and_techniques: @@ -106,4 +14,4 @@ detection_methods: - "Header analysis" id: "eab46d4b-39c9-568a-bb72-bf93f4cf997e" testing_pr: 2177 -testing_sha: 9fa98f4cecb92d6d44346987526a8da42700b143 +testing_sha: decc15bf08cf61fe1ae4095b3d241409de6b1e7f