From 6e2db4ede1596df56572a39b482dbf2926aaaad6 Mon Sep 17 00:00:00 2001 From: Sublime Rule Testing Bot Date: Thu, 26 Dec 2024 14:43:13 +0000 Subject: [PATCH] Sync from PR#2151 Create impersonation_capitalone.yml by @zoomequipd https://github.com/sublime-security/sublime-rules/pull/2151 Source SHA c6884642d22015b14fe5b26d17150e5e9c7a2b41 Triggered by @zoomequipd --- detection-rules/impersonation_capitalone.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detection-rules/impersonation_capitalone.yml b/detection-rules/impersonation_capitalone.yml index 9a15609dba3..7e872295a49 100644 --- a/detection-rules/impersonation_capitalone.yml +++ b/detection-rules/impersonation_capitalone.yml @@ -2,7 +2,7 @@ name: "Brand Impersonation: Capital One" description: "This detection rule identifies inbound messages containing Capital One branding indicators in display names, sender addresses, message content, or embedded logos, while excluding legitimate Capital One domains and authenticated communications from known trusted senders." type: "rule" severity: "high" -source: "type.inbound\nand (\n any([\n strings.replace_confusables(sender.display_name),\n strings.replace_confusables(subject.subject),\n // domain parts of sender\n sender.email.local_part,\n sender.email.domain.sld\n ],\n // quick checks first\n strings.icontains(., 'Capital One')\n or strings.icontains(., 'CapitalOne')\n\n // slower checks next\n or regex.icontains(., 'Capital.?One')\n // levenshtein distince similar to captial one\n or strings.ilevenshtein(., 'Capital One') <= 2\n )\n or any(ml.logo_detect(beta.message_screenshot()).brands,\n .name == \"Capital One Bank\" and .confidence != \"low\"\n )\n)\nand not (\n sender.email.domain.root_domain in (\n \"capitalone.co.uk\",\n \"capitalone.com\",\n \"capitaloneshopping.com\",\n \"capitalonesoftware.com\",\n \"capitalonebooking.com\",\n \"capitalonetravel.com\",\n // \"olbanking.com\", // a fiserv.one domain\n // \"bynder.com\", // Digital Assest Mgmt\n // \"gcs-web.com\", // investor relations run by capital one\n // \"capitalonearena.com\", // the arena\n // \"monumentalsports.com\", // the company that owns a bunch of teams that play at the arena?\n // \"ticketmaster.com\", // sell and advertises tickets at Capital One Arena\n )\n and headers.auth_summary.dmarc.pass\n)\n// and the sender is not from high trust sender root domains\nand (\n (\n sender.email.domain.root_domain in $high_trust_sender_root_domains\n and not headers.auth_summary.dmarc.pass\n )\n or sender.email.domain.root_domain not in $high_trust_sender_root_domains\n)\nand // suspicious indicators here\n (\n // // password theme\n (\n strings.icontains(body.html.display_text, \"new password\")\n or regex.icontains(body.html.display_text,\n '(?:credentials?|password)\\s*(?:\\w+\\s+){0,3}\\s*(?:compromise|reset|expir(?:ation|ed)|update|invalid|incorrect|changed|(?:mis)?match)',\n '(?:compromise|reset|expir(?:ation|ed)|update|invalid|incorrect|changed|(?:mis)?match)\\s*(?:\\w+\\s+){0,3}\\s*(?:credentials?|password)',\n '(?:short|weak|chang(?:e|ing)|reset)\\s*(?:\\w+\\s+){0,3}\\s*(?:credentials?|password)',\n '(?:credentials?|password)\\s*(?:\\w+\\s+){0,3}\\s*(?:short|weak|chang(?:e|ing)|reset)',\n )\n )\n // // login failures\n or (\n strings.icontains(body.html.display_text, \"unusual number of\")\n or strings.icontains(body.html.display_text, \"security breach\")\n or strings.icontains(body.html.display_text, \"security alert\")\n or strings.icontains(body.html.display_text, \"account remains secure\")\n or strings.icontains(body.html.display_text, \"please verify your account\")\n or strings.icontains(body.html.display_text, \"suspicious activity detected\")\n or strings.icontains(body.html.display_text, \"temporarily locked out\")\n or regex.icontains(body.html.display_text,\n '(?:invalid|unrecognized|unauthorized|fail(?:ed|ure)?|suspicious|unusual|attempt(?:ed)?|tried to)\\s*(?:\\w+\\s+){0,3}\\s*(?:log(?:.?in)?|sign(?:.?in)?|account|access|activity)',\n '(?:log(?:.?in)?|sign(?:.?in)?|account|access|activity)\\s*(?:\\w+\\s+){0,3}\\s*(?:invalid|unrecognized|fail(?:ed|ure)?|suspicious|unusual|attempt(?:ed)?)'\n )\n )\n // // account locked\n or (\n strings.icontains(body.html.display_text, \"been suspend\")\n or strings.icontains(body.html.display_text, \"to restore access\")\n or strings.icontains(body.html.display_text, \"will be restored\")\n or strings.icontains(body.html.display_text, \"security reasons\")\n or strings.icontains(body.html.display_text,\n \"temporarily restricted access\"\n )\n or regex.icontains(body.html.display_text,\n 'acc(?:ou)?n?t\\s*(?:\\w+\\s+){0,3}\\s*(?:authenticat(?:e|ion)|activity|ho[li]d|terminat|[il1]{2}m[il1]t(?:s|ed|ation)|b?locked|de-?activat|suspen(?:ed|sion)|restrict(?:ed|ion)?|expir(?:ed?|ing)|v[il]o[li]at|verif(?:y|ication))',\n '(?:authenticat(?:e|ion)|activity|ho[li]d|terminat|[il1]{2}m[il1]t(?:s|ed|ation)|b?locked|de-?activat|suspen(?:ed|sion)|restrict(?:ed|ion)?|expir(?:ed?|ing)|v[il]o[li]at|verif(?:y|ication))\\s*(?:\\w+\\s+){0,3}\\s*acc(?:ou)?n?t'\n )\n )\n // // secure messages\n or (\n regex.icontains(body.html.display_text,\n '(?:encrypt(?:ion|ed)?|secur(?:e|ity)) (?:\\w+\\s+){0,3}\\s*message'\n )\n or strings.icontains(body.html.display_text, \"document portal\")\n or regex.icontains(body.html.display_text,\n \"has been (?:encrypt|sent secure)\"\n )\n or regex.icontains(body.html.display_text,\n 'encryption (?:\\w+\\s+){0,3}\\s*tech'\n )\n )\n // // documents to view\n or (\n // we can skip the regex if the diplay_text doesn't contain document\n // this might need to be removed if the regex is expanded\n strings.icontains(body.html.display_text, 'document')\n and regex.icontains(body.html.display_text,\n 'document\\s*(?:\\w+\\s+){0,3}\\s*(?:ready|posted|review|available|online)',\n '(?:ready|posted|review|available|online)\\s*(?:\\w+\\s+){0,3}\\s*document'\n )\n )\n // // account/profile details \n or (\n strings.icontains(body.html.display_text, \"about your account\")\n or strings.icontains(body.html.display_text, \"action required\")\n or regex.icontains(body.html.display_text,\n '(update|\\bedit|modify|revise|verif(?:y|ication)|discrepanc(?:y|ies)|mismatch(?:es)?|inconsistenc(?:y|ies)?|difference(?:s)?|anomal(?:y|ies)?|irregularit(?:y|ies)?)\\s*(?:\\w+\\s+){0,4}\\s*(?:account|detail|record|data|info(?:rmation)?)',\n '(?:account|detail|record|data|info(?:rmation)?)\\s*(?:\\w+\\s+){0,4}\\s*(update|\\bedit|modify|revise|verif(?:y|ication)|discrepanc(?:y|ies)|mismatch(?:es)?|inconsistenc(?:y|ies)?|difference(?:s)?|anomal(?:y|ies)?|irregularit(?:y|ies)?)'\n )\n )\n // // other calls to action that are unexpected\n or (strings.icontains(body.html.display_text, \"download the attachment\"))\n\n // the links contain suspect wording\n or any(filter(body.links,\n any([\n 'login',\n 'log in',\n 'sign in',\n 'confirm',\n 'i recongize it',\n \"something\\'s wrong\",\n \"view\",\n \"message\",\n \"restore\",\n \"acccount\"\n ],\n strings.icontains(..display_text, .)\n )\n ),\n .href_url.domain.root_domain != \"capitalone.com\"\n )\n // the message contains a disclaimer but then isn't \n or (\n regex.icontains(body.current_thread.text,\n 'To ensure delivery, add [^\\@]+@[^\\s]*capitalone.com to your address book.'\n )\n and sender.email.domain.root_domain != \"capitalone.com\"\n )\n)\n" +source: "type.inbound\nand (\n any([\n strings.replace_confusables(sender.display_name),\n strings.replace_confusables(subject.subject),\n // domain parts of sender\n sender.email.local_part,\n sender.email.domain.sld\n ],\n // quick checks first\n strings.icontains(., 'Capital One')\n or strings.icontains(., 'CapitalOne')\n\n // slower checks next\n or regex.icontains(., 'Capital.?One')\n // levenshtein distince similar to captial one\n or strings.ilevenshtein(., 'Capital One') <= 2\n )\n or any(ml.logo_detect(beta.message_screenshot()).brands,\n .name == \"Capital One Bank\" and .confidence != \"low\"\n )\n)\nand not (\n sender.email.domain.root_domain in (\n \"capitalone.co.uk\",\n \"capitalone.com\",\n \"capitaloneshopping.com\",\n \"capitalonesoftware.com\",\n \"capitalonebooking.com\",\n \"capitalonetravel.com\",\n // \"olbanking.com\", // a fiserv.one domain\n // \"bynder.com\", // Digital Assest Mgmt\n // \"gcs-web.com\", // investor relations run by capital one\n // \"capitalonearena.com\", // the arena\n // \"monumentalsports.com\", // the company that owns a bunch of teams that play at the arena?\n // \"ticketmaster.com\", // sell and advertises tickets at Capital One Arena\n )\n and headers.auth_summary.dmarc.pass\n)\n// and the sender is not from high trust sender root domains\nand (\n (\n sender.email.domain.root_domain in $high_trust_sender_root_domains\n and not headers.auth_summary.dmarc.pass\n )\n or sender.email.domain.root_domain not in $high_trust_sender_root_domains\n)\nand // suspicious indicators here\n (\n // // password theme\n (\n strings.icontains(body.html.display_text, \"new password\")\n or regex.icontains(body.html.display_text,\n '(?:credentials?|password)\\s*(?:\\w+\\s+){0,3}\\s*(?:compromise|reset|expir(?:ation|ed)|update|invalid|incorrect|changed|(?:mis)?match)',\n '(?:compromise|reset|expir(?:ation|ed)|update|invalid|incorrect|changed|(?:mis)?match)\\s*(?:\\w+\\s+){0,3}\\s*(?:credentials?|password)',\n '(?:short|weak|chang(?:e|ing)|reset)\\s*(?:\\w+\\s+){0,3}\\s*(?:credentials?|password)',\n '(?:credentials?|password)\\s*(?:\\w+\\s+){0,3}\\s*(?:short|weak|chang(?:e|ing)|reset)',\n )\n )\n // // login failures\n or (\n strings.icontains(body.html.display_text, \"unusual number of\")\n or strings.icontains(body.html.display_text, \"security breach\")\n or strings.icontains(body.html.display_text, \"security alert\")\n or strings.icontains(body.html.display_text, \"account remains secure\")\n or strings.icontains(body.html.display_text, \"please verify your account\")\n or strings.icontains(body.html.display_text, \"suspicious activity detected\")\n or strings.icontains(body.html.display_text, \"temporarily locked out\")\n or regex.icontains(body.html.display_text,\n '(?:invalid|unrecognized|unauthorized|fail(?:ed|ure)?|suspicious|unusual|attempt(?:ed)?|tried to)\\s*(?:\\w+\\s+){0,3}\\s*(?:log(?:.?in)?|sign(?:.?in)?|account|access|activity)',\n '(?:log(?:.?in)?|sign(?:.?in)?|account|access|activity)\\s*(?:\\w+\\s+){0,3}\\s*(?:invalid|unrecognized|fail(?:ed|ure)?|suspicious|unusual|attempt(?:ed)?)'\n )\n )\n // // account locked\n or (\n strings.icontains(body.html.display_text, \"been suspend\")\n or strings.icontains(body.html.display_text, \"to restore access\")\n or strings.icontains(body.html.display_text, \"will be restored\")\n or strings.icontains(body.html.display_text, \"security reasons\")\n or strings.icontains(body.html.display_text,\n \"temporarily restricted access\"\n )\n or regex.icontains(body.html.display_text,\n 'acc(?:ou)?n?t\\s*(?:\\w+\\s+){0,3}\\s*(?:authenticat(?:e|ion)|activity|ho[li]d|terminat|[il1]{2}m[il1]t(?:s|ed|ation)|b?locked|de-?activat|suspen(?:ed|sion)|restrict(?:ed|ion)?|expir(?:ed?|ing)|v[il]o[li]at|verif(?:y|ication))',\n '(?:authenticat(?:e|ion)|activity|ho[li]d|terminat|[il1]{2}m[il1]t(?:s|ed|ation)|b?locked|de-?activat|suspen(?:ed|sion)|restrict(?:ed|ion)?|expir(?:ed?|ing)|v[il]o[li]at|verif(?:y|ication))\\s*(?:\\w+\\s+){0,3}\\s*acc(?:ou)?n?t'\n )\n )\n // // secure messages\n or (\n regex.icontains(body.html.display_text,\n '(?:encrypt(?:ion|ed)?|secur(?:e|ity)) (?:\\w+\\s+){0,3}\\s*message'\n )\n or strings.icontains(body.html.display_text, \"document portal\")\n or regex.icontains(body.html.display_text,\n \"has been (?:encrypt|sent secure)\"\n )\n or regex.icontains(body.html.display_text,\n 'encryption (?:\\w+\\s+){0,3}\\s*tech'\n )\n )\n // // documents to view\n or (\n // we can skip the regex if the diplay_text doesn't contain document\n // this might need to be removed if the regex is expanded\n strings.icontains(body.html.display_text, 'document')\n and regex.icontains(body.html.display_text,\n 'document\\s*(?:\\w+\\s+){0,3}\\s*(?:ready|posted|review|available|online)',\n '(?:ready|posted|review|available|online)\\s*(?:\\w+\\s+){0,3}\\s*document'\n )\n )\n // // account/profile details \n or (\n strings.icontains(body.html.display_text, \"about your account\")\n or strings.icontains(body.html.display_text, \"action required\")\n or regex.icontains(body.html.display_text,\n '(update|\\bedit\\b|modify|revise|verif(?:y|ication)|discrepanc(?:y|ies)|mismatch(?:es)?|inconsistenc(?:y|ies)?|difference(?:s)?|anomal(?:y|ies)?|irregularit(?:y|ies)?)\\s*(?:\\w+\\s+){0,4}\\s*(?:account|detail|record|data|info(?:rmation)?)',\n '(?:account|detail|record|data|info(?:rmation)?)\\s*(?:\\w+\\s+){0,4}\\s*(update|\\bedit\\b|modify|revise|verif(?:y|ication)|discrepanc(?:y|ies)|mismatch(?:es)?|inconsistenc(?:y|ies)?|difference(?:s)?|anomal(?:y|ies)?|irregularit(?:y|ies)?)'\n )\n )\n // // other calls to action that are unexpected\n or (strings.icontains(body.html.display_text, \"download the attachment\"))\n\n // the links contain suspect wording\n or (\n any(filter(body.links,\n any([\n 'login',\n 'log in',\n 'sign in',\n 'confirm',\n 'i recongize it',\n \"something\\'s wrong\",\n \"view\",\n \"message\",\n \"restore\",\n \"acccount\"\n ],\n strings.icontains(..display_text, .)\n )\n ),\n .href_url.domain.root_domain != \"capitalone.com\"\n )\n // use distinct \"urls\" (without query params) to determine number of links\n and 0 < length(distinct(body.links,\n // strip out query params to determine \n // the unique number of links\n strings.concat(.href_url.scheme,\n .href_url.domain.domain,\n .href_url.path\n )\n )\n ) <= 10\n )\n // the message contains a disclaimer but then isn't \n or (\n regex.icontains(body.current_thread.text,\n 'To ensure delivery, add [^\\@]+@[^\\s]*capitalone.com to your address book.'\n )\n and sender.email.domain.root_domain != \"capitalone.com\"\n )\n)\n" attack_types: - "Credential Phishing" tactics_and_techniques: @@ -15,4 +15,4 @@ detection_methods: - "Header analysis" id: "d53848e4-fc40-5bd1-ad5e-c9c4e85a669f" testing_pr: 2151 -testing_sha: 91461fdf9b9c25ce674e31c5c8b7f6a20034305b +testing_sha: c6884642d22015b14fe5b26d17150e5e9c7a2b41