diff --git a/.github/workflows/mql-mimic-tests.yml b/.github/workflows/mql-mimic-tests.yml new file mode 100644 index 00000000000..de506e94e80 --- /dev/null +++ b/.github/workflows/mql-mimic-tests.yml @@ -0,0 +1,40 @@ +name: MQL Mimic Tests + +on: + push: + branches: [ "**" ] + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + trigger-via-zapier: + name: Trigger Test Run + runs-on: ubuntu-20.04 + permissions: + checks: write + + steps: + + - name: "Trigger MQL Mimic Tests" + env: + trigger_url: '${{ secrets.MQL_MOCK_TRIGGER }}' + branch: '${{ github.ref_name }}' + repo: '${{ github.repository }}' + token: '${{ secrets.GITHUB_TOKEN }}' + sha: '${{ github.sha }}' + run: | + curl -X POST $trigger_url \ + -H 'Content-Type: application/json' \ + -d '{"branch":"'$branch'","repo":"'$repo'","token":"'$token'","sha":"'$sha'"}' + + - name: Wait for check to be completed + uses: fountainhead/action-wait-for-check@v1.1.0 + id: wait-for-build + # Wait for results so that the token remains valid while the test suite is executing and posting a check here. + with: + token: ${{ secrets.GITHUB_TOKEN }} + checkName: "MQL Mimic Tests" + ref: ${{ github.sha }} + timeoutSeconds: 3600 diff --git a/detection-rules/attachment_adobe_image_lure_fts.yml b/detection-rules/attachment_adobe_image_lure_fts.yml index 1d84a92ff8c..78125362de3 100644 --- a/detection-rules/attachment_adobe_image_lure_fts.yml +++ b/detection-rules/attachment_adobe_image_lure_fts.yml @@ -4,25 +4,30 @@ type: "rule" severity: "medium" source: | type.inbound - and length(filter(attachments, .file_type not in~ ('png', 'jpeg', 'jpg', 'bmp'))) == 0 - and length(body.links) >0 + and length(filter(attachments, .file_type not in $file_types_images)) == 0 + and length(body.links) > 0 and all(body.links, .display_text is null) and any(attachments, - any(ml.logo_detect(.).brands, .name == "Adobe" and .confidence in ("high")) - and any(file.explode(.), - any(.scan.strings.strings, strings.ilike(., - "*review*", "*sign*", "*view*", "*completed document*", "*open agreement*")) - ) + any(ml.logo_detect(.).brands, .name == "Adobe" and .confidence in ("high")) + and any(file.explode(.), + strings.ilike(.scan.ocr.raw, + "*review*", + "*sign*", + "*view*", + "*completed document*", + "*open agreement*" + ) + ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_any_html_in_archive_unsolicited.yml b/detection-rules/attachment_any_html_in_archive_unsolicited.yml index 95bd7734acc..ddf0659e54e 100644 --- a/detection-rules/attachment_any_html_in_archive_unsolicited.yml +++ b/detection-rules/attachment_any_html_in_archive_unsolicited.yml @@ -10,19 +10,18 @@ severity: "medium" source: | type.inbound and any(attachments, - .file_extension in~ $file_extensions_common_archives - and any(file.explode(.), .depth > 0 - and .file_extension in~ ("html", "htm")) + .file_extension in~ $file_extensions_common_archives + and any(file.explode(.), .depth > 0 and .file_extension in~ ("html", "htm")) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Attack surface reduction" diff --git a/detection-rules/attachment_any_html_new_sender.yml b/detection-rules/attachment_any_html_new_sender.yml index 17aedb1ff72..cc22e73e915 100644 --- a/detection-rules/attachment_any_html_new_sender.yml +++ b/detection-rules/attachment_any_html_new_sender.yml @@ -10,21 +10,18 @@ type: "rule" severity: "medium" source: | type.inbound - and any(attachments, - .file_extension in~ ('htm', 'html') or - .file_type == "html" - ) + and any(attachments, .file_extension in~ ('htm', 'html') or .file_type == "html") // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) tags: - "Attack surface reduction" diff --git a/detection-rules/attachment_any_html_unsolicited.yml b/detection-rules/attachment_any_html_unsolicited.yml index 80527bfd3c1..075feda5569 100644 --- a/detection-rules/attachment_any_html_unsolicited.yml +++ b/detection-rules/attachment_any_html_unsolicited.yml @@ -10,21 +10,18 @@ type: "rule" severity: "low" source: | type.inbound - and any(attachments, - .file_extension in~ ('htm', 'html') or - .file_type == "html" - ) + and any(attachments, .file_extension in~ ('htm', 'html') or .file_type == "html") // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Attack surface reduction" diff --git a/detection-rules/attachment_archive_with_chm.yml b/detection-rules/attachment_archive_with_chm.yml index 926e3f7e0be..56da4665e7a 100644 --- a/detection-rules/attachment_archive_with_chm.yml +++ b/detection-rules/attachment_archive_with_chm.yml @@ -11,8 +11,9 @@ type: "rule" severity: "medium" source: | type.inbound - and any(attachments, .file_extension in~ $file_extensions_common_archives - and any(file.explode(.), .file_extension =~ "chm") + and any(attachments, + .file_extension in~ $file_extensions_common_archives + and any(file.explode(.), .file_extension =~ "chm") ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_archive_with_exe.yml b/detection-rules/attachment_archive_with_exe.yml index 24101b3a289..17b5f160d88 100644 --- a/detection-rules/attachment_archive_with_exe.yml +++ b/detection-rules/attachment_archive_with_exe.yml @@ -14,10 +14,9 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, .file_extension in~ $file_extensions_common_archives - and any(file.explode(.), - any(.flavors.yara, . == "mz_file") - ) + and any(attachments, + .file_extension in~ $file_extensions_common_archives + and any(file.explode(.), any(.flavors.yara, . == "mz_file")) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_archive_with_pdf_wsf_txt_attached.qakbot.yml b/detection-rules/attachment_archive_with_pdf_wsf_txt_attached.qakbot.yml index f3cc147ff46..d457374f2b1 100644 --- a/detection-rules/attachment_archive_with_pdf_wsf_txt_attached.qakbot.yml +++ b/detection-rules/attachment_archive_with_pdf_wsf_txt_attached.qakbot.yml @@ -8,11 +8,15 @@ severity: "medium" source: | type.inbound and any(attachments, - .file_extension in~ $file_extensions_common_archives - and length(distinct(filter(file.explode(.), .depth == 1 - and .flavors.mime in~ ("application/pdf", "text/plain")), - .flavors.mime)) == 2 - and any(file.explode(.), .depth == 1 and .file_extension == "wsf") + .file_extension in~ $file_extensions_common_archives + and length(distinct(filter(file.explode(.), + .depth == 1 + and .flavors.mime in~ ("application/pdf", "text/plain") + ), + .flavors.mime + ) + ) == 2 + and any(file.explode(.), .depth == 1 and .file_extension == "wsf") ) tags: - "Malfam: QakBot" diff --git a/detection-rules/attachment_callback_phish_with_img.yml b/detection-rules/attachment_callback_phish_with_img.yml index 29ad847fe58..e9ce44623c7 100644 --- a/detection-rules/attachment_callback_phish_with_img.yml +++ b/detection-rules/attachment_callback_phish_with_img.yml @@ -10,48 +10,49 @@ severity: "high" source: | type.inbound and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) - and sender.email.domain.root_domain in $free_email_providers - and any(attachments, .file_extension in~ ('png', 'jpg', 'jpeg') - and any(file.explode(.), - length(filter(.scan.strings.strings, strings.ilike(., - "*purchase*", - "*subscription*", - "*antivirus*", - "*order*", - "*support*", - "*receipt*", - "*amount*", - "*charged*", - "*invoice*", - "*call*", - "*cancel*", - "*renew*", - "*refund*", - "*+1*" - ))) >= 4) - - and any(file.explode(.), - length(filter(.scan.strings.strings, strings.ilike(., - "*geek squad*", - "*lifelock*", - "*best buy*", - "*mcafee*", - "*norton*", - "*ebay*", - "*paypal*", - "*secure anywhere*" - ))) >=1) - ) + and any(attachments, + .file_type in $file_types_images + and any(file.explode(.), + 4 of ( + strings.icontains(.scan.ocr.raw, "purchase"), + strings.icontains(.scan.ocr.raw, "subscription"), + strings.icontains(.scan.ocr.raw, "antivirus"), + strings.icontains(.scan.ocr.raw, "order"), + strings.icontains(.scan.ocr.raw, "support"), + strings.icontains(.scan.ocr.raw, "receipt"), + strings.icontains(.scan.ocr.raw, "amount"), + strings.icontains(.scan.ocr.raw, "charged"), + strings.icontains(.scan.ocr.raw, "invoice"), + strings.icontains(.scan.ocr.raw, "call"), + strings.icontains(.scan.ocr.raw, "cancel"), + strings.icontains(.scan.ocr.raw, "renew"), + strings.icontains(.scan.ocr.raw, "refund"), + strings.icontains(.scan.ocr.raw, "+1") + ) + ) + and any(file.explode(.), + strings.ilike(.scan.ocr.raw, + "*geek squad*", + "*lifelock*", + "*best buy*", + "*mcafee*", + "*norton*", + "*ebay*", + "*paypal*", + "*secure anywhere*" + ) + ) + ) attack_types: - "Callback Phishing" tactics_and_techniques: diff --git a/detection-rules/attachment_callback_phish_with_pdf.yml b/detection-rules/attachment_callback_phish_with_pdf.yml index c951fafcf30..1b6f24a320b 100644 --- a/detection-rules/attachment_callback_phish_with_pdf.yml +++ b/detection-rules/attachment_callback_phish_with_pdf.yml @@ -8,14 +8,14 @@ severity: "high" source: | type.inbound and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) // single attachment @@ -25,41 +25,46 @@ source: | and sender.email.domain.root_domain in $free_email_providers // the attachment is a pdf with 1 page, and at least 60 ocr chars - and any(attachments, .file_extension == "pdf" - and any(file.explode(.), - .scan.exiftool.page_count == 1) - and any(file.explode(.), - length(.scan.ocr.raw) > 60) + and any(attachments, + .file_extension == "pdf" + and any(file.explode(.), .scan.exiftool.page_count == 1) + and any(file.explode(.), length(.scan.ocr.raw) > 60) - // 4 of the following strings are found - and any(file.explode(.), - length(filter(.scan.strings.strings, strings.ilike(., - "*purchase*", - "*subscription*", - "*antivirus*", - "*order*", - "*support*", - "*receipt*", - "*invoice*", - "*call*", - "*cancel*", - "*renew*", - "*refund*", - "*+1*" - ))) >= 4) + // 4 of the following strings are found + and any(file.explode(.), + 4 of ( + strings.icontains(.scan.ocr.raw, "purchase"), + strings.icontains(.scan.ocr.raw, "payment"), + strings.icontains(.scan.ocr.raw, "transaction"), + strings.icontains(.scan.ocr.raw, "subscription"), + strings.icontains(.scan.ocr.raw, "antivirus"), + strings.icontains(.scan.ocr.raw, "order"), + strings.icontains(.scan.ocr.raw, "support"), + strings.icontains(.scan.ocr.raw, "help line"), + strings.icontains(.scan.ocr.raw, "receipt"), + strings.icontains(.scan.ocr.raw, "invoice"), + strings.icontains(.scan.ocr.raw, "call"), + strings.icontains(.scan.ocr.raw, "helpdesk"), + strings.icontains(.scan.ocr.raw, "cancel"), + strings.icontains(.scan.ocr.raw, "renew"), + strings.icontains(.scan.ocr.raw, "refund"), + regex.icontains(.scan.ocr.raw, '\+\d') + ) + ) - // 1 of the following strings is found, representing common Callback brands - and any(file.explode(.), - length(filter(.scan.strings.strings, strings.ilike(., - "*geek squad*", - "*lifelock*", - "*best buy*", - "*mcafee*", - "*norton*", - "*ebay*", - "*paypal*", - ))) >=1) - ) + // 1 of the following strings is found, representing common Callback brands + and any(file.explode(.), + 1 of ( + strings.icontains(.scan.ocr.raw, "geek squad"), + strings.icontains(.scan.ocr.raw, "lifelock"), + strings.icontains(.scan.ocr.raw, "best buy"), + strings.icontains(.scan.ocr.raw, "mcafee"), + strings.icontains(.scan.ocr.raw, "norton"), + strings.icontains(.scan.ocr.raw, "ebay"), + strings.icontains(.scan.ocr.raw, "paypal"), + ) + ) + ) attack_types: - "Callback Phishing" tactics_and_techniques: diff --git a/detection-rules/attachment_credential_phishing_image_as_content.yml b/detection-rules/attachment_credential_phishing_image_as_content.yml new file mode 100644 index 00000000000..dc9b0a60fc6 --- /dev/null +++ b/detection-rules/attachment_credential_phishing_image_as_content.yml @@ -0,0 +1,59 @@ +name: "Credential Phishing: Image as content, short or no body contents" +description: | + This rule identifies incoming messages with minimal links, all image attachments and either empty, brief + or the body text is only a warning banner/disclaimer. It also checks for truncated PNG images or logos in addition + to high-confidence credit theft intentions. +type: "rule" +severity: "medium" +source: | + type.inbound + and length(body.links) < 2 + and 0 < (length(attachments)) < 3 + and ( + // body text is very short + ( + 0 <= (length(body.current_thread.text)) < 10 or body.current_thread.text is null + ) + or ( + length(body.current_thread.text) < 900 + // or body is most likely all warning banner (text contains the sender and common warning banner language) + and ( + ( + strings.contains(body.current_thread.text, sender.email.email) + and strings.contains(body.current_thread.text, 'caution') + ) + or regex.icontains(body.current_thread.text, + "intended recipient's use only|external email|sent from outside|you don't often" + ) + ) + ) + ) + and ( + all(attachments, + (.file_type in $file_types_images) + and ( + any(file.explode(.), + any(.scan.exiftool.fields, .value == "Truncated PNG image") + or ( + any(ml.logo_detect(..).brands, .name is not null) + and any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence == "high" + ) + ) + ) + ) + ) + ) +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "Evasion" + - "Image as content" +detection_methods: + - "Computer Vision" + - "Content analysis" + - "File analysis" + - "Header analysis" + - "Natural Language Understanding" + - "Optical Character Recognition" +id: "01313f38-d0d1-5240-b407-8f9158639277" diff --git a/detection-rules/attachment_cve_2023_21716_rtf_fonts.yml b/detection-rules/attachment_cve_2023_21716_rtf_fonts.yml index 4158d855436..26f9c8d15bf 100644 --- a/detection-rules/attachment_cve_2023_21716_rtf_fonts.yml +++ b/detection-rules/attachment_cve_2023_21716_rtf_fonts.yml @@ -11,15 +11,15 @@ severity: "high" source: | type.inbound and any(attachments, - ( - .file_extension in~ ("rtf", "doc", "docx") - or .file_extension in~ $file_extensions_common_archives - or .file_extension in~ $file_extensions_macros - ) - and any(file.explode(.), - any(.scan.strings.strings, strings.ilike(., '*\fonttbl*')) - and length(filter(.scan.strings.strings, strings.ilike(.,'{\f*;}'))) > 10000 - ) + ( + .file_extension in~ ("rtf", "doc", "docx") + or .file_extension in~ $file_extensions_common_archives + or .file_extension in~ $file_extensions_macros + ) + and any(file.explode(.), + any(.scan.strings.strings, strings.ilike(., '*\fonttbl*')) + and length(filter(.scan.strings.strings, strings.ilike(., '{\f*;}'))) > 10000 + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_disallowed_file_type_in_archive.yml b/detection-rules/attachment_disallowed_file_type_in_archive.yml index fdfb6213a46..7c137b9f5b2 100644 --- a/detection-rules/attachment_disallowed_file_type_in_archive.yml +++ b/detection-rules/attachment_disallowed_file_type_in_archive.yml @@ -11,187 +11,189 @@ type: "rule" severity: "low" source: | type.inbound - and any(attachments, .file_extension in~ $file_extensions_common_archives - and any(file.explode(.), .file_extension in~ ( - // File types blocked by Gmail by default - // https://support.google.com/mail/answer/6590?hl=en#zippy=%2Cmessages-that-have-attachments - "ade", - "adp", - "apk", - "appx", - "appxbundle", - "bat", - "cab", - "chm", - "cmd", - "com", - "cpl", - "dll", - "dmg", - "ex", - "ex_", - "exe", - "hta", - "ins", - "isp", - "iso", - "jar", - "js", - "jse", - "lib", - "lnk", - "mde", - "msc", - "msi", - "msix", - "msixbundle", - "msp", - "mst", - "nsh", - "pif", - "ps1", - "scr", - "sct", - "shb", - "sys", - "vb", - "vbe", - "vbs", - "vxd", - "wsc", - "wsf", - "wsh", + and any(attachments, + .file_extension in~ $file_extensions_common_archives + and any(file.explode(.), + .file_extension in~ ( + // File types blocked by Gmail by default + // https://support.google.com/mail/answer/6590?hl=en#zippy=%2Cmessages-that-have-attachments + "ade", + "adp", + "apk", + "appx", + "appxbundle", + "bat", + "cab", + "chm", + "cmd", + "com", + "cpl", + "dll", + "dmg", + "ex", + "ex_", + "exe", + "hta", + "ins", + "isp", + "iso", + "jar", + "js", + "jse", + "lib", + "lnk", + "mde", + "msc", + "msi", + "msix", + "msixbundle", + "msp", + "mst", + "nsh", + "pif", + "ps1", + "scr", + "sct", + "shb", + "sys", + "vb", + "vbe", + "vbs", + "vxd", + "wsc", + "wsf", + "wsh", - // File types blocked by Microsoft 365 by default - // https://support.microsoft.com/en-us/office/blocked-attachments-in-outlook-434752e1-02d3-4e90-9124-8b81e49a8519 - "ade", - "adp", - "app", - "application", - "appref-ms", - "asp", - "aspx", - "asx", - // "bas", excluded at depth > 1 because they can exist natively in word docs within an archive. see below - "bat", - "bgi", - "cab", - // "cer", - "chm", - "cmd", - "cnt", - "com", - "cpl", - // "crt", - // "csh", - // "der", - "diagcab", - "exe", - "fxp", - "gadget", - // "grp", - "hlp", - "hpj", - "hta", - "htc", - // "inf", - "ins", - "iso", - "isp", - "its", - "jar", - "jnlp", - "js", - "jse", - "ksh", - "lnk", - "mad", - "maf", - "mag", - "mam", - "maq", - "mar", - "mas", - "mat", - "mau", - "mav", - "maw", - "mcf", - "mda", - // "mdb", - "mde", - "mdt", - "mdw", - "mdz", - "msc", - "msh", - "msh1", - "msh2", - "mshxml", - "msh1xml", - "msh2xml", - "msi", - "msp", - "mst", - "msu", - "ops", - "osd", - "pcd", - "pif", - "pl", - "plg", - "prf", - "prg", - "printerexport", - "ps1", - "ps1xml", - "ps2", - "ps2xml", - "psc1", - "psc2", - "psd1", - "psdm1", - "pst", - // "py", - // "pyc", - "pyo", - "pyw", - "pyz", - "pyzw", - "reg", - "scf", - "scr", - "sct", - "shb", - "shs", - "theme", - // "tmp", - "url", - "vb", - "vbe", - "vbp", - "vbs", - "vhd", - "vhdx", - "vsmacros", - "vsw", - "webpnp", - "website", - "ws", - "wsc", - "wsf", - "wsh", - "xbap", - "xll", - "xnk" + // File types blocked by Microsoft 365 by default + // https://support.microsoft.com/en-us/office/blocked-attachments-in-outlook-434752e1-02d3-4e90-9124-8b81e49a8519 + "ade", + "adp", + "app", + "application", + "appref-ms", + "asp", + "aspx", + "asx", + // "bas", excluded at depth > 1 because they can exist natively in word docs within an archive. see below + "bat", + "bgi", + "cab", + // "cer", + "chm", + "cmd", + "cnt", + "com", + "cpl", + // "crt", + // "csh", + // "der", + "diagcab", + "exe", + "fxp", + "gadget", + // "grp", + "hlp", + "hpj", + "hta", + "htc", + // "inf", + "ins", + "iso", + "isp", + "its", + "jar", + "jnlp", + "js", + "jse", + "ksh", + "lnk", + "mad", + "maf", + "mag", + "mam", + "maq", + "mar", + "mas", + "mat", + "mau", + "mav", + "maw", + "mcf", + "mda", + // "mdb", + "mde", + "mdt", + "mdw", + "mdz", + "msc", + "msh", + "msh1", + "msh2", + "mshxml", + "msh1xml", + "msh2xml", + "msi", + "msp", + "mst", + "msu", + "ops", + "osd", + "pcd", + "pif", + "pl", + "plg", + "prf", + "prg", + "printerexport", + "ps1", + "ps1xml", + "ps2", + "ps2xml", + "psc1", + "psc2", + "psd1", + "psdm1", + "pst", + // "py", + // "pyc", + "pyo", + "pyw", + "pyz", + "pyzw", + "reg", + "scf", + "scr", + "sct", + "shb", + "shs", + "theme", + // "tmp", + "url", + "vb", + "vbe", + "vbp", + "vbs", + "vhd", + "vhdx", + "vsmacros", + "vsw", + "webpnp", + "website", + "ws", + "wsc", + "wsf", + "wsh", + "xbap", + "xll", + "xnk" + ) + or ( + // BASIC files can naturally occur in word docs, + // so only flag if depth is 1 (archive -> bas, not archive -> doc -> bas) + .depth == 1 + and .file_extension =~ "bas" + ) ) - or ( - // BASIC files can naturally occur in word docs, - // so only flag if depth is 1 (archive -> bas, not archive -> doc -> bas) - .depth == 1 - and .file_extension =~ "bas" - ) - ) ) tags: - "Attack surface reduction" diff --git a/detection-rules/attachment_docusign_image_suspicious_links.yml b/detection-rules/attachment_docusign_image_suspicious_links.yml index 76e6ca214fc..514b82554c1 100644 --- a/detection-rules/attachment_docusign_image_suspicious_links.yml +++ b/detection-rules/attachment_docusign_image_suspicious_links.yml @@ -1,33 +1,40 @@ name: "Attachment: DocuSign image lure with no DocuSign domains in links" description: "Detects DocuSign phishing emails with no DocuSign links, a DocuSign logo attached, from a first-time sender." type: "rule" -severity: "medium" +severity: "high" source: | type.inbound - and length(filter(attachments, .file_type not in~ ('png', 'jpeg', 'jpg', 'bmp', 'gif'))) == 0 + and length(filter(attachments, .file_type not in $file_types_images)) == 0 and any(body.links, not strings.ilike(.href_url.domain.root_domain, "docusign.*")) and any(attachments, - ( - any(ml.logo_detect(.).brands, .name == "DocuSign" and .confidence in ("medium", "high")) - or any(file.explode(.), - any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence != "low") - ) - ) - and any(file.explode(.), - any(.scan.strings.strings, regex.icontains(., - "review document", "[^d][^o][^c][^u]sign", "important edocs", "completed document")) - ) - ) - and ( ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails + any(ml.logo_detect(.).brands, .name == "DocuSign" and .confidence in ("medium", "high")) + or any(file.explode(.), + strings.ilike(.scan.ocr.raw, "*DocuSign*") + and any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence != "low" + ) + ) ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + and any(file.explode(.), + regex.icontains(.scan.ocr.raw, + "review document", + "[^d][^o][^c][^u]sign", + "important edocs", + "completed document" + ) ) ) + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + ) attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/attachment_dropbox_image_suspicious_links.yml b/detection-rules/attachment_dropbox_image_suspicious_links.yml index 77bed727988..1de0a856b31 100644 --- a/detection-rules/attachment_dropbox_image_suspicious_links.yml +++ b/detection-rules/attachment_dropbox_image_suspicious_links.yml @@ -4,25 +4,24 @@ type: "rule" severity: "medium" source: | type.inbound - and length(filter(attachments, .file_type not in~ ('png', 'jpeg', 'jpg', 'bmp'))) == 0 + and length(filter(attachments, .file_type not in $file_types_images)) == 0 and any(body.links, not strings.ilike(.href_url.domain.root_domain, "dropbox.*")) - - and any(attachments, .file_type in~ ('png','jpg','jpeg','bmp') - and any(file.explode(.), - any(.scan.strings.strings, strings.ilike(., "*dropbox*")) - and any(.scan.strings.strings, strings.ilike(., "*review*", "*sign*")) - ) + and any(attachments, + .file_type in $file_types_images + and any(file.explode(.), + strings.ilike(.scan.ocr.raw, "*dropbox*") + and strings.ilike(.scan.ocr.raw, "*review*", "*sign*") + ) ) - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_eicar.yml b/detection-rules/attachment_eicar.yml index 0ca141f4953..3ab44269525 100644 --- a/detection-rules/attachment_eicar.yml +++ b/detection-rules/attachment_eicar.yml @@ -11,11 +11,17 @@ authors: - twitter: "ajpc500" severity: "low" source: | - type.inbound + type.inbound and any(attachments, strings.icontains(.file_name, "eicar")) - and any(attachments, any(file.explode(.), - any(.scan.strings.strings, strings.icontains(., 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*')) - )) + and any(attachments, + any(file.explode(.), + any(.scan.strings.strings, + strings.icontains(., + 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' + ) + ) + ) + ) tags: - "EICAR" attack_types: diff --git a/detection-rules/attachment_eml_cred_theft.yml b/detection-rules/attachment_eml_cred_theft.yml index 88e8063435f..a85a54f7777 100644 --- a/detection-rules/attachment_eml_cred_theft.yml +++ b/detection-rules/attachment_eml_cred_theft.yml @@ -5,28 +5,41 @@ type: "rule" severity: "medium" source: | type.inbound - - and any(attachments, .content_type == "message/rfc822" - and any(file.explode(.), - any(.scan.url.urls, - .domain.domain in $free_file_hosts or - .domain.root_domain in $free_subdomain_hosts - ) - and any(.scan.url.urls, - beta.linkanalysis(.).credphish.disposition == "phishing" + and length(attachments) == 1 + and any(attachments, + .content_type == "message/rfc822" + and any(file.explode(.), + any(.scan.url.urls, + ( + .domain.root_domain in $free_subdomain_hosts + or .domain.root_domain in ("sharepoint.com") + or .domain.root_domain not in $tranco_1m + ) + and beta.linkanalysis(.).credphish.disposition == "phishing" + ) ) - ) ) // engaging language in the original body and any(ml.nlu_classifier(body.html.display_text).entities, .name == "request") // 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, .) + and not any(headers.references, strings.contains(body.html.display_text, .)) + + // unsolicited + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_eml_file_with_ipfs_links.yml b/detection-rules/attachment_eml_file_with_ipfs_links.yml index 2797732d568..0a6ec0b1893 100644 --- a/detection-rules/attachment_eml_file_with_ipfs_links.yml +++ b/detection-rules/attachment_eml_file_with_ipfs_links.yml @@ -8,28 +8,29 @@ type: "rule" severity: "medium" source: | type.inbound - - and any(attachments, .content_type == "message/rfc822" - and any(file.explode(.), - any(.scan.url.urls, - strings.icontains(beta.linkanalysis(.).effective_url.url, 'ipfs') - - or ( - regex.icontains(beta.linkanalysis(.).effective_url.path, '[\.-/]ipfs|ipfs[\.-/]') - and beta.linkanalysis(.).effective_url.domain.domain not in $org_domains - and ( - ( - // don't include high rep domains - beta.linkanalysis(.).effective_url.domain.domain not in $tranco_1m - and beta.linkanalysis(.).effective_url.domain.domain not in $umbrella_1m + and any(attachments, + .content_type == "message/rfc822" + and any(file.explode(.), + any(.scan.url.urls, + strings.icontains(beta.linkanalysis(.).effective_url.url, 'ipfs') + or ( + regex.icontains(beta.linkanalysis(.).effective_url.path, + '[\.-/]ipfs|ipfs[\.-/]' + ) + and beta.linkanalysis(.).effective_url.domain.domain not in $org_domains + and ( + ( + // don't include high rep domains + beta.linkanalysis(.).effective_url.domain.domain not in $tranco_1m + and beta.linkanalysis(.).effective_url.domain.domain not in $umbrella_1m + ) + // if it's in Tranco or Umbrella, still include it if it's one of these + or beta.linkanalysis(.).effective_url.domain.domain in $free_file_hosts + or beta.linkanalysis(.).effective_url.domain.root_domain in $free_subdomain_hosts + ) ) - // if it's in Tranco or Umbrella, still include it if it's one of these - or beta.linkanalysis(.).effective_url.domain.domain in $free_file_hosts - or beta.linkanalysis(.).effective_url.domain.root_domain in $free_subdomain_hosts ) - ) ) - ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_eml_html_attachment_portal.yml b/detection-rules/attachment_eml_html_attachment_portal.yml index 5dc69446d86..2bcdd9998c4 100644 --- a/detection-rules/attachment_eml_html_attachment_portal.yml +++ b/detection-rules/attachment_eml_html_attachment_portal.yml @@ -24,52 +24,53 @@ source: | and any(attachments, .content_type == "message/rfc822" and any(file.explode(.), - ( - // suspicious strings found in javascript - length(filter(.scan.javascript.strings, - strings.ilike(., - "*username*", - "*login-form*", - "*email-form*", - "*Incorrect password. Please try again.*", - "*Password Incomplete, please try again*" - ) - ) - ) - >= 3 - or ( + // suspicious strings found in javascript + length(filter(.scan.javascript.strings, + strings.ilike(., + "*username*", + "*login-form*", + "*email-form*", + "*Incorrect password. Please try again.*", + "*Password Incomplete, please try again*" + ) + ) + ) >= 3 + or ( - // suspicious strings found outside of javascript, but binexplode'd file still of HTML type - .flavors.mime in~ ("text/html", "text/plain") - and length(filter(.scan.strings.strings, - strings.ilike(., - "*username*", - "*login-form*", - "*email-form*", - "*Incorrect password. Please try again.*", - "*Password Incomplete, please try again*" - ) - ) + // suspicious strings found outside of javascript, but binexplode'd file still of HTML type + .flavors.mime in~ ("text/html", "text/plain") + and 3 of ( + any(.scan.strings.strings, strings.ilike(., "*username*")), + any(.scan.strings.strings, strings.ilike(., "*login-form*")), + any(.scan.strings.strings, strings.ilike(., "*email-form*")), + any(.scan.strings.strings, + strings.ilike(., "*Incorrect password. Please try again.*") + ), + any(.scan.strings.strings, + strings.ilike(., "*Password Incomplete, please try again*") ) - >= 3 ) ) or //Known phishing obfuscation - ( - length(filter(.scan.strings.strings, - strings.ilike(., - //Enter password - "*Enter password*", - //Forgotten my password - "*Forgotten my password*", - //Sign in - "*Sign in*" - ) - ) + 2 of ( + // Enter password + any(.scan.strings.strings, + strings.ilike(., + "*Enter password*" + ) + ), + // Forgotten my password + any(.scan.strings.strings, + strings.ilike(., + "*Forgotten my password*" + ) + ), + // Sign in + any(.scan.strings.strings, + strings.ilike(., "*Sign in*") ) - >= 2 ) ) ) diff --git a/detection-rules/attachment_eml_suspicious_link_language.yml b/detection-rules/attachment_eml_suspicious_link_language.yml deleted file mode 100644 index 6e56eff21fa..00000000000 --- a/detection-rules/attachment_eml_suspicious_link_language.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: "Attachment: EML with suspicious link & engaging language (unsolicited)" -description: | - Attached EML uses engaging language and links to a file sharing or free subdomain link from an unsolicited sender. -type: "rule" -severity: "medium" -source: | - type.inbound - - and any(attachments, .content_type == "message/rfc822" - and any(file.explode(.), - any(.scan.url.urls, - .domain.domain in $free_file_hosts or - .domain.root_domain in $free_subdomain_hosts - ) - - // ideally we have the full raw string instead of - // an array, hopefully we can switch to that soon - and any(.scan.strings.strings, - any(ml.nlu_classifier(.).intents, - .name != "benign" and - .confidence in ("medium", "high") - ) - ) - ) - ) - - // engaging language in the original body - and any(ml.nlu_classifier(body.html.display_text).entities, .name == "request") - and any(ml.nlu_classifier(body.html.display_text).entities, .name == "urgency") - // any non-benign intent with any confidence - and any(ml.nlu_classifier(body.html.display_text).intents, .name != "benign") - - // exclude bounce backs & read receipts - 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, .) - ) - - // unsolicited - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) - ) -attack_types: - - "Credential Phishing" -tactics_and_techniques: - - "Evasion" - - "Free file host" - - "Free subdomain host" - - "Social engineering" -detection_methods: - - "File analysis" - - "Header analysis" - - "HTML analysis" - - "Natural Language Understanding" - - "Sender analysis" - - "URL analysis" -id: "2038ffcc-c38e-5cb3-8594-7f40c112d08c" diff --git a/detection-rules/attachment_eml_with_html_attachment.yml b/detection-rules/attachment_eml_with_html_attachment.yml index 221f4a1e697..68fac95489f 100644 --- a/detection-rules/attachment_eml_with_html_attachment.yml +++ b/detection-rules/attachment_eml_with_html_attachment.yml @@ -9,15 +9,16 @@ source: | type.inbound // has EML attachment - and any(attachments, .content_type == "message/rfc822" - and any(file.explode(.), + and any(attachments, + .content_type == "message/rfc822" + and any(file.explode(.), - // HTML file inside EML attachment - // we've seen files named ".htm.", which results in an empty - // .file_extension, so instead we look at .file_name - // they should be rare enough in EML attachments to not cause - // extraneous FPs - strings.ilike(.file_name, "*htm*") + // HTML file inside EML attachment + // we've seen files named ".htm.", which results in an empty + // .file_extension, so instead we look at .file_name + // they should be rare enough in EML attachments to not cause + // extraneous FPs + strings.ilike(.file_name, "*htm*") // optional: we can add additional signals here if necessary // identify at least one additional suspicious signal in the message @@ -30,7 +31,7 @@ source: | // // commonly abused sender TLD // strings.ilike(sender.email.domain.tld, "*.jp") // ) - ) + ) ) // exclude bounce backs & read receipts @@ -38,20 +39,18 @@ source: | 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, .) - ) + and not any(headers.references, strings.contains(body.html.display_text, .)) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Attack surface reduction" diff --git a/detection-rules/attachment_emotet_heavily_padded_doc_in_zip.yml b/detection-rules/attachment_emotet_heavily_padded_doc_in_zip.yml index dd39e0e495a..b23bcff7ba2 100644 --- a/detection-rules/attachment_emotet_heavily_padded_doc_in_zip.yml +++ b/detection-rules/attachment_emotet_heavily_padded_doc_in_zip.yml @@ -8,14 +8,15 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, - .file_extension == "zip" - and any(file.explode(.), - .depth == 0 and .size < 1000000 - and not .depth > 0 - and strings.ends_with(.scan.exiftool.zip_file_name, ".doc") - and .scan.exiftool.zip_uncompressed_size > 500000000 - ) + and any(attachments, + .file_extension == "zip" + and any(file.explode(.), + .depth == 0 + and .size < 1000000 + and not .depth > 0 + and strings.ends_with(.scan.exiftool.zip_file_name, ".doc") + and .scan.exiftool.zip_uncompressed_size > 500000000 + ) ) and ( ( diff --git a/detection-rules/attachment_encrypted_ole_unsolicited.yml b/detection-rules/attachment_encrypted_ole_unsolicited.yml index db7335545c1..6e591479b56 100644 --- a/detection-rules/attachment_encrypted_ole_unsolicited.yml +++ b/detection-rules/attachment_encrypted_ole_unsolicited.yml @@ -9,18 +9,18 @@ severity: "high" source: | type.inbound and any(attachments, - .file_extension in~ $file_extensions_macros - and file.oletools(.).indicators.encryption.exists + .file_extension in~ $file_extensions_macros + and file.oletools(.).indicators.encryption.exists ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_excel_web_query_file_iqy.yml b/detection-rules/attachment_excel_web_query_file_iqy.yml index 5c9666f5fa5..2a068d4a3d3 100644 --- a/detection-rules/attachment_excel_web_query_file_iqy.yml +++ b/detection-rules/attachment_excel_web_query_file_iqy.yml @@ -13,12 +13,13 @@ severity: "high" source: | type.inbound and ( - any(attachments, .file_extension =~ "iqy") - or ( - any(attachments, .file_extension in~ $file_extensions_common_archives - and any(file.explode(.), .file_extension =~ "iqy") - ) + any(attachments, .file_extension =~ "iqy") + or ( + any(attachments, + .file_extension in~ $file_extensions_common_archives + and any(file.explode(.), .file_extension =~ "iqy") ) + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_filename_with_unicode_rtlo.yml b/detection-rules/attachment_filename_with_unicode_rtlo.yml index 4bc236eae92..500f5981222 100644 --- a/detection-rules/attachment_filename_with_unicode_rtlo.yml +++ b/detection-rules/attachment_filename_with_unicode_rtlo.yml @@ -11,13 +11,12 @@ severity: "high" source: | type.inbound and any(attachments, - regex.icontains(.file_name, '\x{202E}', '\x{202D}') or ( - .file_extension in~ $file_extensions_common_archives - and any(file.explode(.), - regex.icontains(.file_name, '\x{202E}', '\x{202D}') - ) + regex.icontains(.file_name, '\x{202E}', '\x{202D}') + or ( + .file_extension in~ $file_extensions_common_archives + and any(file.explode(.), regex.icontains(.file_name, '\x{202E}', '\x{202D}')) ) - ) + ) attack_types: - "Malware/Ransomware" tactics_and_techniques: diff --git a/detection-rules/attachment_free_subdomain_suspicious_link_language.yml b/detection-rules/attachment_free_subdomain_suspicious_link_language.yml index 3dad2cd4cab..11fa2309c25 100644 --- a/detection-rules/attachment_free_subdomain_suspicious_link_language.yml +++ b/detection-rules/attachment_free_subdomain_suspicious_link_language.yml @@ -5,24 +5,18 @@ type: "rule" severity: "high" source: | type.inbound - and any(body.links, - .href_url.domain.root_domain in $free_subdomain_hosts - and .href_url.domain.subdomain is not null - and .href_url.domain.subdomain != "www" - ) - and ( - length(recipients.to) == 0 - or all(recipients.to, .display_name == "Undisclosed recipients") + and any(body.links, + .href_url.domain.root_domain in $free_subdomain_hosts + and .href_url.domain.subdomain is not null + and .href_url.domain.subdomain != "www" ) + and (length(recipients.to) == 0 or all(recipients.to, .display_name == "Undisclosed recipients")) and length(recipients.cc) == 0 and length(recipients.bcc) == 0 - and any(body.links, - any(file.explode(beta.linkanalysis(.).screenshot), - any(ml.nlu_classifier(.scan.ocr.raw).intents, - .name == "cred_theft" + any(file.explode(beta.linkanalysis(.).screenshot), + any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft") ) - ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_html_all_script.yml b/detection-rules/attachment_html_all_script.yml index f6c6ff606a7..ac5b9b86b91 100644 --- a/detection-rules/attachment_html_all_script.yml +++ b/detection-rules/attachment_html_all_script.yml @@ -4,22 +4,18 @@ description: | type: "rule" severity: "medium" source: | - type.inbound + type.inbound and any(attachments, - ( - .file_extension in~ ("html", "htm", "shtml", "dhtml") or - .file_extension in~ $file_extensions_common_archives or - .file_type == "html" - ) - and any(file.explode(.), - length(.scan.strings.strings) == 1 - and any(.scan.strings.strings, - strings.starts_with(., "") + and any(file.explode(.), + length(.scan.strings.strings) == 1 + and any(.scan.strings.strings, strings.starts_with(., "")) ) - ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_html_attachment_login_page.yml b/detection-rules/attachment_html_attachment_login_page.yml index 1838f3cdc13..6f720efda3f 100644 --- a/detection-rules/attachment_html_attachment_login_page.yml +++ b/detection-rules/attachment_html_attachment_login_page.yml @@ -10,55 +10,74 @@ severity: "medium" authors: - twitter: "ajpc500" source: | - type.inbound - + type.inbound and any(attachments, - ( - .file_extension in~ ("html", "htm", "shtml", "dhtml") or - .file_extension in~ $file_extensions_common_archives or - .file_type == "html" - ) - and any(file.explode(.), - ( - // suspicious strings found in javascript - length(filter(.scan.javascript.strings, strings.ilike(., - "*password*", "*username*", "*login-form*", "*email-form*", "*Incorrect password. Please try again.*", "*Password Incomplete, please try again*" - ))) >= 3 or ( - // suspicious strings found outside of javascript, but binexplode'd file still of HTML type - .flavors.mime in~ ("text/html", "text/plain") and - length(filter(.scan.strings.strings, strings.ilike(., - "*password*", "*username*", "*login-form*", "*email-form*", "*Incorrect password. Please try again.*", "*Password Incomplete, please try again*" - ))) >= 3 + .file_extension in~ ("html", "htm", "shtml", "dhtml") + or .file_extension in~ $file_extensions_common_archives + or .file_type == "html" ) - ) or - //Known phishing obfuscation - ( - length( - filter( - .scan.strings.strings, strings.ilike(., - //Enter password - "*Enter password*", - //Forgotten my password - "*Forgotten my password*", - //Sign in - "*Sign in*" + and any(file.explode(.), + // suspicious strings found in javascript + ( + length(filter(.scan.javascript.strings, strings.ilike(., "*password*", ))) >= 2 + and 2 of ( + any(.scan.javascript.strings, strings.ilike(., "*incorrect*")), + any(.scan.javascript.strings, strings.ilike(., "*invalid*")), + any(.scan.javascript.strings, strings.ilike(., "*login*")), + any(.scan.javascript.strings, regex.icontains(., "sign.in")), + ) ) - ) - ) >= 2 - ) - - )) + or ( + // suspicious strings found outside of javascript, but binexplode'd file still of HTML type + length(filter(.scan.strings.strings, strings.ilike(., "*password*", ))) >= 2 + and 2 of ( + any(.scan.strings.strings, strings.ilike(., "*incorrect*")), + any(.scan.strings.strings, strings.ilike(., "*invalid*")), + any(.scan.strings.strings, strings.ilike(., "*login*")), + any(.scan.strings.strings, strings.ilike(., "* - and any(.scan.strings.strings, strings.icontains(., "ActiveXObject")) - and any(.scan.strings.strings, strings.icontains(., "WScript.Shell")) - and any(.scan.strings.strings, strings.like(., "*Run*", "*Execute*")) - ) + (.file_extension =~ "svg" or .file_extension in $file_extensions_common_archives) + and any(file.explode(.), + .file_extension == "svg" + // Author Matt harr0ey @harr0ey + // Topic: SVG file Execution + // WScript inside SVG + // + and any(.scan.strings.strings, strings.icontains(., "ActiveXObject")) + and any(.scan.strings.strings, strings.icontains(., "WScript.Shell")) + and any(.scan.strings.strings, strings.like(., "*Run*", "*Execute*")) + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_url_with_unc_path.yml b/detection-rules/attachment_url_with_unc_path.yml index 366944f0bd7..9abaa8ae150 100644 --- a/detection-rules/attachment_url_with_unc_path.yml +++ b/detection-rules/attachment_url_with_unc_path.yml @@ -6,12 +6,17 @@ references: type: "rule" severity: "medium" source: | - type.inbound - and any(attachments, .file_extension in ("lnk", "url") - and any(file.explode(.), - any(.scan.strings.strings, regex.icontains(., '\\\\([a-zA-Z0-9_:%.$-]+)\\([a-zA-Z0-9_:%.$-]+)')) // normal UNC paths - or any(.scan.strings.strings, regex.icontains(., '%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)')) // percent-encoded UNC paths - ) + type.inbound + and any(attachments, + .file_extension in ("lnk", "url") + and any(file.explode(.), + any(.scan.strings.strings, + regex.icontains(., '\\\\([a-zA-Z0-9_:%.$-]+)\\([a-zA-Z0-9_:%.$-]+)') + ) // normal UNC paths + or any(.scan.strings.strings, + regex.icontains(., '%5C%5C([a-zA-Z0-9_:%.$-]+)%5C([a-zA-Z0-9_:%.$-]+)') + ) // percent-encoded UNC paths + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml b/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml index d4ba1a6a1c0..37e28fd0864 100644 --- a/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml +++ b/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml @@ -8,20 +8,20 @@ references: type: "rule" severity: "medium" source: | - type.inbound - and any(attachments, - .file_extension in~ $file_extensions_macros - and any(file.oletools(.).macros.keywords, .type =~ "autoexec") + type.inbound + and any(attachments, + .file_extension in~ $file_extensions_macros + and any(file.oletools(.).macros.keywords, .type =~ "autoexec") ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) // negate replies diff --git a/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml b/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml index 37dfcf5b083..15d1abef2b1 100644 --- a/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml +++ b/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml @@ -8,24 +8,22 @@ severity: "medium" source: | type.inbound and any(attachments, + ( + .file_extension in~ $file_extensions_macros + or .file_extension in~ $file_extensions_common_archives + ) + and any(file.explode(.), any(.scan.vba.auto_exec, . == "AutoOpen")) + ) + and ( ( - .file_extension in~ $file_extensions_macros - or .file_extension in~ $file_extensions_common_archives + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails ) - and any(file.explode(.), - any(.scan.vba.auto_exec, . == "AutoOpen") + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains ) ) - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) - ) attack_types: - "Malware/Ransomware" tactics_and_techniques: diff --git a/detection-rules/attachment_vba_macro_calling_executable.yml b/detection-rules/attachment_vba_macro_calling_executable.yml index ca8f74e4bcd..afea6b087aa 100644 --- a/detection-rules/attachment_vba_macro_calling_executable.yml +++ b/detection-rules/attachment_vba_macro_calling_executable.yml @@ -9,9 +9,12 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, (.file_extension in~ $file_extensions_macros or .file_extension in~ $file_extensions_common_archives) - and any(file.explode(.), - any(.scan.vba.hex, strings.ilike(., "*exe*"))) + and any(attachments, + ( + .file_extension in~ $file_extensions_macros + or .file_extension in~ $file_extensions_common_archives + ) + and any(file.explode(.), any(.scan.vba.hex, strings.ilike(., "*exe*"))) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_vba_macro_employee_impersonation.yml b/detection-rules/attachment_vba_macro_employee_impersonation.yml index 64fa45578d8..56297c4fc66 100644 --- a/detection-rules/attachment_vba_macro_employee_impersonation.yml +++ b/detection-rules/attachment_vba_macro_employee_impersonation.yml @@ -14,18 +14,21 @@ source: | type.inbound and sender.display_name in $org_display_names and any(attachments, - (.file_extension in~ $file_extensions_macros or .file_extension in~ $file_extensions_common_archives) - and file.oletools(.).indicators.vba_macros.exists - ) - and ( ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + .file_extension in~ $file_extensions_macros + or .file_extension in~ $file_extensions_common_archives ) + and file.oletools(.).indicators.vba_macros.exists + ) + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_vba_macro_high_risk.yml b/detection-rules/attachment_vba_macro_high_risk.yml index 56be092673d..87e0802a0d1 100644 --- a/detection-rules/attachment_vba_macro_high_risk.yml +++ b/detection-rules/attachment_vba_macro_high_risk.yml @@ -7,19 +7,19 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, - .file_extension in~ $file_extensions_macros - and file.oletools(.).indicators.vba_macros.risk == "high" + and any(attachments, + .file_extension in~ $file_extensions_macros + and file.oletools(.).indicators.vba_macros.risk == "high" ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_with_encrypted_zip_unsolicited.yml b/detection-rules/attachment_with_encrypted_zip_unsolicited.yml index c81f3e21e0b..02c3d167ed8 100644 --- a/detection-rules/attachment_with_encrypted_zip_unsolicited.yml +++ b/detection-rules/attachment_with_encrypted_zip_unsolicited.yml @@ -7,18 +7,19 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, (.file_type == "zip" or .file_extension == "zip") - and any(file.explode(.), any(.flavors.yara, . == 'encrypted_zip')) + and any(attachments, + (.file_type == "zip" or .file_extension == "zip") + and any(file.explode(.), any(.flavors.yara, . == 'encrypted_zip')) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_with_suspicious_author_unsolicited.yml b/detection-rules/attachment_with_suspicious_author_unsolicited.yml index 5a9e5decc7f..b1a0aefa868 100644 --- a/detection-rules/attachment_with_suspicious_author_unsolicited.yml +++ b/detection-rules/attachment_with_suspicious_author_unsolicited.yml @@ -5,19 +5,22 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, (.file_extension in~ ("doc", "docm", "docx", "dot", "dotm") or .file_extension in~ $file_extensions_common_archives) - and any(file.explode(.), strings.ilike(.scan.docx.author, "root") - ) + and any(attachments, + ( + .file_extension in~ ("doc", "docm", "docx", "dot", "dotm") + or .file_extension in~ $file_extensions_common_archives + ) + and any(file.explode(.), strings.ilike(.scan.docx.author, "root")) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml b/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml index f8204c292ae..ea490e8480e 100644 --- a/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml +++ b/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml @@ -8,20 +8,22 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, (.file_type == "zip" or .file_extension == "zip") - and any(file.explode(.), - any(.flavors.yara, . == 'encrypted_zip') and .scan.encrypted_zip.cracked_password == null - ) + and any(attachments, + (.file_type == "zip" or .file_extension == "zip") + and any(file.explode(.), + any(.flavors.yara, . == 'encrypted_zip') + and .scan.encrypted_zip.cracked_password == null + ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/body_business_email_compromise_new_sender.yml b/detection-rules/body_business_email_compromise_new_sender.yml index 18e7cea6a04..1c509c258c0 100644 --- a/detection-rules/body_business_email_compromise_new_sender.yml +++ b/detection-rules/body_business_email_compromise_new_sender.yml @@ -5,22 +5,27 @@ type: "rule" severity: "medium" source: | type.inbound - - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name in ("bec") and .confidence == "high" + and any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("bec") and .confidence == "high" + ) + // negating legit replies + and not ( + strings.istarts_with(subject.subject, "RE:") + and ( + length(headers.references) > 0 + or any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) ) - + ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/body_business_email_compromise_unsolicited.yml b/detection-rules/body_business_email_compromise_unsolicited.yml index 56610cc6c3a..f47916f189f 100644 --- a/detection-rules/body_business_email_compromise_unsolicited.yml +++ b/detection-rules/body_business_email_compromise_unsolicited.yml @@ -5,38 +5,39 @@ type: "rule" severity: "medium" source: | type.inbound - - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name in ("bec") and .confidence == "high" + and any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("bec") and .confidence == "high" ) - and 1 of ( - ( - // mismatched From and Reply-to - length(headers.reply_to) > 0 - and all(headers.reply_to, .email.domain.root_domain != sender.email.domain.root_domain) - ), - ( - // DMARC failure - any(distinct(headers.hops, .authentication_results.dmarc is not null), strings.ilike(.authentication_results.dmarc, "*fail")) - ), - ( - // SPF failure - any(distinct(headers.hops, .received_spf.verdict is not null), strings.ilike(.received_spf.verdict, "*fail")) - ), + ( + // mismatched From and Reply-to + length(headers.reply_to) > 0 + and all(headers.reply_to, .email.domain.root_domain != sender.email.domain.root_domain) + ), + ( + // DMARC failure + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ), + ( + // SPF failure + any(distinct(headers.hops, .received_spf.verdict is not null), + strings.ilike(.received_spf.verdict, "*fail") + ) + ), ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/body_callback_phishing_no_attachment.yml b/detection-rules/body_callback_phishing_no_attachment.yml index f537ce3ce84..b946d070b17 100644 --- a/detection-rules/body_callback_phishing_no_attachment.yml +++ b/detection-rules/body_callback_phishing_no_attachment.yml @@ -9,32 +9,50 @@ source: | type.inbound and length(attachments) == 0 and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) - and sender.email.domain.root_domain in $free_email_providers - and strings.ilike(body.plain.raw, "*mcafee*", "*norton*", "*geek squad*", "*paypal*", "*ebay*", "*symantec*", "*best buy*", "*lifelock*") - and 4 of ( - strings.ilike(body.plain.raw, '*purchase*'), - strings.ilike(body.plain.raw, '*subscription*'), - strings.ilike(body.plain.raw, '*antivirus*'), - strings.ilike(body.plain.raw, '*order*'), - strings.ilike(body.plain.raw, '*support*'), - strings.ilike(body.plain.raw, '*receipt*'), - strings.ilike(body.plain.raw, '*invoice*'), - strings.ilike(body.plain.raw, '*call*'), - strings.ilike(body.plain.raw, '*cancel*'), - strings.ilike(body.plain.raw, '*renew*'), - strings.ilike(body.plain.raw, '*refund*'), - strings.ilike(body.plain.raw, '*+1*') + and strings.ilike(body.current_thread.text, + "*mcafee*", + "*norton*", + "*geek squad*", + "*paypal*", + "*ebay*", + "*symantec*", + "*best buy*", + "*lifelock*" ) + and length(body.current_thread.text) < 1500 + and 3 of ( + strings.ilike(body.current_thread.text, '*purchase*'), + strings.ilike(body.current_thread.text, '*payment*'), + strings.ilike(body.current_thread.text, '*transaction*'), + strings.ilike(body.current_thread.text, '*subscription*'), + strings.ilike(body.current_thread.text, '*antivirus*'), + strings.ilike(body.current_thread.text, '*order*'), + strings.ilike(body.current_thread.text, '*support*'), + strings.ilike(body.current_thread.text, '*help line*'), + strings.ilike(body.current_thread.text, '*receipt*'), + strings.ilike(body.current_thread.text, '*invoice*'), + strings.ilike(body.current_thread.text, '*call*'), + strings.ilike(body.current_thread.text, '*cancel*'), + strings.ilike(body.current_thread.text, '*renew*'), + strings.ilike(body.current_thread.text, '*refund*') + ) + // phone number regex + and regex.icontains(body.current_thread.text, '\+?(\d{1}.)?\(?\d{3}?\)?.\d{3}.?\d{4}') + and sender.email.domain.root_domain not in ( + // paypal domain + "xoom.com" + ) + and not strings.ends_with(headers.message_id, "@shopify.com>") attack_types: - "Callback Phishing" tactics_and_techniques: diff --git a/detection-rules/body_extortion.yml b/detection-rules/body_extortion.yml index 62fb414bdda..3beca403221 100644 --- a/detection-rules/body_extortion.yml +++ b/detection-rules/body_extortion.yml @@ -6,27 +6,24 @@ references: type: "rule" severity: "low" source: | - type.inbound - and any([body.html.display_text, body.plain.raw], - any(ml.nlu_classifier(.).intents, - .name == "extortion" and .confidence == "high" - ) - and ( - any(ml.nlu_classifier(.).entities, .name == "financial") - ) + type.inbound + and ( + any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "extortion" and .confidence == "high" + ) + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "financial") ) - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) - // many extortion emails spoof sender domains and fail sender authentication - or any(headers.hops, .authentication_results.dmarc == "fail") + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + // many extortion emails spoof sender domains and fail sender authentication + or any(headers.hops, .authentication_results.dmarc == "fail") ) attack_types: - "Extortion" diff --git a/detection-rules/body_html_callback_phishing_no_attachment.yml b/detection-rules/body_html_callback_phishing_no_attachment.yml deleted file mode 100644 index 2241ffac3b7..00000000000 --- a/detection-rules/body_html_callback_phishing_no_attachment.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: "Body HTML: Callback Phishing solicitation" -description: | - A fraudulent invoice/receipt found in the html body of the message. - Callback Phishing is an attempt by an attacker to solicit the victim (recipient) to call a phone number. - The resulting interaction could lead to a multitude of attacks ranging from Financial theft, Remote Access Trojan (RAT) Installation or Ransomware Deployment. -type: "rule" -severity: "medium" -source: | - type.inbound - and length(attachments) == 0 - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) - ) - - and sender.email.domain.root_domain in $free_email_providers - and any([body.html.inner_text], strings.ilike(., "*mcafee*", "*norton*", "*geek squad*", "*paypal*", "*ebay*", "*symantec*", "*best buy*", "*lifelock*")) - and any([body.html.inner_text], strings.ilike(., "*+1*")) - - and 4 of ( - strings.ilike(body.html.inner_text, '*purchase*'), - strings.ilike(body.html.inner_text, '*subscription*'), - strings.ilike(body.html.inner_text, '*antivirus*'), - strings.ilike(body.html.inner_text, '*order*'), - strings.ilike(body.html.inner_text, '*support*'), - strings.ilike(body.html.inner_text, '*receipt*'), - strings.ilike(body.html.inner_text, '*invoice*'), - strings.ilike(body.html.inner_text, '*call*'), - strings.ilike(body.html.inner_text, '*cancel*'), - strings.ilike(body.html.inner_text, '*renew*'), - strings.ilike(body.html.inner_text, '*refund*') - ) -attack_types: - - "Callback Phishing" -tactics_and_techniques: - - "Free email provider" - - "Impersonation: Brand" - - "Out of band pivot" - - "Social engineering" -detection_methods: - - "Content analysis" - - "Sender analysis" - - "URL analysis" -id: "afe5dec2-1ec0-505e-b5dd-768144d71bec" diff --git a/detection-rules/body_job_scam_new_sender.yml b/detection-rules/body_job_scam_new_sender.yml index 7e4c12ace6f..e8f38c799a2 100644 --- a/detection-rules/body_job_scam_new_sender.yml +++ b/detection-rules/body_job_scam_new_sender.yml @@ -4,26 +4,21 @@ description: | type: "rule" severity: "low" source: | - type.inbound - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name in ("job_scam") and .confidence == "high" - - and ( - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities, .name == "financial") - ) + type.inbound + and any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("job_scam") + and .confidence == "high" + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "financial") ) - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/body_microsoft_logo_bing_redirect.yml b/detection-rules/body_microsoft_logo_bing_redirect.yml index cb7058d8f47..0e1617419ce 100644 --- a/detection-rules/body_microsoft_logo_bing_redirect.yml +++ b/detection-rules/body_microsoft_logo_bing_redirect.yml @@ -8,57 +8,54 @@ source: | // Microsoft logo and ( - any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft")) - ) - or - any(attachments, - .file_type in~ ('bmp', 'png', 'jpg', 'jpeg') - and ( - any(file.explode(.), - length(filter(.scan.strings.strings, strings.ilike(., - "*password*", - "*unread messages*", - "*Shared Documents*", - "*expiration*", - "*office*", - "*expire*", - "*expiring*", - "*kindly*", - "*renew*", - "*review", - "*emails failed*", - "*kicked out*", - "*prevented*", - "*storage quota*", - "*required now", - "*cache*", - "*qr code*", - "*barcode*", - "*security update*", - "*quarantine*" - ))) >= 2 - ) - ) - ) + any(attachments, + .file_type in $file_types_images + and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft")) + ) + or any(attachments, + .file_type in $file_types_images + and ( + any(file.explode(.), + 2 of ( + strings.ilike(.scan.ocr.raw, "*password*"), + strings.ilike(.scan.ocr.raw, "*unread messages*"), + strings.ilike(.scan.ocr.raw, "*Shared Documents*"), + strings.ilike(.scan.ocr.raw, "*expiration*"), + strings.ilike(.scan.ocr.raw, "*office*"), + strings.ilike(.scan.ocr.raw, "*expire*"), + strings.ilike(.scan.ocr.raw, "*expiring*"), + strings.ilike(.scan.ocr.raw, "*kindly*"), + strings.ilike(.scan.ocr.raw, "*renew*"), + strings.ilike(.scan.ocr.raw, "*review"), + strings.ilike(.scan.ocr.raw, "*emails failed*"), + strings.ilike(.scan.ocr.raw, "*kicked out*"), + strings.ilike(.scan.ocr.raw, "*prevented*"), + strings.ilike(.scan.ocr.raw, "*storage quota*"), + strings.ilike(.scan.ocr.raw, "*required now"), + strings.ilike(.scan.ocr.raw, "*cache*"), + strings.ilike(.scan.ocr.raw, "*qr code*"), + strings.ilike(.scan.ocr.raw, "*barcode*"), + strings.ilike(.scan.ocr.raw, "*security update*"), + strings.ilike(.scan.ocr.raw, "*quarantine*") + ) + ) + ) + ) ) // Bing redirect and any(body.links, .href_url.domain.root_domain == 'bing.com' and .href_url.path =~ '/ck/a') - and sender.email.domain.root_domain not in $org_domains - and sender.email.domain.root_domain not in ( - "bing.com", - "microsoft.com", - "microsoftonline.com", - "microsoftsupport.com", - "microsoft365.com", - "office.com", - "onedrive.com", - "sharepointonline.com", - "yammer.com" + "bing.com", + "microsoft.com", + "microsoftonline.com", + "microsoftsupport.com", + "microsoft365.com", + "office.com", + "onedrive.com", + "sharepointonline.com", + "yammer.com" ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/body_unicode_slashes_in_url.yml b/detection-rules/body_unicode_slashes_in_url.yml index 5dfe4f3fe9f..4b2e73ff606 100644 --- a/detection-rules/body_unicode_slashes_in_url.yml +++ b/detection-rules/body_unicode_slashes_in_url.yml @@ -8,10 +8,12 @@ authors: references: - https://medium.com/@bobbyrsec/the-dangers-of-googles-zip-tld-5e1e675e59a5 source: | - type.inbound and - ( - regex.icontains(body.plain.raw, 'https?:\/\/[^\s⁄∕]+(?:\/[^\s⁄∕]+)*[⁄∕][^\s⁄∕]+') or - any(body.links, regex.icontains(.href_url.url,'https?:\/\/[^\s⁄∕]+(?:\/[^\s⁄∕]+)*[⁄∕][^\s⁄∕]+')) + type.inbound + and ( + regex.icontains(body.plain.raw, 'https?:\/\/[^\s⁄∕]+(?:\/[^\s⁄∕]+)*[⁄∕][^\s⁄∕]+') + or any(body.links, + regex.icontains(.href_url.url, 'https?:\/\/[^\s⁄∕]+(?:\/[^\s⁄∕]+)*[⁄∕][^\s⁄∕]+') + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/callback_phishing_nlu_body_or_attachments.yml b/detection-rules/callback_phishing_nlu_body_or_attachments.yml index 4aa91a9de3c..2eaa5c00728 100644 --- a/detection-rules/callback_phishing_nlu_body_or_attachments.yml +++ b/detection-rules/callback_phishing_nlu_body_or_attachments.yml @@ -4,30 +4,36 @@ description: | type: "rule" severity: "medium" source: | - type.inbound - and ( - any(attachments, - .file_type in ("png", "jpg", "pdf") - and any(file.explode(.), - any(ml.nlu_classifier(.scan.ocr.raw).intents, - .name == "callback_scam" and .confidence == "high" - ) - ) - ) - or any(ml.nlu_classifier(body.current_thread.text).intents, - .name in ("callback_scam") and .confidence == "high" - ) + type.inbound + and ( + any(attachments, + (.file_type in $file_types_images or .file_type == "pdf") + and any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "callback_scam" and .confidence == "high" + ) + ) ) - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + or any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("callback_scam") + and .confidence == "high" + and length(body.current_thread.text) < 1500 ) + ) + and not ( + any(headers.domains, .domain == "smtp-out.gcp.bigcommerce.net") + and strings.icontains(body.html.raw, "bigcommerce.com") + ) + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + ) attack_types: - "Callback Phishing" tactics_and_techniques: diff --git a/detection-rules/cve_2021_40444_external_relationship.yml b/detection-rules/cve_2021_40444_external_relationship.yml index d98db979cbb..f7b83ff077b 100644 --- a/detection-rules/cve_2021_40444_external_relationship.yml +++ b/detection-rules/cve_2021_40444_external_relationship.yml @@ -17,16 +17,17 @@ severity: "critical" source: | type.inbound and any(attachments, - ( - (.file_extension in~ $file_extensions_macros or .file_extension =~ "rtf") - and any(file.oletools(.).relationships, regex.icontains(.target, ".*html:http.*")) - ) or ( - .file_extension in~ $file_extensions_common_archives - and any(file.explode(.), - .flavors.mime == "text/xml" and - any(.scan.strings.strings, regex.icontains(., ".*oleObject.*mhtml.*http.*")) + ( + (.file_extension in~ $file_extensions_macros or .file_extension =~ "rtf") + and any(file.oletools(.).relationships, regex.icontains(.target, ".*html:http.*")) + ) + or ( + .file_extension in~ $file_extensions_common_archives + and any(file.explode(.), + .flavors.mime == "text/xml" + and any(.scan.strings.strings, regex.icontains(., ".*oleObject.*mhtml.*http.*")) + ) ) - ) ) tags: - "CVE-2021-40444" diff --git a/detection-rules/file_sharing_link_from_suspicious_sender_domain.yml b/detection-rules/file_sharing_link_from_suspicious_sender_domain.yml index bedb767f21f..025a1355b86 100644 --- a/detection-rules/file_sharing_link_from_suspicious_sender_domain.yml +++ b/detection-rules/file_sharing_link_from_suspicious_sender_domain.yml @@ -8,14 +8,14 @@ source: | and any(body.links, .href_url.domain.domain in $free_file_hosts) and sender.email.domain.tld in $suspicious_tlds and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/file_sharing_link_suspicious_subject.yml b/detection-rules/file_sharing_link_suspicious_subject.yml index ff3c735beee..88d8b23f04c 100644 --- a/detection-rules/file_sharing_link_suspicious_subject.yml +++ b/detection-rules/file_sharing_link_suspicious_subject.yml @@ -7,17 +7,25 @@ severity: "medium" source: | type.inbound and sender.email.domain.root_domain != 'google.com' - and any(body.links, .href_url.domain.domain in $free_file_hosts) + and any(body.links, + .href_url.domain.domain in $free_file_hosts + and not ( + // negating Google Forms links + .href_url.domain.domain == "docs.google.com" + and strings.istarts_with(.href_url.path, "/forms/") + ) + ) and regex.icontains(subject.subject, 'immediately', 'urgent') + and any(ml.nlu_classifier(body.current_thread.text).intents, .name != "benign") and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/headers_anonymousfox.yml b/detection-rules/headers_anonymousfox.yml index 3b1e379309b..8ce82cfd200 100644 --- a/detection-rules/headers_anonymousfox.yml +++ b/detection-rules/headers_anonymousfox.yml @@ -5,14 +5,16 @@ description: | reference: - "https://sucuri.net/guides/anonymousfox-hack-guide/" type: "rule" -severity: "medium" +severity: "high" source: | type.inbound - and any(headers.hops, - any(.fields, - regex.icontains(.name, "X-Authenticated-Sender|X-Sender") and - regex.icontains(.value, "(anonymous|smtp)fox-")) - or regex.icontains(sender.email.email, "(anonymous|smtp)fox-")) + and any(headers.hops, + any(.fields, + regex.icontains(.name, "X-Authenticated-Sender|X-Sender") + and regex.icontains(.value, "(anonymous|smtp)fox-") + ) + or regex.icontains(sender.email.email, "(anonymous|smtp)fox-") + ) attack_types: - "BEC/Fraud" - "Credential Phishing" diff --git a/detection-rules/headers_bec_masked_recipients_no_links_freemail_replyto.yml b/detection-rules/headers_bec_masked_recipients_no_links_freemail_replyto.yml index 782509a0586..f255d1269da 100644 --- a/detection-rules/headers_bec_masked_recipients_no_links_freemail_replyto.yml +++ b/detection-rules/headers_bec_masked_recipients_no_links_freemail_replyto.yml @@ -6,28 +6,24 @@ description: | type: "rule" severity: "medium" source: | - type.inbound - + type.inbound and any(recipients.to, .email.email == sender.email.email) and length(recipients.cc) == 0 and length(recipients.bcc) == 0 - - and length(body.links) == 0 - + and length(body.links) == 0 and any(headers.reply_to, - .email.domain.domain in $free_email_providers - and not .email.domain.domain == sender.email.domain.domain + .email.domain.domain in $free_email_providers + and not .email.domain.domain == sender.email.domain.domain ) - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/headers_freemail_replyto_returnpath_mismatch.yml b/detection-rules/headers_freemail_replyto_returnpath_mismatch.yml index c0360a0682b..d5c5e187a9d 100644 --- a/detection-rules/headers_freemail_replyto_returnpath_mismatch.yml +++ b/detection-rules/headers_freemail_replyto_returnpath_mismatch.yml @@ -5,7 +5,7 @@ severity: "medium" source: | type.inbound and any(ml.nlu_classifier(body.current_thread.text).intents, - .name in ("bec") and .confidence in ("medium", "high") + .name in ("bec") and .confidence == "high" ) and ( headers.return_path.domain.root_domain in $free_email_providers @@ -21,6 +21,24 @@ source: | ) ) and sender.email.domain.root_domain not in $free_email_providers + + // negate gmail autoforwards and null return paths + and ( + headers.return_path.email is null + or not any([headers.return_path.email], strings.ilike(headers.return_path.local_part, "*+caf_=*")) + ) + + // negate listservs + and not ( + any(headers.hops, any(.fields, .name == "List-Unsubscribe")) + and strings.contains(sender.display_name, "via") + ) + + // negate legit replies + and not ( + length(headers.references) > 0 + or any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) + ) attack_types: - "BEC/Fraud" tactics_and_techniques: diff --git a/detection-rules/headers_php_mailer_with_common_phishing_attachments.yml b/detection-rules/headers_php_mailer_with_common_phishing_attachments.yml index ea173528ddf..606eca2e998 100644 --- a/detection-rules/headers_php_mailer_with_common_phishing_attachments.yml +++ b/detection-rules/headers_php_mailer_with_common_phishing_attachments.yml @@ -8,7 +8,7 @@ severity: "medium" authors: - twitter: "vector_sec" source: | - type.inbound + type.inbound and strings.ilike(headers.mailer, '*phpmailer*') and any(attachments, .file_name in~ ('image.png', 'name.png', 'use.png')) attack_types: diff --git a/detection-rules/headers_replyto_new_domain_nlu_request.yml b/detection-rules/headers_replyto_new_domain_nlu_request.yml index c477612dfd6..ca6fcd540c8 100644 --- a/detection-rules/headers_replyto_new_domain_nlu_request.yml +++ b/detection-rules/headers_replyto_new_domain_nlu_request.yml @@ -6,45 +6,35 @@ type: "rule" severity: "medium" source: | type.inbound - and any(headers.reply_to, - // mismatched reply-to and sender domain - .email.domain.root_domain != sender.email.domain.root_domain + // mismatched reply-to and sender domain + .email.domain.root_domain != sender.email.domain.root_domain - // newly registered reply-to domain - and beta.whois(.email.domain).days_old <= 30 + // newly registered reply-to domain + and beta.whois(.email.domain).days_old <= 30 ) - + // request is being made - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities, .name == "request" - ) + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") // there's financial/urgency OR a tag of medium/high confidence and ( - ( - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities, .name == "financial") - or any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities, .name == "urgency") - ) - - or any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).tags, - .name is not null and .confidence in ("medium", "high") + any(ml.nlu_classifier(body.current_thread.text).entities, .name in ("financial", "urgency")) + or any(ml.nlu_classifier(body.current_thread.text).tags, + .name is not null and .confidence in ("medium", "high") ) ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/headers_russia_return_path.yml b/detection-rules/headers_russia_return_path.yml index 1e3c6025da9..a1aa279d27f 100644 --- a/detection-rules/headers_russia_return_path.yml +++ b/detection-rules/headers_russia_return_path.yml @@ -8,15 +8,15 @@ source: | and headers.return_path.domain.tld == "ru" and sender.email.email not in $recipient_emails and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + ) attack_types: - "BEC/Fraud" - "Credential Phishing" diff --git a/detection-rules/headers_sendgrid_onmicrosoft.yml b/detection-rules/headers_sendgrid_onmicrosoft.yml index b8daac8b4de..d4779d6296f 100644 --- a/detection-rules/headers_sendgrid_onmicrosoft.yml +++ b/detection-rules/headers_sendgrid_onmicrosoft.yml @@ -6,9 +6,9 @@ authors: - twitter: "ajpc500" severity: "medium" source: | - type.inbound and - headers.return_path.domain.domain == "sendgrid.net" and - sender.email.domain.root_domain == "onmicrosoft.com" + type.inbound + and headers.return_path.domain.domain == "sendgrid.net" + and sender.email.domain.root_domain == "onmicrosoft.com" attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/headers_spf_temp_error.yml b/detection-rules/headers_spf_temp_error.yml index d237245ed1e..ced1bf93748 100644 --- a/detection-rules/headers_spf_temp_error.yml +++ b/detection-rules/headers_spf_temp_error.yml @@ -13,7 +13,11 @@ type: "rule" severity: "medium" source: | type.inbound - and any(headers.hops, any(.fields, strings.ilike(.name, "Received-SPF") and strings.ilike(.value, "*spf=temperror*"))) + and any(headers.hops, + any(.fields, + strings.ilike(.name, "Received-SPF") and strings.ilike(.value, "*spf=temperror*") + ) + ) tactics_and_techniques: - "Spoofing" detection_methods: diff --git a/detection-rules/impersonation_adp.yml b/detection-rules/impersonation_adp.yml index f42224d5045..4411fc741f9 100644 --- a/detection-rules/impersonation_adp.yml +++ b/detection-rules/impersonation_adp.yml @@ -7,7 +7,7 @@ type: "rule" severity: "medium" source: | type.inbound - and sender.display_name in~ ('RS-Plan-Admin@adp.com','ADP','SecurityServices_NoReply@adp.com') + and sender.display_name in~ ('RS-Plan-Admin@adp.com', 'ADP', 'SecurityServices_NoReply@adp.com') and sender.email.domain.root_domain not in~ ('adp.com', 'adpsurveys.com') and sender.email.email not in $recipient_emails attack_types: diff --git a/detection-rules/impersonation_amazon.yml b/detection-rules/impersonation_amazon.yml index 40e073c96a3..0070ab55275 100644 --- a/detection-rules/impersonation_amazon.yml +++ b/detection-rules/impersonation_amazon.yml @@ -9,14 +9,21 @@ type: "rule" severity: "low" source: | type.inbound - and not any(headers.hops, any(.fields, .name == 'X-Amazon-Mail-Relay-Type' and .value == "notification")) + and not any(headers.hops, + any(.fields, .name == 'X-Amazon-Mail-Relay-Type' and .value == "notification") + ) and ( - regex.icontains(sender.display_name, '\b[aaa𝝰aa𝑎𝗮𝕒𝖆𝓪𝚊𝞪аɑα𝔞𝒂𝘢𝛂⍺𝒶𝙖𝜶𝛼𝐚𝖺]maz[o0]n\s?(pay|marketplace|\.com)') - or strings.ilevenshtein(sender.display_name, 'amazon.com') <= 1 - or strings.ilevenshtein(sender.display_name, 'amazon pay') <= 1 - or strings.ilevenshtein(sender.display_name, 'amazon marketplace') <= 1 - or strings.ilevenshtein(sender.display_name, 'amazon customer support') <= 1 - or (strings.ilevenshtein(sender.display_name, 'amazon') <= 1 and sender.email.domain.root_domain in $free_email_providers) + regex.icontains(sender.display_name, + '\b[aaa𝝰aa𝑎𝗮𝕒𝖆𝓪𝚊𝞪аɑα𝔞𝒂𝘢𝛂⍺𝒶𝙖𝜶𝛼𝐚𝖺]maz[o0]n\s?(pay|marketplace|\.com)|ᵃ⤻ᶻ' + ) + or strings.ilevenshtein(sender.display_name, 'amazon.com') <= 1 + or strings.ilevenshtein(sender.display_name, 'amazon pay') <= 1 + or strings.ilevenshtein(sender.display_name, 'amazon marketplace') <= 1 + or strings.ilevenshtein(sender.display_name, 'amazon customer support') <= 1 + or ( + strings.ilevenshtein(sender.display_name, 'amazon') <= 1 + and sender.email.domain.root_domain in $free_email_providers + ) ) and sender.email.domain.root_domain not in~ ( 'amazon.com', diff --git a/detection-rules/impersonation_amazon_suspicious_text.yml b/detection-rules/impersonation_amazon_suspicious_text.yml index 537fd7cd1f3..018882fa9dc 100644 --- a/detection-rules/impersonation_amazon_suspicious_text.yml +++ b/detection-rules/impersonation_amazon_suspicious_text.yml @@ -9,32 +9,40 @@ type: "rule" severity: "medium" source: | type.inbound - and strings.ilike(sender.display_name, "amazon*") - and any(attachments, .file_type in ("pdf", "jpg", "jpeg", "png") - and any(ml.logo_detect(.).brands, - .name == "Amazon" and .confidence in~ ("medium", "high") - ) - and ( - any(file.explode(.), - any(ml.nlu_classifier(.scan.ocr.raw).intents, - .name != "benign" and .confidence == "high" - ) - ) - or any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, - .name != "benign" and .confidence == "high" + and ( + strings.ilike(sender.display_name, "amazon*") + or any(attachments, strings.icontains(.file_name, "amazon")) + or any(attachments, + (.file_type in $file_types_images or .file_type == "pdf") + and any(file.explode(.), + strings.icontains(.scan.ocr.raw, "amazon") ) ) ) + and any(attachments, + (.file_type in $file_types_images or .file_type == "pdf") + and any(ml.logo_detect(.).brands, .name == "Amazon" and .confidence in~ ("medium", "high")) + and ( + any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name != "benign" and .confidence == "high" + ) + ) + or any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, + .name != "benign" and .confidence == "high" + ) + ) + ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) and sender.email.domain.root_domain not in~ ( 'amazon.com', diff --git a/detection-rules/impersonation_amex.yml b/detection-rules/impersonation_amex.yml index 8cad2868b4b..984e899216c 100644 --- a/detection-rules/impersonation_amex.yml +++ b/detection-rules/impersonation_amex.yml @@ -8,11 +8,22 @@ severity: "low" source: | type.inbound and ( - strings.ilike(sender.display_name, '*american express*') - or strings.ilevenshtein(sender.display_name, 'american express') <= 2 - or strings.ilike(sender.email.domain.domain, '*americanexpress*') + strings.ilike(sender.display_name, '*american express*') + or strings.ilevenshtein(sender.display_name, 'american express') <= 2 + or strings.ilike(sender.email.domain.domain, '*americanexpress*') + ) + and sender.email.domain.root_domain not in ( + 'aexp.com', + 'americanexpress.com', + 'americanexpress.co.uk', + 'aexpfeedback.com', + 'amexnetwork.com', + 'accountonline.com', + 'transunion.com', + 'amexgiftcard.com', + 'amexgbt.com', + 'citi.com' ) - and sender.email.domain.root_domain not in ('aexp.com','americanexpress.com', 'americanexpress.co.uk', 'aexpfeedback.com', 'amexnetwork.com', 'accountonline.com', 'transunion.com', 'amexgiftcard.com', 'amexgbt.com') and sender.email.domain.domain not in ('accountprotection.microsoft.com') and sender.email.email not in $recipient_emails attack_types: diff --git a/detection-rules/impersonation_apple.yml b/detection-rules/impersonation_apple.yml index c341f889b6f..cc5c7b6efe9 100644 --- a/detection-rules/impersonation_apple.yml +++ b/detection-rules/impersonation_apple.yml @@ -8,8 +8,8 @@ severity: "high" source: | type.inbound and ( - sender.display_name =~ 'apple developer' - or strings.ilevenshtein(sender.display_name, 'apple developer') <= 2 + sender.display_name =~ 'apple developer' + or strings.ilevenshtein(sender.display_name, 'apple developer') <= 2 ) and sender.email.domain.root_domain !~ 'apple.com' and sender.email.email not in $recipient_emails diff --git a/detection-rules/impersonation_bank_of_america.yml b/detection-rules/impersonation_bank_of_america.yml index 7487e05a17d..e901b0cb634 100644 --- a/detection-rules/impersonation_bank_of_america.yml +++ b/detection-rules/impersonation_bank_of_america.yml @@ -8,9 +8,9 @@ severity: "high" source: | type.inbound and ( - sender.display_name =~ 'bank of america' - or strings.ilevenshtein(sender.display_name, 'bank of america') <= 2 - or strings.ilike(sender.email.domain.domain, '*bankofamerica*') + sender.display_name =~ 'bank of america' + or strings.ilevenshtein(sender.display_name, 'bank of america') <= 2 + or strings.ilike(sender.email.domain.domain, '*bankofamerica*') ) and sender.email.domain.root_domain not in~ ('bankofamerica.com', 'transunion.com', 'bofa.com') and sender.email.email not in $recipient_emails diff --git a/detection-rules/impersonation_barracuda.yml b/detection-rules/impersonation_barracuda.yml index f8e419f29d0..ac9b348cb8c 100644 --- a/detection-rules/impersonation_barracuda.yml +++ b/detection-rules/impersonation_barracuda.yml @@ -6,21 +6,30 @@ severity: "medium" source: | type.inbound and ( - strings.ilike(sender.display_name, '*barracuda*') - or strings.ilevenshtein(sender.display_name, 'barracuda') <= 1 - or strings.ilike(sender.email.domain.domain, '*barracuda*') + strings.ilike(sender.display_name, '*barracuda*') + or strings.ilevenshtein(sender.display_name, 'barracuda') <= 1 + or strings.ilike(sender.email.domain.domain, '*barracuda*') ) - and sender.email.domain.root_domain not in ('barracuda.com', 'barracudamsp.com', 'barracudanetworks.com', 'netsuite.com') - // unsolicited + and sender.email.domain.root_domain not in ( + 'barracuda.com', + 'barracudamsp.com', + 'barracudanetworks.com', + 'netsuite.com', + + // hockey team + 'sharkssports.net', + 'sjbarracuda.com' + ) + // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_binance.yml b/detection-rules/impersonation_binance.yml index 33be6a6de61..fd5543ac4cb 100644 --- a/detection-rules/impersonation_binance.yml +++ b/detection-rules/impersonation_binance.yml @@ -6,10 +6,10 @@ severity: "medium" source: | type.inbound and ( - strings.ilike(sender.display_name, '*binance*') - or strings.ilevenshtein(sender.display_name, 'binance') <= 1 - or strings.ilike(sender.email.domain.domain, '*binance*') - or strings.ilike(subject.subject, '*binance*') + strings.ilike(sender.display_name, '*binance*') + or strings.ilevenshtein(sender.display_name, 'binance') <= 1 + or strings.ilike(sender.email.domain.domain, '*binance*') + or strings.ilike(subject.subject, '*binance*') ) and sender.email.domain.root_domain not in~ ('binance.com', 'trustwallet.com', 'binance.charity') and any(ml.nlu_classifier(body.html.display_text).entities, .text == "Binance") @@ -20,18 +20,18 @@ source: | or any(ml.nlu_classifier(body.html.display_text).intents, .name != "benign") ) and ( - // if this comes from a free email provider, - // flag if org has never sent an email to sender's email before - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - // if this comes from a custom domain, - // flag if org has never sent an email to sender's domain before - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + // if this comes from a free email provider, + // flag if org has never sent an email to sender's email before + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + // if this comes from a custom domain, + // flag if org has never sent an email to sender's domain before + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Cryptocurrency" diff --git a/detection-rules/impersonation_blockchain.yml b/detection-rules/impersonation_blockchain.yml index fd59c27b031..89db7b6df80 100644 --- a/detection-rules/impersonation_blockchain.yml +++ b/detection-rules/impersonation_blockchain.yml @@ -6,13 +6,20 @@ severity: "medium" source: | type.inbound and ( - regex.imatch(sender.display_name, '\bblockchain\b') - or strings.ilevenshtein(sender.display_name, 'blockchain') <= 1 - or strings.ilike(sender.email.domain.domain, '*blockchain.com*') - or any(body.links, strings.ilevenshtein(.href_url.domain.root_domain, 'blockchain') == 1) + regex.imatch(sender.display_name, '\bblockchain\b') + or strings.ilevenshtein(sender.display_name, 'blockchain') <= 1 + or strings.ilike(sender.email.domain.domain, '*blockchain.com*') + or any(body.links, strings.ilevenshtein(.href_url.domain.root_domain, 'blockchain') == 1) + ) + and any(distinct(headers.hops, .received_spf.verdict is not null), + strings.like(.received_spf.verdict, "*fail") + ) + and sender.email.domain.root_domain not in~ ( + 'blockchain.com', + 'wxblockchain.com', + 'ai-blockchain.com', + 'envisionblockchain.com' ) - and any(distinct(headers.hops, .received_spf.verdict is not null), strings.like(.received_spf.verdict, "*fail")) - and sender.email.domain.root_domain not in~ ('blockchain.com', 'wxblockchain.com', 'ai-blockchain.com', 'envisionblockchain.com') and sender.email.email not in $recipient_emails attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_chase.yml b/detection-rules/impersonation_chase.yml index 3c1732303ac..40990223d26 100644 --- a/detection-rules/impersonation_chase.yml +++ b/detection-rules/impersonation_chase.yml @@ -10,15 +10,29 @@ severity: "high" source: | type.inbound and ( - strings.ilike(sender.display_name, '*chase sapphire*','*chase card services*','*united mileageplus*', "echase*") - or strings.ilevenshtein(sender.display_name, 'chase sapphire') <= 2 - or strings.ilevenshtein(sender.display_name, 'chase card services') <= 2 - or strings.ilevenshtein(sender.display_name, 'united mileageplus') <= 2 - or strings.ilevenshtein(sender.display_name, 'echase') <= 2 + strings.ilike(sender.display_name, + '*chase sapphire*', + '*chase card services*', + '*united mileageplus*', + "echase*" + ) + or strings.ilevenshtein(sender.display_name, 'chase sapphire') <= 2 + or strings.ilevenshtein(sender.display_name, 'chase card services') <= 2 + or strings.ilevenshtein(sender.display_name, 'united mileageplus') <= 2 + or strings.ilevenshtein(sender.display_name, 'echase') <= 1 + ) + and sender.display_name not in~ ("chaser", "case") + and sender.email.domain.root_domain not in~ ('chase.com', 'united.com', 'transunion.com', 'shopping-chase.com') + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) - and sender.display_name not in ("Chaser") - and sender.email.domain.root_domain not in~ ('chase.com', 'united.com', 'transunion.com') - and sender.email.email not in $recipient_emails attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/impersonation_coinbase.yml b/detection-rules/impersonation_coinbase.yml index cd6b5a13235..3b15e463925 100644 --- a/detection-rules/impersonation_coinbase.yml +++ b/detection-rules/impersonation_coinbase.yml @@ -9,24 +9,24 @@ severity: "high" source: | type.inbound and ( - strings.ilike(sender.display_name, '*coinbase*') - or strings.ilevenshtein(sender.display_name, 'coinbase') <= 1 - or strings.ilike(sender.email.domain.domain, '*coinbase*') + strings.ilike(sender.display_name, '*coinbase*') + or strings.ilevenshtein(sender.display_name, 'coinbase') <= 1 + or strings.ilike(sender.email.domain.domain, '*coinbase*') ) and sender.email.domain.root_domain not in~ ('coinbase.com', 'q4inc.com') and ( - // if this comes from a free email provider, - // flag if org has never sent an email to sender's email before - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - // if this comes from a custom domain, - // flag if org has never sent an email to sender's domain before - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + // if this comes from a free email provider, + // flag if org has never sent an email to sender's email before + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + // if this comes from a custom domain, + // flag if org has never sent an email to sender's domain before + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Cryptocurrency" diff --git a/detection-rules/impersonation_dhl.yml b/detection-rules/impersonation_dhl.yml index d5cd44d8299..3fee425bae3 100644 --- a/detection-rules/impersonation_dhl.yml +++ b/detection-rules/impersonation_dhl.yml @@ -9,21 +9,31 @@ severity: "low" source: | type.inbound and ( - regex.icontains(sender.display_name, '\bDHL\b') - or strings.ilike(sender.email.domain.domain, '*DHL*') - or strings.ilike(subject.subject, '*DHL notification*') + regex.icontains(sender.display_name, '\bDHL\b') + or strings.ilike(sender.email.domain.domain, '*DHL*') + or strings.ilike(subject.subject, '*DHL notification*') + ) + and sender.email.domain.root_domain not in~ ( + 'dhl.com', + 'dhl-news.com', + 'bdhllp.com', + 'dhlparcel.co.uk', + 'dhlecs.com', + 'dhl.co.uk', + 'dpdhl.com', + 'dhl.de', + 'dhl.fr' ) - and sender.email.domain.root_domain not in~ ('dhl.com', 'dhl-news.com', 'bdhllp.com', 'dhlparcel.co.uk', 'dhlecs.com', 'dhl.co.uk', 'dpdhl.com', 'dhl.de', 'dhl.fr') // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_digital_ocean.yml b/detection-rules/impersonation_digital_ocean.yml index a3ca8088647..83e18797939 100644 --- a/detection-rules/impersonation_digital_ocean.yml +++ b/detection-rules/impersonation_digital_ocean.yml @@ -6,9 +6,9 @@ severity: "high" source: | type.inbound and ( - sender.display_name =~ 'digitalocean' - or strings.ilevenshtein(sender.display_name, 'digitalocean') <= 2 - or strings.ilike(sender.email.domain.domain, '*digitalocean*') + sender.display_name =~ 'digitalocean' + or strings.ilevenshtein(sender.display_name, 'digitalocean') <= 2 + or strings.ilike(sender.email.domain.domain, '*digitalocean*') ) and sender.email.domain.root_domain !~ 'digitalocean.com' and sender.email.email not in $recipient_emails diff --git a/detection-rules/impersonation_docusign.yml b/detection-rules/impersonation_docusign.yml index 2af461dce5a..07d58391c7a 100644 --- a/detection-rules/impersonation_docusign.yml +++ b/detection-rules/impersonation_docusign.yml @@ -8,59 +8,59 @@ severity: "high" source: | type.inbound and ( - // orgs can have docusign.company.com - strings.ilike(sender.email.email, '*docusign.net*', '*docusign.com*') + // orgs can have docusign.company.com + strings.ilike(sender.email.email, '*docusign.net*', '*docusign.com*') - // if the above is true, you'll see a "via Docusign" - or strings.ilike(sender.display_name, '*docusign*') + // if the above is true, you'll see a "via Docusign" + or strings.ilike(sender.display_name, '*docusign*') - // detects 1 character variations, - // such as DocuSlgn (with an "L" instead of an "I") - or strings.ilevenshtein(sender.display_name, "docusign") == 1 + // detects 1 character variations, + // such as DocuSlgn (with an "L" instead of an "I") + or strings.ilevenshtein(sender.display_name, "docusign") == 1 ) // identifies the main CTA in the email, eg "Review now" or "Review document" // this should always be a known docusign domain, // even with branded docusign subdomains and any(body.links, - // we've observed invisible characters in the display name - // such as U+034f(look carefully): "Revi͏ew Now" - ( - strings.ilevenshtein(.display_text, "Review Now") <= 3 - or (strings.icontains(.display_text, "Review") and not strings.icontains(.display_text, "Review Us")) - or strings.icontains(.display_text, "Now") - or strings.contains(.display_text, "document") - ) - and .href_url.domain.root_domain not in ("docusign.com","docusign.net") + // we've observed invisible characters in the display name + // such as U+034f(look carefully): "Revi͏ew Now" + ( + strings.ilevenshtein(.display_text, "Review Now") <= 3 + or ( + strings.icontains(.display_text, "Review") + and not strings.icontains(.display_text, "Review Us") + ) + or strings.icontains(.display_text, "Now") + or strings.contains(.display_text, "document") + ) + and .href_url.domain.root_domain not in ("docusign.com", "docusign.net") ) - and ( - sender.email.domain.root_domain not in ('docusign.net', 'docusign.com') - // check for DMARC fail for spoofs - or any(distinct(headers.hops, .authentication_results.dmarc is not null), - strings.ilike(.authentication_results.dmarc, "*fail") - ) - ) + sender.email.domain.root_domain not in ('docusign.net', 'docusign.com') + // check for DMARC fail for spoofs + or any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) // adding negation for messages originating from docusigns api // and the sender.display.name contains "via" and not ( - any(headers.hops, - any(.fields, .name == "X-Api-Host" and - strings.ends_with(.value, "docusign.net") - ) - ) - and strings.contains(sender.display_name, "via") + any(headers.hops, + any(.fields, .name == "X-Api-Host" and strings.ends_with(.value, "docusign.net")) ) + and strings.contains(sender.display_name, "via") + ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_domain_replyto_freemail_lookalike_financial_request.yml b/detection-rules/impersonation_domain_replyto_freemail_lookalike_financial_request.yml index 09a34f1c365..ff300c64bee 100644 --- a/detection-rules/impersonation_domain_replyto_freemail_lookalike_financial_request.yml +++ b/detection-rules/impersonation_domain_replyto_freemail_lookalike_financial_request.yml @@ -6,23 +6,22 @@ description: | type: "rule" severity: "medium" source: | - type.inbound - and any(headers.reply_to, .email.email != sender.email.email + type.inbound + and any(headers.reply_to, + .email.email != sender.email.email and .email.domain.domain in $free_email_providers and .email.email not in $sender_emails and strings.contains(.email.local_part, sender.email.domain.sld) - ) - and any([body.plain.raw, body.html.inner_text], - any(ml.nlu_classifier(.).intents, - .name == "bec" and .confidence in ("medium","high") - ) - or ( - any(ml.nlu_classifier(.).entities, .name == "financial") - and any(ml.nlu_classifier(.).entities, .name == "request") - and any(ml.nlu_classifier(.).entities, .name == "urgency") - and any(ml.nlu_classifier(.).entities, .name == "sender") - and any(ml.nlu_classifier(.).intents, .name != "benign") - ) + ) + and any([body.plain.raw, body.html.inner_text], + any(ml.nlu_classifier(.).intents, .name == "bec" and .confidence in ("medium", "high")) + or ( + any(ml.nlu_classifier(.).entities, .name == "financial") + and any(ml.nlu_classifier(.).entities, .name == "request") + and any(ml.nlu_classifier(.).entities, .name == "urgency") + and any(ml.nlu_classifier(.).entities, .name == "sender") + and any(ml.nlu_classifier(.).intents, .name != "benign") + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_dropbox.yml b/detection-rules/impersonation_dropbox.yml index 870e402b031..20971fd3cc7 100644 --- a/detection-rules/impersonation_dropbox.yml +++ b/detection-rules/impersonation_dropbox.yml @@ -6,15 +6,14 @@ severity: "medium" source: | type.inbound and ( - strings.ilike(sender.display_name, '*dropbox*') - or strings.ilevenshtein(sender.display_name, 'dropbox') <= 1 - or strings.ilike(sender.email.domain.domain, '*dropbox*') + strings.ilike(sender.display_name, '*dropbox*') + or strings.ilevenshtein(sender.display_name, 'dropbox') <= 1 + or strings.ilike(sender.email.domain.domain, '*dropbox*') ) and sender.email.domain.root_domain !~ 'dropbox.com' - and any(attachments, .file_type in~ ('png','jpg','jpeg','bmp') - and any(file.explode(.), - any(.scan.strings.strings, strings.ilike(., "*dropbox*")) - ) + and any(attachments, + .file_type in $file_types_images + and any(file.explode(.), strings.ilike(.scan.ocr.raw, "*dropbox*")) ) and sender.email.email not in $recipient_emails attack_types: diff --git a/detection-rules/impersonation_employee_payroll_fraud.yml b/detection-rules/impersonation_employee_payroll_fraud.yml index c8e01b2286f..253133f8f10 100644 --- a/detection-rules/impersonation_employee_payroll_fraud.yml +++ b/detection-rules/impersonation_employee_payroll_fraud.yml @@ -5,30 +5,34 @@ description: | type: "rule" severity: "medium" source: | - type.inbound + type.inbound and sender.display_name in $org_display_names - and length(attachments) == 0 + and length(attachments) == 0 and length(body.plain.raw) < 300 and ( - sender.email.domain.root_domain not in $org_domains - or - sender.email.domain.root_domain in $free_email_providers + sender.email.domain.root_domain not in $org_domains + or sender.email.domain.root_domain in $free_email_providers ) - and 1 of ( - regex.icontains(body.plain.raw, '(pay\s?(roll|check|date|day)|direct deposit|\bdd\b|gehalt|salario|salary)'), - regex.icontains(body.html.inner_text, '(pay\s?(roll|check|date|day)|direct deposit|\bdd\b|gehalt|salario|salary)'), - regex.icontains(subject.subject, '(pay\s?(roll|check|date|day)|direct deposit|\bdd\b|gehalt|salario|salary)') + regex.icontains(body.plain.raw, + '(pay\s?(roll|check|date|day)|direct deposit|\bdd\b|gehalt|salario|salary)' + ), + regex.icontains(body.html.inner_text, + '(pay\s?(roll|check|date|day)|direct deposit|\bdd\b|gehalt|salario|salary)' + ), + regex.icontains(subject.subject, + '(pay\s?(roll|check|date|day)|direct deposit|\bdd\b|gehalt|salario|salary)' + ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/impersonation_employee_subject.yml b/detection-rules/impersonation_employee_subject.yml index d46d07f0d5a..1897f23e05d 100644 --- a/detection-rules/impersonation_employee_subject.yml +++ b/detection-rules/impersonation_employee_subject.yml @@ -11,23 +11,20 @@ source: | // subject typically would contain. this is an attempt to // bypass impersonation detections and subject.subject in~ $org_display_names - and any([body.html.display_text, body.plain.raw], - any(ml.nlu_classifier(.).intents, - .name == "bec" and .confidence in ("medium", "high") - ) + any(ml.nlu_classifier(.).intents, .name == "bec" and .confidence in ("medium", "high")) ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/impersonation_employee_urgent_request.yml b/detection-rules/impersonation_employee_urgent_request.yml index 5c52c9b98f9..3f6978174c4 100644 --- a/detection-rules/impersonation_employee_urgent_request.yml +++ b/detection-rules/impersonation_employee_urgent_request.yml @@ -7,31 +7,33 @@ type: "rule" severity: "medium" source: | type.inbound - and sender.display_name in~ $org_display_names - - and any([body.plain.raw, body.html.inner_text], - any(ml.nlu_classifier(.).intents, - .name == "bec" and .confidence == "high" - ) + and ( + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "bec" and .confidence == "high") or ( - any(ml.nlu_classifier(.).entities, .name == "urgency") - and any(ml.nlu_classifier(.).entities, .name == "request") - and not any(ml.nlu_classifier(.).intents, .name == "benign" and .confidence == "high") + ( + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency") + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") + ) + and not any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "benign" and .confidence == "high" + ) + // there are intents returned + and any(ml.nlu_classifier(body.current_thread.text).intents, true) and not strings.istarts_with(subject.subject, "fwd:") ) ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/impersonation_exodus.yml b/detection-rules/impersonation_exodus.yml index 4704dc61445..6e00ea45b61 100644 --- a/detection-rules/impersonation_exodus.yml +++ b/detection-rules/impersonation_exodus.yml @@ -7,12 +7,18 @@ type: "rule" severity: "low" source: | type.inbound - and strings.ilike(sender.display_name, "*exodus*") + and ( + strings.ilike(sender.display_name, "*exodus*") + or ( + strings.ilike(sender.email.domain.root_domain, "*exodus*") + and beta.whois(sender.email.domain).days_old <= 30 + ) + ) and sender.email.domain.root_domain not in ("exodus.com", "exodus.io", "exodusescaperoom.com") and sender.email.email not in $recipient_emails and ( - any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, .name != "benign") - or any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).entities, .text == "wallet") + any(ml.nlu_classifier(body.current_thread.text).intents, .name != "benign") + or any(ml.nlu_classifier(body.current_thread.text).entities, .text == "wallet") ) tags: - "Cryptocurrency" diff --git a/detection-rules/impersonation_facebook.yml b/detection-rules/impersonation_facebook.yml index b27ebe9629d..883579e9fd1 100644 --- a/detection-rules/impersonation_facebook.yml +++ b/detection-rules/impersonation_facebook.yml @@ -8,12 +8,17 @@ severity: "low" source: | type.inbound and ( - strings.ilike(sender.display_name, '*facebook ads*', '*facebook business*') - or strings.ilevenshtein(sender.display_name, 'facebook ads') <= 2 - or strings.ilevenshtein(sender.display_name, 'facebook business') <= 2 - or strings.ilike(sender.email.domain.domain, '*facebook*') + strings.ilike(sender.display_name, '*facebook ads*', '*facebook business*') + or strings.ilevenshtein(sender.display_name, 'facebook ads') <= 2 + or strings.ilevenshtein(sender.display_name, 'facebook business') <= 2 + or strings.ilike(sender.email.domain.domain, '*facebook*') + ) + and sender.email.domain.root_domain not in~ ( + 'facebook.com', + 'facebookmail.com', + 'eventsatfacebook.com', + 'facebookenterprise.com' ) - and sender.email.domain.root_domain not in~ ('facebook.com','facebookmail.com', 'eventsatfacebook.com', 'facebookenterprise.com') and sender.email.email not in $recipient_emails attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_fake_msg_thread_mismatched_from_freemail_replyto.yml b/detection-rules/impersonation_fake_msg_thread_mismatched_from_freemail_replyto.yml index 1834add8b97..126d35c2cd8 100644 --- a/detection-rules/impersonation_fake_msg_thread_mismatched_from_freemail_replyto.yml +++ b/detection-rules/impersonation_fake_msg_thread_mismatched_from_freemail_replyto.yml @@ -11,20 +11,20 @@ source: | // First-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) // Reply-to is a freemail sender but From is not and any(headers.reply_to, - .email.domain.domain in $free_email_providers - and not .email.domain.domain == sender.email.domain.domain + .email.domain.domain in $free_email_providers + and not .email.domain.domain == sender.email.domain.domain ) // Exclude marketing emails @@ -32,17 +32,18 @@ source: | // Check for Message Thread Indicators and ( - strings.istarts_with(subject.subject, "RE:") - or any([body.plain.raw, body.html.display_text], - regex.icontains(.,"From:[ a-z0-9<>_@\\.]{0,80}Sent:[ a-z0-9<>_@\\.:]{0,40}To:[ a-z0-9<>_@\\.;]{0,300}(Cc:)?.{0,300}Subject:") - ) - + strings.istarts_with(subject.subject, "RE:") + or any([body.plain.raw, body.html.display_text], + regex.icontains(., + "From:[ a-z0-9<>_@\\.]{0,80}Sent:[ a-z0-9<>_@\\.:]{0,40}To:[ a-z0-9<>_@\\.;]{0,300}(Cc:)?.{0,300}Subject:" + ) + ) ) // Check for the Presence of References or In-Reply-To properties and ( - length(headers.references) == 0 - or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) + length(headers.references) == 0 + or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/impersonation_fake_shipping_notification.yml b/detection-rules/impersonation_fake_shipping_notification.yml index 7b003eb09ba..97db7637a49 100644 --- a/detection-rules/impersonation_fake_shipping_notification.yml +++ b/detection-rules/impersonation_fake_shipping_notification.yml @@ -9,7 +9,9 @@ source: | type.inbound and length(attachments) == 0 and ( - regex.icontains(coalesce(body.html.inner_text, body.html.display_text), '\bf[ _]?e[ _]?d[ _]?e[ _]?x\b') + regex.icontains(coalesce(body.html.inner_text, body.html.display_text), + '\bf[ _]?e[ _]?d[ _]?e[ _]?x\b' + ) and sender.email.domain.domain != "fedex.com" and headers.return_path.domain.domain != sender.email.domain.domain and any(body.links, strings.contains(.display_text, "track")) diff --git a/detection-rules/impersonation_fedex.yml b/detection-rules/impersonation_fedex.yml index a6b9412cfac..77073c7a3d4 100644 --- a/detection-rules/impersonation_fedex.yml +++ b/detection-rules/impersonation_fedex.yml @@ -8,13 +8,13 @@ severity: "low" source: | type.inbound and ( - sender.display_name in~ ('fedex', 'fedex shipment', 'fedex tracking updates') - or strings.ilevenshtein(sender.display_name, 'fedex') <= 1 - or strings.ilike(sender.email.domain.domain, '*fedex*') + sender.display_name in~ ('fedex', 'fedex shipment', 'fedex tracking updates') + or strings.ilevenshtein(sender.display_name, 'fedex') <= 1 + or strings.ilike(sender.email.domain.domain, '*fedex*') ) // sedex.com is not affiliated with FedEx, but is an apparent FP - and sender.email.domain.root_domain not in~ ('fedex.com', 'sedex.com') - and sender.email.email not in $recipient_emails + and sender.email.domain.root_domain not in~ ('fedex.com', 'sedex.com', 'myworkday.com') + and sender.email.email not in $sender_emails attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/impersonation_finra.yml b/detection-rules/impersonation_finra.yml index d31b31cae3e..8922f317c38 100644 --- a/detection-rules/impersonation_finra.yml +++ b/detection-rules/impersonation_finra.yml @@ -8,22 +8,21 @@ severity: "medium" source: | type.inbound and ( - strings.ilevenshtein(sender.display_name, 'finra') <= 1 - or strings.ilevenshtein(sender.email.domain.sld, 'finra') <= 1 + strings.ilevenshtein(sender.display_name, 'finra') <= 1 + or strings.ilevenshtein(sender.email.domain.sld, 'finra') <= 1 ) - and sender.email.domain.root_domain not in~ ('finra.org', 'finrax.com') // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_github.yml b/detection-rules/impersonation_github.yml index 138e6d21d85..7f60c752bac 100644 --- a/detection-rules/impersonation_github.yml +++ b/detection-rules/impersonation_github.yml @@ -9,21 +9,29 @@ source: | type.inbound and not strings.ilike(sender.display_name, '*course*', '*bootcamp*', '*training*') and ( - strings.ilike(sender.display_name, '*github*') - or strings.ilike(sender.email.email, '*github*') - or strings.ilevenshtein(sender.email.domain.sld, 'github') <= 1 + strings.ilike(sender.display_name, '*github*') + or strings.ilike(sender.email.email, '*github*') + or strings.ilevenshtein(sender.email.domain.sld, 'github') <= 1 + ) + and sender.email.domain.root_domain not in ( + 'github.com', + 'gitlab.com', + 'itthub.net', + 'githubsupport.com', + 'gtmhub.com', + 'githubstatus.com', + 'githubnext.com', + 'lithub.com' ) - and sender.email.domain.root_domain not in ('github.com', 'gitlab.com', 'itthub.net', 'githubsupport.com', 'gtmhub.com', - 'githubstatus.com', 'githubnext.com') and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_google_via_msft_forms.yml b/detection-rules/impersonation_google_via_msft_forms.yml index c8890d2b6b5..87ea75bdffe 100644 --- a/detection-rules/impersonation_google_via_msft_forms.yml +++ b/detection-rules/impersonation_google_via_msft_forms.yml @@ -11,8 +11,13 @@ source: | // MsgID does not contain Google|Gmail|GoogleMail and not regex.icontains(headers.message_id, '(mail|mx)?\.?(google(mail)?|gmail.com)') and ( - any(body.links, .href_url.domain.root_domain not in $tranco_1m) - or strings.ilike(body.html.display_text, "*suspicious activities*", "*failure to secure*", "*loose your*", "*suspended*") + any(body.links, .href_url.domain.root_domain not in $tranco_1m) + or strings.ilike(body.html.display_text, + "*suspicious activities*", + "*failure to secure*", + "*loose your*", + "*suspended*" + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_gusto.yml b/detection-rules/impersonation_gusto.yml index 3c7312fe349..b335798ce4a 100644 --- a/detection-rules/impersonation_gusto.yml +++ b/detection-rules/impersonation_gusto.yml @@ -6,13 +6,13 @@ severity: "medium" source: | type.inbound and ( - strings.ilike(sender.display_name, '*gusto*') - or strings.ilevenshtein(sender.display_name, 'gusto') <= 1 - or strings.ilike(sender.email.domain.domain, '*gusto*') + strings.ilike(sender.display_name, '*gusto*') + or strings.ilevenshtein(sender.display_name, 'gusto') <= 1 + or strings.ilike(sender.email.domain.domain, '*gusto*') + ) + and any(ml.logo_detect(beta.message_screenshot()).brands, + .name == "Gusto" and .confidence in ("medium", "high") ) - and any(ml.logo_detect(beta.message_screenshot()).brands, - .name == "Gusto" - and .confidence in ("medium", "high")) and sender.email.domain.root_domain !~ 'gusto.com' and sender.email.email not in $recipient_emails attack_types: diff --git a/detection-rules/impersonation_human_resources.yml b/detection-rules/impersonation_human_resources.yml index b3496282108..96c9e0d6bdc 100644 --- a/detection-rules/impersonation_human_resources.yml +++ b/detection-rules/impersonation_human_resources.yml @@ -5,32 +5,27 @@ severity: "medium" source: | type.inbound and sender.email.domain.domain not in $org_domains - and regex.icontains(sender.display_name, '(\bh\W?r\W?\b|human resources|hr depart(ment)?|employee relations)') - + and regex.icontains(sender.display_name, + '(\bh\W?r\W?\b|human resources|hr depart(ment)?|employee relations)' + ) and (length(body.links) > 0 or length(attachments) > 0) - + // Request and Urgency - and any(ml.nlu_classifier(body.html.inner_text).entities, .name == "request") - and any(ml.nlu_classifier(body.html.inner_text).entities, .name == "urgency") + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency") and ( - ( - length(ml.nlu_classifier(body.html.inner_text).intents) > 0 - and any(ml.nlu_classifier(body.html.inner_text).intents, .name != "benign") - ) - or length(ml.nlu_classifier(body.html.inner_text).intents) == 0 + any(ml.nlu_classifier(body.current_thread.text).intents, .name != "benign") + and not length(ml.nlu_classifier(body.current_thread.text).intents) == 0 ) - - and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or - ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/impersonation_ledger.yml b/detection-rules/impersonation_ledger.yml index 0f5b09331be..3410f79c1f9 100644 --- a/detection-rules/impersonation_ledger.yml +++ b/detection-rules/impersonation_ledger.yml @@ -8,34 +8,46 @@ severity: "low" source: | type.inbound // Fortune has a newsletter called "The Ledger" - and sender.email.domain.root_domain not in ('fortune.com', 'velocityledger.com', 'lever.co', 'queensledger.com', 'libertyledger.com', 'uledger.io') + and sender.email.domain.root_domain not in ( + 'fortune.com', + 'velocityledger.com', + 'lever.co', + 'queensledger.com', + 'libertyledger.com', + 'uledger.io' + ) and ( - ( - sender.email.domain.root_domain == 'ledger.com' - and headers.return_path.domain.root_domain not in ('ledger.com', 'amazonses.com', 'ledger.fr', 'hubspotemail.net') + ( + sender.email.domain.root_domain == 'ledger.com' + and headers.return_path.domain.root_domain not in ( + 'ledger.com', + 'amazonses.com', + 'ledger.fr', + 'hubspotemail.net' + ) + ) + or ( + sender.email.domain.root_domain != 'ledger.com' + and ( + strings.ilike(sender.email.email, '*-ledger.com*') + or sender.display_name =~ "ledger" + or strings.ilevenshtein(sender.email.domain.sld, "ledger") <= 1 ) - or ( - sender.email.domain.root_domain != 'ledger.com' - and ( - strings.ilike(sender.email.email, '*-ledger.com*') - or sender.display_name =~ "ledger" - or strings.ilevenshtein(sender.email.domain.sld, "ledger") <= 1 - ) - and ( - // if this comes from a free email provider, - // flag if org has never sent an email to sender's email before - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - // if this comes from a custom domain, - // flag if org has never sent an email to sender's domain before - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) - ) + and ( + // if this comes from a free email provider, + // flag if org has never sent an email to sender's email before + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + // if this comes from a custom domain, + // flag if org has never sent an email to sender's domain before + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) + ) ) tags: - "Cryptocurrency" diff --git a/detection-rules/impersonation_linkedin.yml b/detection-rules/impersonation_linkedin.yml index 8c0e3ab07d7..0de91abd542 100644 --- a/detection-rules/impersonation_linkedin.yml +++ b/detection-rules/impersonation_linkedin.yml @@ -8,12 +8,13 @@ severity: "medium" source: | type.inbound and ( - sender.display_name =~ 'linkedin' - or strings.ilevenshtein(sender.display_name, 'linkedin') <= 2 - or strings.ilevenshtein(sender.email.domain.root_domain, 'linkedin.com') <= 2 + sender.display_name =~ 'linkedin' + or strings.ilevenshtein(sender.display_name, 'linkedin') <= 2 + or strings.ilevenshtein(sender.email.domain.root_domain, 'linkedin.com') <= 2 ) and sender.email.domain.root_domain !~ 'linkedin.com' and sender.email.email not in $recipient_emails + and not strings.iends_with(headers.message_id, "linkedin.com>") attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/impersonation_microsoft.yml b/detection-rules/impersonation_microsoft.yml index c36840119f0..e903b05d922 100644 --- a/detection-rules/impersonation_microsoft.yml +++ b/detection-rules/impersonation_microsoft.yml @@ -13,11 +13,10 @@ source: | type.inbound and ( ( - strings.ilike(subject.subject, '*Microsoft 365*') + strings.ilike(subject.subject, '*Microsoft 365*') and strings.ilike(subject.subject, '*is expired*') ) - or - ( + or ( // should catch any instance of the word "expired" strings.ilike(body.html.display_text, "*expir*") and strings.ilike(body.html.display_text, "*password*") @@ -27,23 +26,28 @@ source: | or strings.ilike(sender.display_name, '*new activity in Teams*') or subject.subject =~ 'Offline Message in Teams' or strings.ilike(subject.subject, '*Teams Sent A Message') - or sender.display_name in~ ('Microsoft Partner Network','Microsoft', - 'Microsoft Feedback', 'Microsoft account team', - 'Microsoft Support', 'Microsoft 365 Message center', - 'Microsoft Azure') - ) + or sender.display_name in~ ( + 'Microsoft Partner Network', + 'Microsoft', + 'Microsoft Feedback', + 'Microsoft account team', + 'Microsoft Support', + 'Microsoft 365 Message center', + 'Microsoft Azure' + ) + ) and sender.email.domain.root_domain not in~ ('microsoft.com', 'microsoftsupport.com', 'office.com') // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_microsoft_fake_sign_in_alert.yml b/detection-rules/impersonation_microsoft_fake_sign_in_alert.yml index 6b655705cea..0997e7a2275 100644 --- a/detection-rules/impersonation_microsoft_fake_sign_in_alert.yml +++ b/detection-rules/impersonation_microsoft_fake_sign_in_alert.yml @@ -13,15 +13,15 @@ source: | or strings.contains(sender.display_name, "Microsoft") or strings.contains(body.current_thread.text, "Microsoft") or ( - + // or Microsoft Brand logo any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') + .file_type in $file_types_images and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft")) ) ) ) - + // Body contains Indicators of fake sign in notification and ( regex.contains(body.current_thread.text, @@ -29,23 +29,19 @@ source: | ) or regex.contains(body.current_thread.text, "Unusual.{0,10}activity") ) - - and ( // If the sender is freemail sender.email.domain.domain in $free_email_providers or ( - + // sender is not freemail, but the return path email or reply to email is sender.email.domain.domain not in $free_email_providers and ( headers.return_path.domain.root_domain in $free_email_providers or ( length(headers.reply_to) > 0 - and ( - all(headers.reply_to, .email.domain.root_domain in $free_email_providers) - ) + and (all(headers.reply_to, .email.domain.root_domain in $free_email_providers)) ) or ( @@ -61,7 +57,7 @@ source: | or beta.whois(sender.email.domain).days_old <= 90 or ( - // or Compauth verdict is not pass/softpass + // or Compauth verdict is not pass/softpass any(headers.hops, .authentication_results.compauth.verdict is not null and .authentication_results.compauth.verdict not in ("pass", "softpass") diff --git a/detection-rules/impersonation_microsoft_quarantine.yml b/detection-rules/impersonation_microsoft_quarantine.yml index 2b7b1927e12..be7d520db2e 100644 --- a/detection-rules/impersonation_microsoft_quarantine.yml +++ b/detection-rules/impersonation_microsoft_quarantine.yml @@ -5,32 +5,34 @@ type: "rule" severity: "high" source: | type.inbound - and length(filter(attachments, .file_type not in~ ('png', 'jpeg', 'jpg', 'bmp', 'gif'))) == 0 + and length(filter(attachments, .file_type not in $file_types_images)) == 0 and any(attachments, - any(file.explode(.), - any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence != "low") - and any(ml.nlu_classifier(.scan.ocr.raw).entities, .name == "urgency") - ) - and any(file.explode(.), - 3 of ( - any(.scan.strings.strings, strings.icontains(., "review")), - any(.scan.strings.strings, strings.icontains(., "release")), - any(.scan.strings.strings, strings.icontains(., "quarantine")), - any(.scan.strings.strings, strings.icontains(., "messages")), - any(ml.logo_detect(..).brands, strings.starts_with(.name, "Microsoft")) + any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence != "low" + ) + and any(ml.nlu_classifier(.scan.ocr.raw).entities, .name == "urgency") + ) + and any(file.explode(.), + 3 of ( + strings.icontains(.scan.ocr.raw, "review"), + strings.icontains(.scan.ocr.raw, "release"), + strings.icontains(.scan.ocr.raw, "quarantine"), + strings.icontains(.scan.ocr.raw, "messages"), + any(ml.logo_detect(..).brands, strings.starts_with(.name, "Microsoft")) + ) ) - ) ) and sender.email.domain.root_domain not in ( - "bing.com", - "microsoft.com", - "microsoftonline.com", - "microsoftsupport.com", - "microsoft365.com", - "office.com", - "onedrive.com", - "sharepointonline.com", - "yammer.com", + "bing.com", + "microsoft.com", + "microsoftonline.com", + "microsoftsupport.com", + "microsoft365.com", + "office.com", + "onedrive.com", + "sharepointonline.com", + "yammer.com", ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_microsoft_teams.yml b/detection-rules/impersonation_microsoft_teams.yml index 4b56e2189cc..33b8af0fe80 100644 --- a/detection-rules/impersonation_microsoft_teams.yml +++ b/detection-rules/impersonation_microsoft_teams.yml @@ -6,7 +6,7 @@ severity: "high" source: | type.inbound and any(attachments, - .file_type in ("pdf", "jpg", "jpeg", "png") + (.file_type in $file_types_images or .file_type == "pdf") and any(file.explode(.), regex.icontains(.scan.ocr.raw, "trying to reach you.*microsoft teams") ) diff --git a/detection-rules/impersonation_netflix.yml b/detection-rules/impersonation_netflix.yml index deb0c71ce17..34aac49144d 100644 --- a/detection-rules/impersonation_netflix.yml +++ b/detection-rules/impersonation_netflix.yml @@ -10,11 +10,11 @@ authors: source: | type.inbound and ( - strings.ilike(sender.display_name, '*netflix*') - or strings.ilevenshtein(sender.display_name, 'netflix') <= 1 - or strings.ilike(sender.email.domain.domain, '*netflix*') + strings.ilike(sender.display_name, '*netflix*') + or strings.ilevenshtein(sender.display_name, 'netflix') <= 1 + or strings.ilike(sender.email.domain.domain, '*netflix*') ) - and sender.email.domain.root_domain !~ 'netflix.com' + and sender.email.domain.root_domain not in ('netflix.com', 'dvd.com', 'netflixfamily.com') and sender.email.email not in $recipient_emails attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_norton_lifelock.yml b/detection-rules/impersonation_norton_lifelock.yml index 2cb0864b1be..3a7c638813c 100644 --- a/detection-rules/impersonation_norton_lifelock.yml +++ b/detection-rules/impersonation_norton_lifelock.yml @@ -12,37 +12,39 @@ source: | type.inbound and sender.email.domain.domain != "norton.com" and any(attachments, - .file_extension in~ ('pdf', 'jpg', 'jpeg', 'png') - and ( - strings.ilike(.file_name, "*norton*") - or any(file.explode(.), - any(.scan.strings.strings, regex.icontains(., ".*norton.?60.*", ".*lifelock.*", ".*norton.?security.*")) + (.file_type in $file_types_images or .file_type == "pdf") + and ( + strings.ilike(.file_name, "*norton*") + or any(file.explode(.), + regex.icontains(.scan.ocr.raw, + ".*norton.?60.*", + ".*lifelock.*", + ".*norton.?security.*" + ) + ) ) - ) ) and ( - ( - // if freemail, flag if it's a first-time sender - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or - ( - // if custom domain, we want to avoid flagging - // on the real Norton invoices - // so we flag if it's not a first-time sender - // and if it's not in the tranco 1M w/ a reply-to mismatch - // for example we've observed: - // Sender: Norton - // Reply-to: foo@outlook.com - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - and ( - sender.email.domain.root_domain not in $tranco_1m - or any(headers.reply_to, .email.domain.domain != sender.email.domain.domain) - ) - + ( + // if freemail, flag if it's a first-time sender + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + // if custom domain, we want to avoid flagging + // on the real Norton invoices + // so we flag if it's not a first-time sender + // and if it's not in the tranco 1M w/ a reply-to mismatch + // for example we've observed: + // Sender: Norton + // Reply-to: foo@outlook.com + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + and ( + sender.email.domain.root_domain not in $tranco_1m + or any(headers.reply_to, .email.domain.domain != sender.email.domain.domain) ) + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_paypal.yml b/detection-rules/impersonation_paypal.yml index d15b6c23e8a..f8c180384a7 100644 --- a/detection-rules/impersonation_paypal.yml +++ b/detection-rules/impersonation_paypal.yml @@ -8,60 +8,61 @@ severity: "medium" source: | type.inbound and ( - sender.display_name =~ "paypal" - or strings.ilevenshtein(sender.display_name, 'paypal') <= 1 - or strings.ilike(sender.email.domain.domain, '*paypal*') - - or any(attachments, .file_type in ("pdf", "jpg", "jpeg", "png") - and any(ml.logo_detect(.).brands, .name == "PayPal") - and any(file.explode(.), - any(.scan.strings.strings, strings.ilike(., "*PayPal*")) - and any(.scan.strings.strings, - strings.ilike(., - "*invoice*", - "*transaction*", - "*bitcoin*", - "*dear customer*", - ) - ) - ) - ) + sender.display_name =~ "paypal" + or strings.ilevenshtein(sender.display_name, 'paypal') <= 1 + or strings.ilike(sender.email.domain.domain, '*paypal*') + or any(attachments, + (.file_type in $file_types_images or .file_type == "pdf") + and any(ml.logo_detect(.).brands, .name == "PayPal") + and any(file.explode(.), + strings.ilike(.scan.ocr.raw, "*PayPal*") + and strings.ilike(.scan.ocr.raw, + "*invoice*", + "*transaction*", + "*bitcoin*", + "*dear customer*", + ) + ) + ) ) - - and sender.email.domain.root_domain not in~ ( - 'paypal.com', - 'paypal.ch', - 'paypal.nl', - 'paypal.co.uk', - 'google.com', - 'q4inc.com', - 'paypal.com.au', - 'paypal.se', - 'paypal.be', - 'paypal.de', - 'paypal.dk', - 'paypal.pl', - 'paypal.es', - 'paypal.ca', - 'paypal.fr', - 'paypal.it', - 'synchronyfinancial.com', - 'synchronybank.com', - 'xoom.com', - 'paypal-experience.com', - 'paypalcorp.com' + and sender.email.domain.root_domain not in ( + 'paypal.com', + 'paypal.ch', + 'paypal.nl', + 'paypal.co.uk', + 'google.com', + 'q4inc.com', + 'paypal.com.au', + 'paypal.se', + 'paypal.be', + 'paypal.de', + 'paypal.dk', + 'paypal.pl', + 'paypal.es', + 'paypal.ca', + 'paypal.fr', + 'paypal.it', + 'synchronyfinancial.com', + 'synchronybank.com', + 'xoom.com', + 'paypal-experience.com', + 'paypalcorp.com', + 'paypal-customerfeedback.com', + 'paypal-creditsurvey.com', + 'paypal-prepaid.com', + 'xoom.com' ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_recipient_domain.yml b/detection-rules/impersonation_recipient_domain.yml index eedf925ca66..d02e2a84f81 100644 --- a/detection-rules/impersonation_recipient_domain.yml +++ b/detection-rules/impersonation_recipient_domain.yml @@ -11,29 +11,37 @@ source: | // only 1 To: recipient and length(recipients.to) + length(recipients.bcc) + length(recipients.cc) == 1 - and any(recipients.to, - // custom domains only - sender.email.domain.domain not in $free_email_providers - - // recipient's domain is in the sender's display name - and strings.icontains(sender.display_name, .email.domain.root_domain)) + // custom domains only + sender.email.domain.domain not in $free_email_providers + // recipient's domain is in the sender's display name + and strings.icontains(sender.display_name, .email.domain.root_domain) + ) + and not ( - strings.contains(sender.display_name, "on behalf of") - and sender.email.domain.root_domain == "microsoftonline.com" + ( + strings.contains(sender.display_name, "on behalf of") + and sender.email.domain.root_domain == "microsoftonline.com" + ) + or ( + strings.contains(sender.display_name, "via TransferXL") + and sender.email.domain.root_domain == "transferxl.com" + ) ) + + and all(recipients.to, .email.email != sender.email.email) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml b/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml index 087cf4725c7..193fc25d260 100644 --- a/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml +++ b/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml @@ -6,12 +6,24 @@ description: | the sender's domain is not a known org domain, and it's a first time sender. source: | type.inbound + // check that there's at least 1 sus attachment, link, or body text and ( - any(recipients.to, - (strings.contains(sender.email.local_part, .email.domain.sld) + length(attachments) > 0 + // this must be run in user environments to not flag, + // not the Analyzer + or any(body.links, .href_url.domain.domain not in $org_domains) + or any(ml.nlu_classifier(body.current_thread.text).intents, + .name != "benign" and .confidence == "high" + ) + ) + and ( + any(recipients.to, + ( + strings.contains(sender.email.local_part, .email.domain.sld) // checking to ensure no FPs, like "me" in "me.com" - and length(.email.domain.sld) > 3) - ) + and length(.email.domain.sld) > 3 + ) + ) ) and sender.email.domain.root_domain not in $org_domains and ( diff --git a/detection-rules/impersonation_ripple.yml b/detection-rules/impersonation_ripple.yml index 69176a1177c..da3450cfb57 100644 --- a/detection-rules/impersonation_ripple.yml +++ b/detection-rules/impersonation_ripple.yml @@ -11,14 +11,14 @@ source: | and regex.imatch(sender.display_name, '\bripple\b') and sender.email.domain.root_domain not in ("ripple.com", "ripplejobs.co.uk") and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Cryptocurrency" diff --git a/detection-rules/impersonation_sharepoint_body_credential_theft.yml b/detection-rules/impersonation_sharepoint_body_credential_theft.yml index d3252dd7cd1..f4bdaeaabac 100644 --- a/detection-rules/impersonation_sharepoint_body_credential_theft.yml +++ b/detection-rules/impersonation_sharepoint_body_credential_theft.yml @@ -1,16 +1,28 @@ name: "Brand impersonation: Sharepoint" description: | - Body contains a Sharepoint logo, a link, and credential theft language. + Body, attached images or pdf contains a Sharepoint logo. The message contains a link and credential theft language. type: "rule" severity: "high" source: | type.inbound and length(body.links) > 0 - and any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(ml.logo_detect(.).brands, .name == "Microsoft SharePoint") + and ( + any(attachments, + (.file_type in $file_types_images or .file_type == "pdf") + and any(ml.logo_detect(.).brands, .name == "Microsoft SharePoint") + ) + or any(ml.logo_detect(beta.message_screenshot()).brands, .name == "Microsoft SharePoint") + ) + and ( + any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "cred_theft" and .confidence == "high" + ) + or any(file.explode(beta.message_screenshot()), + any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence == "high" + ) + ) ) - and any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, .name == "cred_theft") attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/impersonation_sharepoint_image_credential_theft.yml b/detection-rules/impersonation_sharepoint_image_credential_theft.yml deleted file mode 100644 index cb947d11466..00000000000 --- a/detection-rules/impersonation_sharepoint_image_credential_theft.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: "Brand impersonation: Sharepoint (image as content)" -description: | - Impersonation of Sharepoint where the attached image contains the contents of the credential phishing attack. -type: "rule" -severity: "high" -source: | - type.inbound - and length(body.links) > 0 - and any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(ml.logo_detect(.).brands, .name == "Microsoft SharePoint") - - and any(file.explode(.), - any(ml.nlu_classifier(.scan.ocr.raw).intents, - .name == "cred_theft" and - .confidence == "high" - ) - ) - ) -attack_types: - - "Credential Phishing" -tactics_and_techniques: - - "Impersonation: Brand" - - "Image as content" - - "Social engineering" -detection_methods: - - "Computer Vision" - - "File analysis" - - "Header analysis" - - "Natural Language Understanding" - - "Optical Character Recognition" - - "Sender analysis" -id: "0ac51b9a-7a2a-5be2-9e04-f71b9bfd61ac" diff --git a/detection-rules/impersonation_spotify.yml b/detection-rules/impersonation_spotify.yml index 4e982b24716..cfddbc55737 100644 --- a/detection-rules/impersonation_spotify.yml +++ b/detection-rules/impersonation_spotify.yml @@ -8,22 +8,28 @@ severity: "low" source: | type.inbound and ( - strings.ilike(sender.display_name, '*spotify*') - or strings.ilevenshtein(sender.display_name, 'spotify') <= 1 - or strings.ilike(sender.email.domain.domain, '*spotify*') + strings.ilike(sender.display_name, '*spotify*') + or strings.ilevenshtein(sender.display_name, 'spotify') <= 1 + or strings.ilike(sender.email.domain.domain, '*spotify*') + ) + and sender.email.domain.root_domain not in~ ( + 'spotify.com', + 'byspotify.com', + 'echosign.com', + 'fromspotify.com', + 'anchor.fm' ) - and sender.email.domain.root_domain not in~ ('spotify.com', 'byspotify.com', 'echosign.com', 'fromspotify.com', 'anchor.fm') and sender.email.domain.domain not in~ ('privaterelay.appleid.com') // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_stellar.yml b/detection-rules/impersonation_stellar.yml index 898f25f88ee..0a6c3a65b1e 100644 --- a/detection-rules/impersonation_stellar.yml +++ b/detection-rules/impersonation_stellar.yml @@ -11,14 +11,14 @@ source: | and regex.imatch(sender.display_name, '\bstellar\b') and sender.email.domain.root_domain != "stellar.org" and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Cryptocurrency" diff --git a/detection-rules/impersonation_sublime_security.yml b/detection-rules/impersonation_sublime_security.yml index b1dd99c3ad9..092022258c8 100644 --- a/detection-rules/impersonation_sublime_security.yml +++ b/detection-rules/impersonation_sublime_security.yml @@ -8,25 +8,20 @@ severity: "high" source: | type.inbound and ( - sender.display_name in~ ( - 'Sublime Security', - 'Josh Kamdjou', - 'Joshua Kamdjou', - 'Ian Thiel' - ) + sender.display_name in~ ('Sublime Security', 'Josh Kamdjou', 'Joshua Kamdjou', 'Ian Thiel') or strings.ilevenshtein(sender.email.domain.domain, 'sublimesecurity.com') <= 2 ) and sender.email.domain.domain != 'sublimesecurity.com' // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_turbotax.yml b/detection-rules/impersonation_turbotax.yml index f0ed686bf7f..ac382473349 100644 --- a/detection-rules/impersonation_turbotax.yml +++ b/detection-rules/impersonation_turbotax.yml @@ -8,9 +8,9 @@ severity: "low" source: | type.inbound and ( - strings.ilike(sender.display_name, '*turbotax*') - or strings.ilevenshtein(sender.display_name, 'turbotax') <= 1 - or strings.ilike(sender.email.domain.domain, '*turbotax*') + strings.ilike(sender.display_name, '*turbotax*') + or strings.ilevenshtein(sender.display_name, 'turbotax') <= 1 + or strings.ilike(sender.email.domain.domain, '*turbotax*') ) and sender.email.domain.root_domain not in~ ('intuit.com', 'turbotax.com', 'intuit.ca') and sender.email.email not in $recipient_emails diff --git a/detection-rules/impersonation_twitter.yml b/detection-rules/impersonation_twitter.yml index dc64485fd8c..82ec602f085 100644 --- a/detection-rules/impersonation_twitter.yml +++ b/detection-rules/impersonation_twitter.yml @@ -8,11 +8,11 @@ severity: "medium" source: | type.inbound and ( - sender.display_name =~ "twitter" - or strings.ilevenshtein(sender.display_name, 'twitter') <= 1 - or strings.ilike(sender.email.domain.domain, '*twitter*') + sender.display_name =~ "twitter" + or strings.ilevenshtein(sender.display_name, 'twitter') <= 1 + or strings.ilike(sender.email.domain.domain, '*twitter*') ) - and sender.email.domain.domain not in~ ('twitter.com', 'privaterelay.appleid.com', 'stripe.com') + and sender.email.domain.domain not in~ ('twitter.com', 'privaterelay.appleid.com', 'stripe.com', 'x.com') and sender.email.email not in $recipient_emails attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_ukr_net.yml b/detection-rules/impersonation_ukr_net.yml index 7a399e522f3..802cf6d666e 100644 --- a/detection-rules/impersonation_ukr_net.yml +++ b/detection-rules/impersonation_ukr_net.yml @@ -15,38 +15,38 @@ severity: "medium" source: | type.inbound and ( - ( - // technique - strings.ilike(sender.display_name, "ukr*net") - and sender.email.domain.root_domain != "ukr.net" - ) - or ( - // IOCs - subject.subject == "Увага" - and ( - sender.email.email in ( - "muthuprakash.b@tvsrubber.com", - "rakesh.ict@msruas.ac.in", - "omars@salecharter.net", - "citi.in.pm@xerago.com", - "qs@gsengint.com", - "sec.ls@msruas.ac.in", - "vaishnavi.kj@tvsrubber.com", - "nshcorp@nshcorp.in", - "purchase2@hitechelastomers.com", - "productionbelgavi@hodekindia.com", - "narayanababu.py.ph@msruas.ac.in", - "roopa.tsld@msruas.ac.in", - "in-nonciti.basupport@xerago.com", - "info@empiink.com", - "pooja.fa@msruas.ac.in", - "babu.d@tvsrubber.com", - "systeam@xerago.com", - "dean.ds@msruas.ac.in", - ) - or any(body.links, .href_url.domain.domain == "consumerspanel.frge.io") - ) + ( + // technique + strings.ilike(sender.display_name, "ukr*net") + and sender.email.domain.root_domain != "ukr.net" + ) + or ( + // IOCs + subject.subject == "Увага" + and ( + sender.email.email in ( + "muthuprakash.b@tvsrubber.com", + "rakesh.ict@msruas.ac.in", + "omars@salecharter.net", + "citi.in.pm@xerago.com", + "qs@gsengint.com", + "sec.ls@msruas.ac.in", + "vaishnavi.kj@tvsrubber.com", + "nshcorp@nshcorp.in", + "purchase2@hitechelastomers.com", + "productionbelgavi@hodekindia.com", + "narayanababu.py.ph@msruas.ac.in", + "roopa.tsld@msruas.ac.in", + "in-nonciti.basupport@xerago.com", + "info@empiink.com", + "pooja.fa@msruas.ac.in", + "babu.d@tvsrubber.com", + "systeam@xerago.com", + "dean.ds@msruas.ac.in", + ) + or any(body.links, .href_url.domain.domain == "consumerspanel.frge.io") ) + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_vanta.yml b/detection-rules/impersonation_vanta.yml index 241749c7896..6267a289c5e 100644 --- a/detection-rules/impersonation_vanta.yml +++ b/detection-rules/impersonation_vanta.yml @@ -8,17 +8,17 @@ authors: source: | type.inbound and ( - strings.ilike(sender.display_name, '*vanta*') - or strings.ilike(sender.email.email, '*vanta*') - or strings.ilevenshtein(sender.email.domain.sld, 'vanta') <= 1 + regex.imatch(sender.display_name, '\bvanta\b') + or strings.ilike(sender.email.local_part, '*vanta*') + or strings.ilevenshtein(sender.email.domain.sld, 'vanta') <= 1 ) and not ( - strings.ilike(sender.display_name, '*advantage*') - or strings.ilike(sender.email.email, '*advantage*') - or strings.ilevenshtein(sender.email.domain.sld, 'advantage') <= 1 + strings.ilike(sender.display_name, '*advantage*') + or strings.ilike(sender.email.email, '*advantage*') + or strings.ilevenshtein(sender.email.domain.sld, 'advantage') <= 1 ) and sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails + and sender.email.email not in $sender_emails attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/impersonation_venmo.yml b/detection-rules/impersonation_venmo.yml index d7f223835cb..e22d70de6cf 100644 --- a/detection-rules/impersonation_venmo.yml +++ b/detection-rules/impersonation_venmo.yml @@ -8,12 +8,21 @@ severity: "medium" source: | type.inbound and ( - strings.ilike(sender.display_name, '*venmo*') - or strings.ilevenshtein(sender.display_name, 'venmo') <= 1 - or strings.ilike(sender.email.domain.domain, '*venmo*') + strings.ilike(sender.display_name, '*venmo*') + or strings.ilevenshtein(sender.display_name, 'venmo') <= 1 + or strings.ilike(sender.email.domain.domain, '*venmo*') ) - and sender.email.domain.root_domain not in~ ('venmo.com', 'synchronybank.com') + and sender.email.domain.root_domain not in~ ('venmo.com', 'synchronybank.com', 'venmocreditsurvey.com') and sender.email.email not in $recipient_emails + + // and not if the sender.display.name contains "via" and dmarc pass from venmo.com + and not ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "pass") + and .authentication_results.dmarc_details.from.domain == "venmo.com" + ) + and strings.contains(sender.display_name, "via") + ) attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/impersonation_vip_urgent_request.yml b/detection-rules/impersonation_vip_urgent_request.yml index ca351239169..a0b24a6fd91 100644 --- a/detection-rules/impersonation_vip_urgent_request.yml +++ b/detection-rules/impersonation_vip_urgent_request.yml @@ -7,29 +7,24 @@ type: "rule" severity: "high" source: | type.inbound - and any($org_vips, .display_name == sender.display_name) - - and any([body.plain.raw, body.html.inner_text], - any(ml.nlu_classifier(.).intents, - .name == "bec" and .confidence == "high" - ) + and ( + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "bec" and .confidence == "high") or ( - any(ml.nlu_classifier(.).entities, .name == "urgency") - and any(ml.nlu_classifier(.).entities, .name == "request") + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency") + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") ) ) - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/impersonation_wells_fargo.yml b/detection-rules/impersonation_wells_fargo.yml index df4a0d019c4..117f9f3fd7f 100644 --- a/detection-rules/impersonation_wells_fargo.yml +++ b/detection-rules/impersonation_wells_fargo.yml @@ -9,14 +9,23 @@ severity: "high" source: | type.inbound and ( - sender.display_name =~ 'wells fargo' - or strings.ilevenshtein(sender.display_name, 'wells fargo') <= 1 - or strings.ilike(sender.email.domain.domain, '*wellsfargo*') - or strings.ilike(subject.subject, '*wells fargo security*') - or strings.ilike(body.plain.raw, '*wells fargo security team*') - or strings.ilike(body.html.inner_text, '*wells fargo security team*') + sender.display_name =~ 'wells fargo' + or strings.ilevenshtein(sender.display_name, 'wells fargo') <= 1 + or strings.ilike(sender.email.domain.domain, '*wellsfargo*') + or strings.ilike(subject.subject, '*wells fargo security*') + or strings.ilike(body.plain.raw, '*wells fargo security team*') + or strings.ilike(body.html.inner_text, '*wells fargo security team*') + ) + and sender.email.domain.root_domain not in~ ( + 'wellsfargo.com', + 'wellsfargoadvisors.com', + 'transunion.com', + 'wellsfargoemail.com', + 'wellsfargorewards.com', + 'comcast-spectacor.com', + 'investordelivery.com', + 'comcastspectacor.com' ) - and sender.email.domain.root_domain not in~ ('wellsfargo.com', 'wellsfargoadvisors.com', 'transunion.com', 'wellsfargoemail.com', 'wellsfargorewards.com', 'comcast-spectacor.com', 'investordelivery.com', 'comcastspectacor.com') and sender.email.email not in $recipient_emails attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_wise_suspicious_attachment.yml b/detection-rules/impersonation_wise_suspicious_attachment.yml index 7ee9bb9b194..9c08fa76a1a 100644 --- a/detection-rules/impersonation_wise_suspicious_attachment.yml +++ b/detection-rules/impersonation_wise_suspicious_attachment.yml @@ -6,15 +6,15 @@ severity: "high" source: | type.inbound and ( - strings.ilike(sender.display_name, '*wise*') - or strings.ilike(sender.email.domain.domain, '*wise*') - ) + strings.ilike(sender.display_name, '*wise*') + or strings.ilike(sender.email.domain.domain, '*wise*') + ) and any(ml.nlu_classifier(body.current_thread.text).tags, .name in ("payment", "invoice")) - and any(attachments, .file_type - in $file_extensions_common_archives - or .file_type in $file_extensions_executables - or .file_type in $file_extensions_macros - or .file_type in ("lz") + and any(attachments, + .file_type in $file_extensions_common_archives + or .file_type in $file_extensions_executables + or .file_type in $file_extensions_macros + or .file_type in ("lz") ) and sender.email.domain.root_domain not in~ ('wise.com', 'wise.jobs') attack_types: diff --git a/detection-rules/impersonation_zoom_strict.yml b/detection-rules/impersonation_zoom_strict.yml index 7f16a2066ac..73980c81631 100644 --- a/detection-rules/impersonation_zoom_strict.yml +++ b/detection-rules/impersonation_zoom_strict.yml @@ -9,24 +9,24 @@ severity: "medium" source: | type.inbound and ( - sender.display_name =~ 'zoom' - or sender.display_name =~ 'zoom video communications, inc.' - or sender.display_name =~ 'zoom call' + sender.display_name =~ 'zoom' + or sender.display_name =~ 'zoom video communications, inc.' + or sender.display_name =~ 'zoom call' ) - and sender.email.domain.root_domain not in ('zoom.us', 'zuora.com') + and sender.email.domain.root_domain not in ('zoom.us', 'zuora.com','zoomgov.com') and ( - // if this comes from a free email provider, - // flag if org has never sent an email to sender's email before - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - // if this comes from a custom domain, - // flag if org has never sent an email to sender's domain before - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + // if this comes from a free email provider, + // flag if org has never sent an email to sender's email before + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + // if this comes from a custom domain, + // flag if org has never sent an email to sender's domain before + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/inline_image_as_message.yml b/detection-rules/inline_image_as_message.yml index 545207dd3ff..ce0948fce12 100644 --- a/detection-rules/inline_image_as_message.yml +++ b/detection-rules/inline_image_as_message.yml @@ -10,20 +10,26 @@ source: | type.inbound and length(body.html.raw) < 200 and ( - ( - length(body.links) > 0 + ( + length(body.links) > 0 - // as of 20220116 there's a link parsing bug with .png inline images, so ignore those - and any(body.links, not strings.ilike(.href_url.url, "*.png")) - ) - // cid images are treated as attachments, so we're looking for more than 1 - or ( - length(attachments) > 1 - and any(attachments, .file_type not in ("jpg", "png", "gif")) - ) + // as of 20220116 there's a link parsing bug with .png inline images, so ignore those + and any(body.links, not strings.ilike(.href_url.url, "*.png")) + ) + // cid images are treated as attachments, so we're looking for more than 1 + or (length(attachments) > 1 and any(attachments, .file_type not in $file_types_images)) ) and strings.ilike(body.html.raw, "*img*cid*") - and sender.email.email not in $recipient_emails + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + ) attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/link_coinbase_low_rep_or_shortened.yml b/detection-rules/link_coinbase_low_rep_or_shortened.yml index 25ca7d8847f..c766a76b482 100644 --- a/detection-rules/link_coinbase_low_rep_or_shortened.yml +++ b/detection-rules/link_coinbase_low_rep_or_shortened.yml @@ -8,42 +8,40 @@ source: | and sender.email.domain.root_domain != "coinbase.com" // more than 0 less than 5 links - and 0 < length(body.links) < 5 + and 0 < length(body.links) < 5 // none of the links are to coinbase.com and all(body.links, .href_url.domain.root_domain != "coinbase.com") // low rep or url shortened links found - and any(body.links, - .href_url.domain.domain in $url_shorteners - - // exempting legitimate Google Maps shortener - and ( - not strings.ilike(.href_url.url, "http?://goo.gl/maps*") - or - ( - .href_url.domain.domain not in $tranco_1m or - .href_url.domain.domain in $free_file_hosts or - .href_url.domain.root_domain in $free_subdomain_hosts or - .href_url.domain.domain in $url_shorteners or + and any(body.links, + .href_url.domain.domain in $url_shorteners - // mass mailer link, masks the actual URL - .href_url.domain.root_domain in ( + // exempting legitimate Google Maps shortener + and ( + not strings.ilike(.href_url.url, "http?://goo.gl/maps*") + or ( + .href_url.domain.domain not in $tranco_1m + or .href_url.domain.domain in $free_file_hosts + or .href_url.domain.root_domain in $free_subdomain_hosts + or .href_url.domain.domain in $url_shorteners + or + + // mass mailer link, masks the actual URL + .href_url.domain.root_domain in ( "hubspotlinks.com", "mandrillapp.com", "sendgrid.net", ) + ) ) - ) ) // Coinbase logo and ( - any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(ml.logo_detect(.).brands, .name == "Coinbase") - ) - or any(ml.logo_detect(beta.message_screenshot()).brands, - .name == "Coinbase") + any(attachments, + .file_type in $file_types_images and any(ml.logo_detect(.).brands, .name == "Coinbase") + ) + or any(ml.logo_detect(beta.message_screenshot()).brands, .name == "Coinbase") ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_contains_punycode_characters.yml b/detection-rules/link_contains_punycode_characters.yml index b6602634cf6..961e9e9ad8a 100644 --- a/detection-rules/link_contains_punycode_characters.yml +++ b/detection-rules/link_contains_punycode_characters.yml @@ -9,7 +9,7 @@ authors: severity: "medium" source: | type.inbound - and any(body.links, .href_url.domain.punycode is not null) + and any(body.links, .href_url.domain.punycode is not null and .href_url.domain.valid == true) and ( // include automated emails sender.display_name == "WordPress" @@ -17,12 +17,12 @@ source: | // Has my organization ever sent an email to this sender? or ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails ) or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains ) ) attack_types: diff --git a/detection-rules/link_credential_phishing.yml b/detection-rules/link_credential_phishing.yml index 4da5dafcea0..214ae9fda81 100644 --- a/detection-rules/link_credential_phishing.yml +++ b/detection-rules/link_credential_phishing.yml @@ -4,21 +4,21 @@ description: | type: "rule" severity: "high" source: | - type.inbound - and any(body.links, - beta.linkanalysis(.).credphish.disposition == "phishing" - and beta.linkanalysis(.).credphish.confidence in ("medium", "high") - ) + type.inbound + and any(body.links, + beta.linkanalysis(.).credphish.disposition == "phishing" + and beta.linkanalysis(.).credphish.confidence in ("medium", "high") + ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_credential_phishing_intent_and_other_indicators.yml b/detection-rules/link_credential_phishing_intent_and_other_indicators.yml index f2ab0717bac..9a305f9ede5 100644 --- a/detection-rules/link_credential_phishing_intent_and_other_indicators.yml +++ b/detection-rules/link_credential_phishing_intent_and_other_indicators.yml @@ -7,292 +7,286 @@ source: | type.inbound and ( regex.icontains(subject.subject, - "termination.*notice", - "38417", - ":completed", - "[il1]{2}mit.*ma[il1]{2} ?bo?x", - "[il][il][il]egai[ -]", - "[li][li][li]ega[li] attempt", - "[ng]-?[io]n .*block", - "[ng]-?[io]n .*cancel", - "[ng]-?[io]n .*deactiv", - "[ng]-?[io]n .*disabl", - "action.*required", - "abandon.*package", - "about.your.account", - "acc(ou)?n?t (is )?on ho[li]d", - "acc(ou)?n?t.*terminat", - "acc(oun)?t.*[il1]{2}mitation", - "access.*limitation", - "account (will be )?block", - "account.*de-?activat", - "account.*locked", - "account.*re-verification", - "account.*security", - "account.*suspension", - "account.has.been", - "account.has.expired", - "account.will.be.blocked", - "account v[il]o[li]at", - "activity.*acc(oun)?t", - "almost.full", - "app[li]e.[il]d", - "authenticate.*account", - "been.*suspend", - "clos.*of.*account.*processed", - "confirm.your.account", - "courier.*able", - "deactivation.*in.*progress", - "delivery.*attempt.*failed", - "document.received", - "documented.*shared.*with.*you", - "dropbox.*document", - "e-?ma[il1]+ .{010}suspen", - "e-?ma[il1]{1} user", - "e-?ma[il1]{2} acc", - "e-?ma[il1]{2}.*up.?grade", - "e.?ma[il1]{2}.*server", - "e.?ma[il1]{2}.*suspend", - "email.update", - "faxed you", - "fraud(ulent)?.*charge", - "from.helpdesk", - "fu[il1]{2}.*ma[il1]+[ -]?box", - "has.been.*suspended", - "has.been.limited", - "have.locked", - "he[li]p ?desk upgrade", - "heipdesk", - "i[il]iega[il]", - "ii[il]ega[il]", - "incoming e?mail", - "incoming.*fax", - "lock.*security", - "ma[il1]{1}[ -]?box.*quo", - "ma[il1]{2}[ -]?box.*fu[il1]", - "ma[il1]{2}box.*[il1]{2}mit", - "ma[il1]{2}box stor", - "mail on.?hold", - "mail.*box.*migration", - "mail.*de-?activat", - "mail.update.required", - "mails.*pending", - "messages.*pending", - "missed.*shipping.*notification", - "missed.shipment.notification", - "must.update.your.account", - "new [sl][io]g?[nig][ -]?in from", - "new voice ?-?mail", - "notifications.*pending", - "office.*3.*6.*5.*suspend", - "office365", - "on google docs with you", - "online doc", - "password.*compromised", - "periodic maintenance", - "potential(ly)? unauthorized", - "refund not approved", - "report", - "revised.*policy", - "scam", - "scanned.?invoice", - "secured?.update", - "security breach", - "securlty", - "signed.*delivery", - "status of your .{314}? ?delivery", - "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty", - "suspicious.*sign.*[io]n", - "suspicious.activit", - "temporar(il)?y deactivate", - "temporar[il1]{2}y disab[li]ed", - "temporarily.*lock", - "un-?usua[li].activity", - "unable.*deliver", - "unauthorized.*activit", - "unauthorized.device", - "undelivered message", - "unread.*doc", - "unusual.activity", - "upgrade.*account", - "upgrade.notice", - "urgent message", - "urgent.verification", - "v[il1]o[li1]at[il1]on security", - "va[il1]{1}date.*ma[il1]{2}[ -]?box", - "verification ?-?require", - "verification( )?-?need", - "verify.your?.account", - "web ?-?ma[il1]{2}", - "web[ -]?ma[il1]{2}", - "will.be.suspended", - "your (customer )?account .as", - "your.office.365", - "your.online.access", - // https://github.com/sublime-security/static-files/blob/master/suspicious_subjects.txt - "account has been limited", - "action required", - "almost full", - "apd notifi cation", - "are you at your desk", - "are you available", - "attached file to docusign", - "banking is temporarily unavailable", - "bankofamerica", - "closing statement invoice", - "completed: docusign", - "de-activation of", - "delivery attempt", - "delivery stopped for shipment", - "detected suspicious", - "detected suspicious actvity", - "docu sign", - "document for you", - "document has been sent to you via docusign", - "document is ready for signature", - "docusign", - "encrypted message", - "failed delivery", - "fedex tracking", - "file was shared", - "freefax", - "fwd: due invoice paid", - "has shared", - "inbox is full", - "invitation to comment", - "invitation to edit", - "invoice due", - "left you a message", - "message from", - "new message", - "new voicemail", - "on desk", - "out of space", - "password reset", - "payment status", - "quick reply", - "re: w-2", - "required", - "required: completed docusign", - "remittance", - "ringcentral", - "scanned image", - "secured files", - "secured pdf", - "security alert", - "new sign-in", - "new sign in", - "sign-in attempt", - "sign in attempt", - "staff review", - "suspicious activity", - "unrecognized login attempt", - "upgrade immediately", - "urgent", - "wants to share", - "w2", - "you have notifications pending", - "your account", - "your amazon order", - "your document settlement", - "your order with amazon", - "your password has been compromised", + "termination.*notice", + "38417", + ":completed", + "[il1]{2}mit.*ma[il1]{2} ?bo?x", + "[il][il][il]egai[ -]", + "[li][li][li]ega[li] attempt", + "[ng]-?[io]n .*block", + "[ng]-?[io]n .*cancel", + "[ng]-?[io]n .*deactiv", + "[ng]-?[io]n .*disabl", + "action.*required", + "abandon.*package", + "about.your.account", + "acc(ou)?n?t (is )?on ho[li]d", + "acc(ou)?n?t.*terminat", + "acc(oun)?t.*[il1]{2}mitation", + "access.*limitation", + "account (will be )?block", + "account.*de-?activat", + "account.*locked", + "account.*re-verification", + "account.*security", + "account.*suspension", + "account.has.been", + "account.has.expired", + "account.will.be.blocked", + "account v[il]o[li]at", + "activity.*acc(oun)?t", + "almost.full", + "app[li]e.[il]d", + "authenticate.*account", + "been.*suspend", + "clos.*of.*account.*processed", + "confirm.your.account", + "courier.*able", + "deactivation.*in.*progress", + "delivery.*attempt.*failed", + "document.received", + "documented.*shared.*with.*you", + "dropbox.*document", + "e-?ma[il1]+ .{010}suspen", + "e-?ma[il1]{1} user", + "e-?ma[il1]{2} acc", + "e-?ma[il1]{2}.*up.?grade", + "e.?ma[il1]{2}.*server", + "e.?ma[il1]{2}.*suspend", + "email.update", + "faxed you", + "fraud(ulent)?.*charge", + "from.helpdesk", + "fu[il1]{2}.*ma[il1]+[ -]?box", + "has.been.*suspended", + "has.been.limited", + "have.locked", + "he[li]p ?desk upgrade", + "heipdesk", + "i[il]iega[il]", + "ii[il]ega[il]", + "incoming e?mail", + "incoming.*fax", + "lock.*security", + "ma[il1]{1}[ -]?box.*quo", + "ma[il1]{2}[ -]?box.*fu[il1]", + "ma[il1]{2}box.*[il1]{2}mit", + "ma[il1]{2}box stor", + "mail on.?hold", + "mail.*box.*migration", + "mail.*de-?activat", + "mail.update.required", + "mails.*pending", + "messages.*pending", + "missed.*shipping.*notification", + "missed.shipment.notification", + "must.update.your.account", + "new [sl][io]g?[nig][ -]?in from", + "new voice ?-?mail", + "notifications.*pending", + "office.*3.*6.*5.*suspend", + "office365", + "on google docs with you", + "online doc", + "password.*compromised", + "periodic maintenance", + "potential(ly)? unauthorized", + "refund not approved", + "report", + "revised.*policy", + "scam", + "scanned.?invoice", + "secured?.update", + "security breach", + "securlty", + "signed.*delivery", + "status of your .{314}? ?delivery", + "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty", + "suspicious.*sign.*[io]n", + "suspicious.activit", + "temporar(il)?y deactivate", + "temporar[il1]{2}y disab[li]ed", + "temporarily.*lock", + "un-?usua[li].activity", + "unable.*deliver", + "unauthorized.*activit", + "unauthorized.device", + "undelivered message", + "unread.*doc", + "unusual.activity", + "upgrade.*account", + "upgrade.notice", + "urgent message", + "urgent.verification", + "v[il1]o[li1]at[il1]on security", + "va[il1]{1}date.*ma[il1]{2}[ -]?box", + "verification ?-?require", + "verification( )?-?need", + "verify.your?.account", + "web ?-?ma[il1]{2}", + "web[ -]?ma[il1]{2}", + "will.be.suspended", + "your (customer )?account .as", + "your.office.365", + "your.online.access", + // https://github.com/sublime-security/static-files/blob/master/suspicious_subjects.txt + "account has been limited", + "action required", + "almost full", + "apd notifi cation", + "are you at your desk", + "are you available", + "attached file to docusign", + "banking is temporarily unavailable", + "bankofamerica", + "closing statement invoice", + "completed: docusign", + "de-activation of", + "delivery attempt", + "delivery stopped for shipment", + "detected suspicious", + "detected suspicious actvity", + "docu sign", + "document for you", + "document has been sent to you via docusign", + "document is ready for signature", + "docusign", + "encrypted message", + "failed delivery", + "fedex tracking", + "file was shared", + "freefax", + "fwd: due invoice paid", + "has shared", + "inbox is full", + "invitation to comment", + "invitation to edit", + "invoice due", + "left you a message", + "message from", + "new message", + "new voicemail", + "on desk", + "out of space", + "password reset", + "payment status", + "quick reply", + "re: w-2", + "required", + "required: completed docusign", + "remittance", + "ringcentral", + "scanned image", + "secured files", + "secured pdf", + "security alert", + "new sign-in", + "new sign in", + "sign-in attempt", + "sign in attempt", + "staff review", + "suspicious activity", + "unrecognized login attempt", + "upgrade immediately", + "urgent", + "wants to share", + "w2", + "you have notifications pending", + "your account", + "your amazon order", + "your document settlement", + "your order with amazon", + "your password has been compromised", ) or regex.icontains(sender.display_name, - "Admin", - "Administrator", - "Alert", - "Assistant", - "Billing", - "Benefits", - "Bonus", - "CEO", - "CFO", - "CIO", - "CTO", - "Chairman", - "Claim", - "Confirm", - "Critical", - "Customer Service", - "Deal", - "Discount", - "Director", - "Exclusive", - "Executive", - "Fax", - "Free", - "Gift", - "HR", - "Helpdesk", - "Human Resources", - "Immediate", - "Important", - "Info", - "Information", - "Invoice", - '\bIT\b', - "Legal", - "Lottery", - "Management", - "Manager", - "Member Services", - "Notification", - "Offer", - "Operations", - "Order", - "Partner", - "Payment", - "Payroll", - "President", - "Premium", - "Prize", - "Receipt", - "Refund", - "Registrar", - "Required", - "Reward", - "Sales", - "Secretary", - "Security", - "Service", - "Support", - "Sweepstakes", - "System", - "Tax", - "Team", - "Tech Support", - "Update", - "Upgrade", - "Urgent", - "Validate", - "Verify", - "VIP", - "Webmaster", - "Winner", + "Admin", + "Administrator", + "Alert", + "Assistant", + "Billing", + "Benefits", + "Bonus", + "CEO", + "CFO", + "CIO", + "CTO", + "Chairman", + "Claim", + "Confirm", + "Critical", + "Customer Service", + "Deal", + "Discount", + "Director", + "Exclusive", + "Executive", + "Fax", + "Free", + "Gift", + "HR", + "Helpdesk", + "Human Resources", + "Immediate", + "Important", + "Info", + "Information", + "Invoice", + '\bIT\b', + "Legal", + "Lottery", + "Management", + "Manager", + "Member Services", + "Notification", + "Offer", + "Operations", + "Order", + "Partner", + "Payment", + "Payroll", + "President", + "Premium", + "Prize", + "Receipt", + "Refund", + "Registrar", + "Required", + "Reward", + "Sales", + "Secretary", + "Security", + "Service", + "Support", + "Sweepstakes", + "System", + "Tax", + "Team", + "Tech Support", + "Update", + "Upgrade", + "Urgent", + "Validate", + "Verify", + "VIP", + "Webmaster", + "Winner", ) ) and any(body.links, - // is the recipient's email address in the URL? - // this method accounts for any encoding we might encounter - // in the query_params - // this is common in link tracking, both for - // benign marketing traffic but also attackers - any(recipients.to, - strings.icontains(..href_url.url, .email.local_part) - and strings.icontains(..href_url.url, .email.domain.domain) - ) - ) - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name == "cred_theft" - and .confidence in ("medium", "high") + // is the recipient's email address in the URL? + // this method accounts for any encoding we might encounter + // in the query_params + // this is common in link tracking, both for + // benign marketing traffic but also attackers + any(recipients.to, + strings.icontains(..href_url.url, .email.local_part) + and strings.icontains(..href_url.url, .email.domain.domain) + ) ) - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities, - .name == "request" + and any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "cred_theft" and .confidence in ("medium", "high") ) - + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") and ( // freemail providers should never be sending this type of email sender.email.domain.domain in $free_email_providers @@ -304,14 +298,14 @@ source: | // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_credential_phishing_language_ipfs.yml b/detection-rules/link_credential_phishing_language_ipfs.yml index b94fc53e673..3879245c22c 100644 --- a/detection-rules/link_credential_phishing_language_ipfs.yml +++ b/detection-rules/link_credential_phishing_language_ipfs.yml @@ -8,22 +8,22 @@ source: | and strings.ilike(body.html.display_text, "*expir*") and strings.ilike(body.html.display_text, "*password*") and any(ml.nlu_classifier(body.html.display_text).intents, .name == "cred_theft") - and any(body.links, - strings.icontains(beta.linkanalysis(.).effective_url.url, 'ipfs') - or ( - regex.icontains(beta.linkanalysis(.).effective_url.path, '[\.-/]ipfs|ipfs[\.-/]') - and beta.linkanalysis(.).effective_url.domain.domain not in $org_domains - and ( - ( - // don't include high rep domains - beta.linkanalysis(.).effective_url.domain.domain not in $tranco_1m - and beta.linkanalysis(.).effective_url.domain.domain not in $umbrella_1m - ) + and any(body.links, + strings.icontains(beta.linkanalysis(.).effective_url.url, 'ipfs') + or ( + regex.icontains(beta.linkanalysis(.).effective_url.path, '[\.-/]ipfs|ipfs[\.-/]') + and beta.linkanalysis(.).effective_url.domain.domain not in $org_domains + and ( + ( + // don't include high rep domains + beta.linkanalysis(.).effective_url.domain.domain not in $tranco_1m + and beta.linkanalysis(.).effective_url.domain.domain not in $umbrella_1m + ) // if it's in Tranco or Umbrella, still include it if it's one of these or beta.linkanalysis(.).effective_url.domain.domain in $free_file_hosts or beta.linkanalysis(.).effective_url.domain.root_domain in $free_subdomain_hosts + ) ) - ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_credential_phishing_secure_message.yml b/detection-rules/link_credential_phishing_secure_message.yml index 51ae6b43e60..4cf9ed06d0b 100644 --- a/detection-rules/link_credential_phishing_secure_message.yml +++ b/detection-rules/link_credential_phishing_secure_message.yml @@ -5,7 +5,6 @@ type: "rule" severity: "medium" source: | type.inbound - and any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence == "high" ) @@ -21,6 +20,14 @@ source: | // has at least 1 link and length(body.links) > 0 + // negate legitimate message senders + and ( + sender.email.domain.root_domain not in ("protectedtrust.com") + and any(body.links, + .href_url.domain.root_domain != sender.email.domain.root_domain + ) + ) + // first-time sender and ( ( diff --git a/detection-rules/link_credential_phishing_suspicious_sender_tld_and_signals.yml b/detection-rules/link_credential_phishing_suspicious_sender_tld_and_signals.yml index b3fbdb5bcb6..f8d7ac3732c 100644 --- a/detection-rules/link_credential_phishing_suspicious_sender_tld_and_signals.yml +++ b/detection-rules/link_credential_phishing_suspicious_sender_tld_and_signals.yml @@ -15,7 +15,6 @@ source: | // commonly abused sender TLD and strings.ilike(sender.email.domain.tld, "*.jp") - and 3 of ( // language attempting to engage any(ml.nlu_classifier(body.html.display_text).entities, .name == "request"), @@ -30,36 +29,31 @@ source: | any(body.links, regex.match(.href_url.path, '\/[a-z]{3}\d[a-z]')), // suspicious image that's most likely cred_theft - any(attachments, .file_type in~ ('bmp', 'png', 'jpg', 'jpeg') - and any(file.explode(.), - any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft") - - or any(ml.nlu_classifier(.scan.ocr.raw).entities, .name == "financial") - ) + any(attachments, + .file_type in $file_types_images + and any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft") + or any(ml.nlu_classifier(.scan.ocr.raw).entities, .name == "financial") + ) ), // recipient's SLD is in the sender's display name - any(recipients.to, - strings.icontains(sender.display_name, .email.domain.sld) - ), + any(recipients.to, strings.icontains(sender.display_name, .email.domain.sld)), // recipient's email address in the subject - any(recipients.to, - strings.icontains(subject.subject, .email.email) - ), - + any(recipients.to, strings.icontains(subject.subject, .email.email)), ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_credential_phishing_voicemail_language.yml b/detection-rules/link_credential_phishing_voicemail_language.yml index 7b446d465d4..0df96e25fe3 100644 --- a/detection-rules/link_credential_phishing_voicemail_language.yml +++ b/detection-rules/link_credential_phishing_voicemail_language.yml @@ -5,53 +5,44 @@ description: | type: "rule" severity: "medium" source: | - type.inbound + type.inbound and length(body.links) > 0 - + // voicemail related and ( - regex.icontains(coalesce(body.html.inner_text, body.html.display_text), - 'voice\s?(mail|message|recording|call)' - ) or ( - regex.icontains(subject.subject, 'voice\s?(mail|message|recording|call)') - ) + regex.icontains(body.current_thread.text, 'voice\s?(mail|message|recording|call)') + or (regex.icontains(subject.subject, 'voice\s?(mail|message|recording|call)')) ) - and 2 of ( - ( - any([body.plain.raw, body.html.inner_text], - any(ml.nlu_classifier(.).intents, - .name in ("cred_theft") and - .confidence in ("medium", "high") - ) - ) - ), - ( - regex.icontains(sender.display_name, 'voice\s?(mail|message|recording|call)') - ), - ( - // sender domain matches no body domains - all(body.links, - .href_url.domain.root_domain != sender.email.domain.root_domain and - .href_url.domain.root_domain not in $org_domains - ) - ), - ( - // recipient's SLD is in the sender's display name - any(recipients.to, - strings.icontains(sender.display_name, .email.domain.sld) - ) - ), + ( + any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("cred_theft") and .confidence in ("medium", "high") + ) + ), + (regex.icontains(sender.display_name, 'voice\s?(mail|message|recording|call)')), + ( + // sender domain matches no body domains + all(body.links, + .href_url.domain.root_domain != sender.email.domain.root_domain + and .href_url.domain.root_domain not in $org_domains + and .href_url.domain.root_domain not in ("unitelvoice.com", "googleapis.com", "dialmycalls.com") + ) + ), + ( + // recipient's SLD is in the sender's display name + any(recipients.to, strings.icontains(sender.display_name, .email.domain.sld)) + ), ) + and sender.email.domain.root_domain not in ("magicjack.com", "unitelvoice.com") and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_deactivated_bitly.yml b/detection-rules/link_deactivated_bitly.yml index c7d0fb33248..b0467b973d4 100644 --- a/detection-rules/link_deactivated_bitly.yml +++ b/detection-rules/link_deactivated_bitly.yml @@ -6,14 +6,12 @@ severity: "medium" source: | type.inbound and any(body.links, - // contains bit.ly link - .href_url.domain.root_domain == "bit.ly" - // link doesn't forward through - and beta.linkanalysis(.).effective_url.domain.domain == "bit.ly" - // blocked by bit.ly - and strings.ilike( - beta.linkanalysis(.).final_dom.display_text, "*link*blocked*" - ) + // contains bit.ly link + .href_url.domain.root_domain == "bit.ly" + // link doesn't forward through + and beta.linkanalysis(.).effective_url.domain.domain == "bit.ly" + // blocked by bit.ly + and strings.ilike(beta.linkanalysis(.).final_dom.display_text, "*link*blocked*") ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_download_disk_image_in_encrypted_zip.yml b/detection-rules/link_download_disk_image_in_encrypted_zip.yml index 03c55ce08db..4d4019a331e 100644 --- a/detection-rules/link_download_disk_image_in_encrypted_zip.yml +++ b/detection-rules/link_download_disk_image_in_encrypted_zip.yml @@ -11,27 +11,29 @@ severity: "medium" authors: - twitter: "ajpc500" source: | - type.inbound - and any(body.links, - any(beta.linkanalysis(.).files_downloaded, - any( - file.explode(.), ( - any(.flavors.yara, . == "encrypted_zip") and - any(.scan.zip.all_paths, any([".img", ".iso", ".vhd"], strings.ends_with(.., .))) + type.inbound + and any(body.links, + any(beta.linkanalysis(.).files_downloaded, + any(file.explode(.), + ( + any(.flavors.yara, . == "encrypted_zip") + and any(.scan.zip.all_paths, + any([".img", ".iso", ".vhd"], strings.ends_with(.., .)) + ) + ) ) ) - ) ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) tags: - "Malfam: QakBot" diff --git a/detection-rules/link_download_suspicious_file.yml b/detection-rules/link_download_suspicious_file.yml index 51f23a46dad..969c0ef8cdb 100644 --- a/detection-rules/link_download_suspicious_file.yml +++ b/detection-rules/link_download_suspicious_file.yml @@ -14,36 +14,35 @@ severity: "medium" source: | type.inbound and any(body.links, - any(beta.linkanalysis(.).files_downloaded, - any(file.explode(.), - ( - // look for files in encrypted zips. - // if password cracking the zip wasn't - // successful, our only opportunity to look - // for suspicious file types is here under - // .zip.attempted_files - "encrypted_zip" in .flavors.yara - - and any(.scan.zip.attempted_files, - strings.ilike(., "*.lnk", "*.js", "*.vba", "*.vbs", "*.vbe") + any(beta.linkanalysis(.).files_downloaded, + any(file.explode(.), + ( + // look for files in encrypted zips. + // if password cracking the zip wasn't + // successful, our only opportunity to look + // for suspicious file types is here under + // .zip.attempted_files + "encrypted_zip" in .flavors.yara + and any(.scan.zip.attempted_files, + strings.ilike(., "*.lnk", "*.js", "*.vba", "*.vbs", "*.vbe") + ) ) + // for both non-encrypted zips and encrypted zips + // that were successfully cracked + or .file_extension in ("lnk", "js", "vba", "vbs", "vbe") ) - // for both non-encrypted zips and encrypted zips - // that were successfully cracked - or .file_extension in ("lnk", "js", "vba", "vbs", "vbe") ) - ) ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Malware/Ransomware" diff --git a/detection-rules/link_dynamics_form.yml b/detection-rules/link_dynamics_form.yml index 57279577c92..d7c287edbb6 100644 --- a/detection-rules/link_dynamics_form.yml +++ b/detection-rules/link_dynamics_form.yml @@ -7,35 +7,38 @@ type: "rule" severity: "high" source: | type.inbound - and any(body.links, .href_url.domain.domain in ("ncv.microsoft.com", "customervoice.microsoft.com") - and beta.linkanalysis(.).effective_url.domain.domain == "customervoice.microsoft.com" + and any(body.links, + .href_url.domain.domain in ("ncv.microsoft.com", "customervoice.microsoft.com") + and beta.linkanalysis(.).effective_url.domain.domain == "customervoice.microsoft.com" - // confirm it is a form - and any(beta.linkanalysis(.).final_dom.links, .href_url.domain.domain == "cdn.forms.office.net") + // confirm it is a form + and any(beta.linkanalysis(.).final_dom.links, + .href_url.domain.domain == "cdn.forms.office.net" + ) - // analyze for credential phishing signals - and 1 of ( + // analyze for credential phishing signals + and 1 of ( ( - // analyze the link - any(file.explode(beta.linkanalysis(.).screenshot), - any(ml.nlu_classifier(.scan.ocr.raw).intents, - .name == "cred_theft" and .confidence != "low" - ) + // analyze the link + any(file.explode(beta.linkanalysis(.).screenshot), + any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence != "low" ) + ) ), ( - // analyze the HTML body - any(ml.nlu_classifier(body.html.display_text).intents, - .name == "cred_theft" and .confidence != "low" - ) + // analyze the HTML body + any(ml.nlu_classifier(body.html.display_text).intents, + .name == "cred_theft" and .confidence != "low" + ) ), ( - // analyze the plain body - any(ml.nlu_classifier(body.plain.raw).intents, - .name == "cred_theft" and .confidence != "low" - ) + // analyze the plain body + any(ml.nlu_classifier(body.plain.raw).intents, + .name == "cred_theft" and .confidence != "low" + ) ) - ) + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_fake_fax_low_reputation.yml b/detection-rules/link_fake_fax_low_reputation.yml index 0bf72f79c40..0974ab392d0 100644 --- a/detection-rules/link_fake_fax_low_reputation.yml +++ b/detection-rules/link_fake_fax_low_reputation.yml @@ -10,60 +10,50 @@ source: | and 0 < length(body.links) < 5 and sender.email.domain.root_domain not in $org_domains and any(body.links, - ( - .href_url.domain.domain not in $tranco_1m or - .href_url.domain.domain in $free_file_hosts or - .href_url.domain.root_domain in $free_subdomain_hosts or - .href_url.domain.domain in $url_shorteners or - - // mass mailer link, masks the actual URL - .href_url.domain.root_domain in ( - "hubspotlinks.com", - "mandrillapp.com", - "sendgrid.net", + ( + .href_url.domain.domain not in $tranco_1m + or .href_url.domain.domain in $free_file_hosts + or .href_url.domain.root_domain in $free_subdomain_hosts + or .href_url.domain.domain in $url_shorteners + or + + // mass mailer link, masks the actual URL + .href_url.domain.root_domain in ("hubspotlinks.com", "mandrillapp.com", "sendgrid.net", ) ) - ) ) - + // any brand logo detected and ( - any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(ml.logo_detect(.).brands, .name is not null) - ) - or any(ml.logo_detect(beta.message_screenshot()).brands, - .name is not null) + any(attachments, + .file_type in $file_types_images and any(ml.logo_detect(.).brands, .name is not null) + ) + or any(ml.logo_detect(beta.message_screenshot()).brands, .name is not null) ) - + // Subject or sender contains fax - and ( - strings.icontains(subject.subject, "fax") or - strings.icontains(sender.display_name, "fax") - ) - + and (strings.icontains(subject.subject, "fax") or strings.icontains(sender.display_name, "fax")) + // suspicious content and ( - strings.ilike(body.plain.raw, "*fax*") - or ( - any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(file.explode(.), - strings.ilike(.scan.ocr.raw, "*fax*") - ) - ) + strings.ilike(body.plain.raw, "*fax*") + or ( + any(attachments, + .file_type in $file_types_images + and any(file.explode(.), strings.ilike(.scan.ocr.raw, "*fax*")) ) + ) ) - + // first time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_fake_thread_nlu_financial_request.yml b/detection-rules/link_fake_thread_nlu_financial_request.yml index 4f52fb5e712..6531d54e6b2 100644 --- a/detection-rules/link_fake_thread_nlu_financial_request.yml +++ b/detection-rules/link_fake_thread_nlu_financial_request.yml @@ -3,65 +3,72 @@ description: "Detects fake message threads with suspicious links and financial r type: "rule" severity: "medium" source: | - type.inbound - + type.inbound + and length(body.links) < 10 // suspicious link and any(body.links, - .href_url.domain.root_domain not in $tranco_1m and - .href_url.domain.domain not in $umbrella_1m + .href_url.domain.root_domain not in $tranco_1m + and .href_url.domain.domain not in $umbrella_1m ) - + // fake thread check - and ( - strings.istarts_with(subject.subject, "RE:") - or strings.istarts_with(subject.subject, "FWD:") - ) - + and (strings.istarts_with(subject.subject, "RE:") or strings.istarts_with(subject.subject, "FWD:")) + // Check for the Presence of References or In-Reply-To properties and ( - ( - length(headers.references) == 0 - and headers.in_reply_to is null - ) - or ( - not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) - and not any(headers.hops, strings.ilike(.signature.headers, "*:reply-to")) - ) + (length(headers.references) == 0 and headers.in_reply_to is null) + or ( + not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) + and not any(headers.hops, strings.ilike(.signature.headers, "*:reply-to")) + ) ) - + // sender's domain is not in body, and body has > 0 links and length(body.links) > 0 and sender.email.domain.root_domain not in $free_email_providers and not any(body.links, .href_url.domain.root_domain == sender.email.domain.root_domain) - + // unusual sender (email address rarely sends to your organization) and sender.email.email not in $sender_emails - + // unusual sender domain (domain rarely sends to your organization) and sender.email.domain.domain not in $sender_domains - - and 2 of ( + and 4 of ( // language attempting to engage - any(ml.nlu_classifier(body.html.inner_text).entities, .name == "request"), - - // financial request - any(ml.nlu_classifier(body.html.inner_text).entities, .name == "financial"), - + ( + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") + and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "financial") + ), + + // invoicing language + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice"), + // urgency request - any(ml.nlu_classifier(body.html.inner_text).entities, .name == "urgency"), - + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency"), + // cred_theft detection - any(ml.nlu_classifier(body.html.inner_text).intents, .name == "cred_theft" and .confidence in~ ("medium", "high")), - + any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "cred_theft" and .confidence in~ ("medium", "high") + ), + // commonly abused sender TLD strings.ilike(sender.email.domain.tld, "*.jp"), - + + // headers traverse abused TLD + any(headers.domains, strings.ilike(.tld, "*.jp")), + // known suspicious pattern in the URL path any(body.links, regex.match(.href_url.path, '\/[a-z]{3}\d[a-z]')), - + // link display text is in all caps any(body.links, regex.match(.display_text, '[A-Z ]+')), - + + // display name contains an email + regex.contains(sender.display_name, '[a-z0-9]+@[a-z]+'), + + // Sender domain is empty + sender.email.domain.domain == "", + // sender domain matches no body domains all(body.links, .href_url.domain.root_domain != sender.email.domain.root_domain), ) diff --git a/detection-rules/link_firebase_new_domain_redirect.yml b/detection-rules/link_firebase_new_domain_redirect.yml index 56770e6e0dd..f08ddba7daa 100644 --- a/detection-rules/link_firebase_new_domain_redirect.yml +++ b/detection-rules/link_firebase_new_domain_redirect.yml @@ -7,11 +7,11 @@ authors: - twitter: "ajpc500" severity: "low" source: | - type.inbound and - any(body.links, - .href_url.domain.root_domain =~ "goo.gl" and - strings.icontains(.href_url.domain.domain, "app") and - any(beta.linkanalysis(.).redirect_history, beta.whois(.domain).days_old < 7) + type.inbound + and any(body.links, + .href_url.domain.root_domain =~ "goo.gl" + and strings.icontains(.href_url.domain.domain, "app") + and any(beta.linkanalysis(.).redirect_history, beta.whois(.domain).days_old < 7) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_google_amp_suspicious_indicators.yml b/detection-rules/link_google_amp_suspicious_indicators.yml index 69b2c6eb4ea..21209aa3456 100644 --- a/detection-rules/link_google_amp_suspicious_indicators.yml +++ b/detection-rules/link_google_amp_suspicious_indicators.yml @@ -10,17 +10,17 @@ severity: "medium" source: | type.inbound - // Any body links with a domain SLD of 'google' and a path starting with /amp/s + // Any body links with a domain SLD of 'google' and a path starting with /amp and any(body.links, .href_url.domain.sld == "google" - and strings.starts_with(.href_url.path, "/amp/s/") + and strings.starts_with(.href_url.path, "/amp/") // Brand Logo detected that is not google and ( any(ml.logo_detect(beta.message_screenshot()).brands, .name is not null and .name != "Google" ) - + // or the page has a login or captcha or ( beta.linkanalysis(.).credphish.contains_login @@ -38,7 +38,7 @@ source: | any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft" and .confidence in ("medium", "high") ) - + // captcha partially loaded or strings.icontains(.scan.ocr.raw, "Checking if the site connection is secure") ) diff --git a/detection-rules/link_google_apps_script_macro.yml b/detection-rules/link_google_apps_script_macro.yml index 455c236c8c7..646a0a9f669 100644 --- a/detection-rules/link_google_apps_script_macro.yml +++ b/detection-rules/link_google_apps_script_macro.yml @@ -8,19 +8,19 @@ type: "rule" severity: "medium" source: | type.inbound - and any(body.links, .href_url.domain.domain == "script.google.com" - and strings.ilike(.href_url.path, "/macros*") + and any(body.links, + .href_url.domain.domain == "script.google.com" and strings.ilike(.href_url.path, "/macros*") ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_google_comment_script_macro.yml b/detection-rules/link_google_comment_script_macro.yml index f3b769a83de..89ea228a3df 100644 --- a/detection-rules/link_google_comment_script_macro.yml +++ b/detection-rules/link_google_comment_script_macro.yml @@ -9,18 +9,18 @@ type: "rule" severity: "medium" source: | type.inbound - and regex.contains( - sender.display_name, '\(Google (Slides|Docs)') + and regex.contains(sender.display_name, '\(Google (Slides|Docs)') and any(body.links, - .href_url.domain.domain == "script.google.com" - and strings.ilike(.href_url.path, "/macros*") + .href_url.domain.domain == "script.google.com" and strings.ilike(.href_url.path, "/macros*") ) and 1 of ( strings.ilike(body.plain.raw, '*you have ? hours*'), strings.ilike(body.plain.raw, '*transfer of funds*'), strings.ilike(body.plain.raw, '*order your funds*') // Or the Sender Display Name is not in your Org Display Names - or not any($org_display_names, strings.istarts_with(sender.display_name, strings.concat(., " (Google "))) + or not any($org_display_names, + strings.istarts_with(sender.display_name, strings.concat(., " (Google ")) + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_google_fake_sign_in_image_lure.yml b/detection-rules/link_google_fake_sign_in_image_lure.yml index 0f7f8a25679..8f0d8bd3aa6 100644 --- a/detection-rules/link_google_fake_sign_in_image_lure.yml +++ b/detection-rules/link_google_fake_sign_in_image_lure.yml @@ -6,33 +6,32 @@ severity: "high" source: | type.inbound and length(body.links) > 0 - + // Google Logo in Attachment and any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(ml.logo_detect(.).brands, .name in ("Google")) + .file_type in $file_types_images and any(ml.logo_detect(.).brands, .name in ("Google")) ) and any(attachments, - .file_type in~ ('bmp', 'png', 'jpg', 'jpeg') - and ( - any(file.explode(.), - // Fake activity warning - length(filter(.scan.strings.strings, strings.ilike(., - "*new sign-in*", - "*google account*", - "*secure your account*", - "*check activity*" - ))) >= 3 + .file_type in $file_types_images + and ( + any(file.explode(.), + // Fake activity warning + 3 of ( + strings.ilike(.scan.ocr.raw, "*new sign-in*"), + strings.ilike(.scan.ocr.raw, "*google account*"), + strings.ilike(.scan.ocr.raw, "*secure your account*"), + strings.ilike(.scan.ocr.raw, "*check activity*"), + ) + ) ) - ) ) - + // legitimate sign-in warnings contains links to google, gmail or googleapis.com and ( - not all(body.links, - .href_url.domain.root_domain in ("google.com", "gmail.com", "googleapis.com") - or .href_url.domain.root_domain is null - ) + not all(body.links, + .href_url.domain.root_domain in ("google.com", "gmail.com", "googleapis.com") + or .href_url.domain.root_domain is null + ) ) and sender.email.domain.root_domain not in $org_domains and sender.email.domain.root_domain != "google.com" diff --git a/detection-rules/link_google_open_redirect_with_suspicious_indicators.yml b/detection-rules/link_google_open_redirect_with_suspicious_indicators.yml new file mode 100644 index 00000000000..e91911a9a39 --- /dev/null +++ b/detection-rules/link_google_open_redirect_with_suspicious_indicators.yml @@ -0,0 +1,82 @@ +name: "Open Redirect: Google domain with /url path and suspicious indicators" +description: | + This rule examines messages containing image attachments that utilize Google's open redirect (google[.]com/url...). + To enhance accuracy and minimize false positives, the rule conducts additional assessments for suspicious indicators, as indicated in the comments. +type: "rule" +severity: "medium" +source: | + type.inbound + // All attachments are images + and length(attachments) > 0 + and all(attachments, .file_type in $file_types_images) + and sender.email.domain.root_domain not in $org_domains + + // not a reply + and ( + length(headers.references) == 0 + or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) + ) + // With a Google Redirect + and any(body.links, + .href_url.domain.sld == "google" + and .href_url.path == "/url" + and regex.contains(.href_url.query_params, "hl=.{2}&q=http(s)?://") + ) + and 2 of ( + // Not a google logo + any(attachments, + .file_type in $file_types_images + and ( + any(ml.logo_detect(.).brands, not strings.starts_with(.name, "Google")) + or any(ml.logo_detect(beta.message_screenshot()).brands, + not strings.starts_with(.name, "Google") + ) + ) + ), + // Body analysis - NLU - Credential theft + ( + any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "cred_theft" and .confidence in~ ("medium", "high") + ) + ), + // Image analysis - NLU - Credential theft language + ( + any(attachments, + .file_type in $file_types_images + and any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft") + ) + ) + ), + // Content analysis - Body - Urgency + ( + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency") + ), + + // White font is found in html raw + ( + length(body.html.display_text) < 500 + and regex.icontains(body.html.raw, + '
0 and + // There are files downloaded + length(beta.linkanalysis(.).files_downloaded) > 0 + and - // Adobe branding - beta.linkanalysis(.).credphish.brand.name == "Adobe" and - beta.linkanalysis(.).credphish.brand.confidence == "high" and + // Adobe branding + beta.linkanalysis(.).credphish.brand.name == "Adobe" + and beta.linkanalysis(.).credphish.brand.confidence == "high" + and - // Qakbot text for user coercion - any(file.explode(beta.linkanalysis(.).screenshot), - all([ - "the file is not displayed correctly", - "document password" - ], strings.icontains(..scan.ocr.raw, .)) - ) + // Qakbot text for user coercion + any(file.explode(beta.linkanalysis(.).screenshot), + all(["the file is not displayed correctly", "document password"], + strings.icontains(..scan.ocr.raw, .) + ) + ) ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) + ) tags: - "Malfam: QakBot" attack_types: diff --git a/detection-rules/link_html_smuggling_with_google_drive_branding.yml b/detection-rules/link_html_smuggling_with_google_drive_branding.yml index 9998b9f2052..0038b4ffdf7 100644 --- a/detection-rules/link_html_smuggling_with_google_drive_branding.yml +++ b/detection-rules/link_html_smuggling_with_google_drive_branding.yml @@ -7,37 +7,40 @@ references: - "https://twitter.com/pr0xylife/status/1598016053787123713" severity: "high" source: | - type.inbound and - any(body.links, - // This isn't a Google Drive link - .href_url.domain.root_domain != "google.com" and - - // There are files downloaded - length(beta.linkanalysis(.).files_downloaded) > 0 and - - // Google Drive branding - beta.linkanalysis(.).credphish.brand.name == "GoogleDrive" and - beta.linkanalysis(.).credphish.brand.confidence == "high" and + type.inbound + and length(body.links) < 10 + and any(body.links, + // This isn't a Google Drive link + .href_url.domain.root_domain != "google.com" + and - // Hi from Qakbot - any(file.explode(beta.linkanalysis(.).screenshot), - any([ - "the file is not displayed correctly", - "use local downloaded file" - ], strings.icontains(..scan.ocr.raw, .)) - ) + // There are files downloaded + length(beta.linkanalysis(.).files_downloaded) > 0 + and + + // Google Drive branding + beta.linkanalysis(.).credphish.brand.name == "GoogleDrive" + and beta.linkanalysis(.).credphish.brand.confidence == "high" + and + + // Hi from Qakbot + any(file.explode(beta.linkanalysis(.).screenshot), + any(["the file is not displayed correctly", "use local downloaded file"], + strings.icontains(..scan.ocr.raw, .) + ) + ) ) // Unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) + ) tags: - "Malfam: QakBot" attack_types: diff --git a/detection-rules/link_invoice_fake_customer_service_freemail_sender.yml b/detection-rules/link_invoice_fake_customer_service_freemail_sender.yml index 7e41ca94b07..bd50ed86d42 100644 --- a/detection-rules/link_invoice_fake_customer_service_freemail_sender.yml +++ b/detection-rules/link_invoice_fake_customer_service_freemail_sender.yml @@ -6,12 +6,19 @@ severity: "low" authors: - twitter: "vector_sec" source: | - type.inbound + type.inbound and sender.email.domain.root_domain in $free_email_providers - and any(body.links, - .display_text == "Unsubscribe" and - (length(.href_url.query_params) == 0 or .href_url.query_params is null) and - (.href_url.path == "/" or .href_url.path is null or (.href_url.domain.root_domain == "google.com" and not strings.ilike(.href_url.path, "*/forms/*"))) + and any(body.links, + .display_text == "Unsubscribe" + and (length(.href_url.query_params) == 0 or .href_url.query_params is null) + and ( + .href_url.path == "/" + or .href_url.path is null + or ( + .href_url.domain.root_domain == "google.com" + and not strings.ilike(.href_url.path, "*/forms/*") + ) + ) ) // First time sender exclusions are in place to avoid legitimate messages from known freemail senders. and sender.email.email not in $sender_emails diff --git a/detection-rules/link_ipfs_phishing.yml b/detection-rules/link_ipfs_phishing.yml index 668f3492769..bb6973c2c02 100644 --- a/detection-rules/link_ipfs_phishing.yml +++ b/detection-rules/link_ipfs_phishing.yml @@ -7,42 +7,40 @@ type: "rule" severity: "medium" source: | type.inbound - and any(body.links, - // Any body link domains contain "ipfs" - strings.icontains(.href_url.domain.domain, "ipfs") + // Any body link domains contain "ipfs" + strings.icontains(.href_url.domain.domain, "ipfs") - // Or the path contains ipfs anchored to a leading or trailing '-', '/', '.' - or ( - regex.icontains(.href_url.query_params, '[\.-/]ipfs|ipfs[\.-/]') - and .href_url.domain.domain not in $org_domains - and ( - ( + // Or the path contains ipfs anchored to a leading and trailing '-', '/', '.' + or ( + regex.icontains(.href_url.query_params, '[\.-/]ipfs[\.-/]') + and .href_url.domain.domain not in $org_domains + and ( + ( // don't include high rep domains .href_url.domain.domain not in $tranco_1m and .href_url.domain.domain not in $umbrella_1m + ) + // if it's in Tranco or Umbrella, still include it if it's one of these + or .href_url.domain.domain in $free_file_hosts + or .href_url.domain.root_domain in $free_subdomain_hosts ) - // if it's in Tranco or Umbrella, still include it if it's one of these - or .href_url.domain.domain in $free_file_hosts - or .href_url.domain.root_domain in $free_subdomain_hosts - ) - ) + ) ) // adding negation block for legitimate domains with ipfs in their name - and not sender.email.domain.domain in ("shipfsl.com") // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_login_or_captcha.yml b/detection-rules/link_login_or_captcha.yml index 28342feeed5..5e9aed2b023 100644 --- a/detection-rules/link_login_or_captcha.yml +++ b/detection-rules/link_login_or_captcha.yml @@ -5,26 +5,25 @@ type: "rule" severity: "high" source: | type.inbound + and any(body.links, - and any(body.links, - - // contains login or captcha - ( - beta.linkanalysis(.).credphish.contains_login - or beta.linkanalysis(.).credphish.contains_captcha - ) + // contains login or captcha + ( + beta.linkanalysis(.).credphish.contains_login + or beta.linkanalysis(.).credphish.contains_captcha + ) - // either the original or the redirect is a free subdomain - and ( - beta.linkanalysis(.).effective_url.domain.root_domain in $free_subdomain_hosts - or .href_url.domain.root_domain in $free_subdomain_hosts - ) + // either the original or the redirect is a free subdomain + and ( + beta.linkanalysis(.).effective_url.domain.root_domain in $free_subdomain_hosts + or .href_url.domain.root_domain in $free_subdomain_hosts + ) - // exclude FP prone free subdomain hosts - // if it's a known brand impersonation, we'll detect it in other rules - and .href_url.domain.root_domain not in ("zendesk.com") - and beta.linkanalysis(.).effective_url.domain.root_domain not in ("zendesk.com") - and beta.linkanalysis(.).effective_url.domain.domain not in ("login.squarespace.com") + // exclude FP prone free subdomain hosts + // if it's a known brand impersonation, we'll detect it in other rules + and .href_url.domain.root_domain not in ("zendesk.com") + and beta.linkanalysis(.).effective_url.domain.root_domain not in ("zendesk.com") + and beta.linkanalysis(.).effective_url.domain.domain not in ("login.squarespace.com") ) // exclude FP prone senders @@ -32,14 +31,14 @@ source: | // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_microsoft_device_code_phish.yml b/detection-rules/link_microsoft_device_code_phish.yml index 50111ea8102..6553b9b081d 100644 --- a/detection-rules/link_microsoft_device_code_phish.yml +++ b/detection-rules/link_microsoft_device_code_phish.yml @@ -18,27 +18,30 @@ source: | and sender.email.domain.root_domain not in~ ("microsoft.com", "microsoftonline.com") // Link to the device code MS pages - and any(body.links, ( - .href_url.url == "https://microsoft.com/devicelogin" or - .href_url.url == "https://login.microsoftonline.com/common/oauth2/deviceauth") + and any(body.links, + ( + .href_url.url == "https://microsoft.com/devicelogin" + or .href_url.url == "https://login.microsoftonline.com/common/oauth2/deviceauth" + ) ) // Body text references device codes and ( - strings.icontains(body.html.display_text, "device code") or - // A nine character string containing a combination of letters and characters - regex.icontains(body.html.display_text, '[\W]([A-Z0-9]{9})[\W]') + strings.icontains(body.html.display_text, "device code") + or + // A nine character string containing a combination of letters and characters + regex.icontains(body.html.display_text, '[\W]([A-Z0-9]{9})[\W]') ) // Unsolicited and ( ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails ) or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains ) ) attack_types: diff --git a/detection-rules/link_microsoft_go2_open_redirect_phish.yml b/detection-rules/link_microsoft_go2_open_redirect_phish.yml index 82d692fcfb2..086b84a39bd 100644 --- a/detection-rules/link_microsoft_go2_open_redirect_phish.yml +++ b/detection-rules/link_microsoft_go2_open_redirect_phish.yml @@ -8,20 +8,22 @@ source: | type.inbound // url path ends with go2.aspx + and any(body.links, + strings.ends_with(.href_url.path, "go2.aspx") - and any(body.links, strings.ends_with(.href_url.path, "go2.aspx") - - // query params from href_url or beta.linkanalysis contain a redirection string ending with a base64 - // pattern intended to capture an encoded email passed as an additional parameter - - and (regex.contains(.href_url.query_params, - '[a-z]=[a-z0-9-]+\.[a-z]{2,3}.+[A-Za-z0-9+/=]$|=[^=]$|={3,}$') - or regex.icontains(beta.linkanalysis(.).effective_url.query_params, - '[a-z]=[a-z0-9-]+\.[a-z]{2,3}.+[A-Za-z0-9+/=]$|=[^=]$|={3,}$')) + // query params from href_url or beta.linkanalysis contain a redirection string ending with a base64 + // pattern intended to capture an encoded email passed as an additional parameter + and ( + regex.contains(.href_url.query_params, + '[a-z]=[a-z0-9-]+\.[a-z]{2,3}.+[A-Za-z0-9+/=]$|=[^=]$|={3,}$' + ) + or regex.icontains(beta.linkanalysis(.).effective_url.query_params, + '[a-z]=[a-z0-9-]+\.[a-z]{2,3}.+[A-Za-z0-9+/=]$|=[^=]$|={3,}$' + ) + ) ) and headers.mailer is null - and regex.icontains(body.html.inner_text, - '(i͏c͏r͏os͏of͏|icrosof)|(office|o)\s?365') + and regex.icontains(body.html.inner_text, '(i͏c͏r͏os͏of͏|icrosof)|(office|o)\s?365') attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/link_microsoft_impersonation_using_hosted_png.yml b/detection-rules/link_microsoft_impersonation_using_hosted_png.yml index 56a8df0da3f..1469d86d458 100644 --- a/detection-rules/link_microsoft_impersonation_using_hosted_png.yml +++ b/detection-rules/link_microsoft_impersonation_using_hosted_png.yml @@ -14,7 +14,9 @@ source: | and sender.email.domain.root_domain not in~ ('microsoft.com', 'microsoftsupport.com', 'office.com') // logo hosted on microsoft.com - and any(body.links, regex.icontains(.display_url.url, '.{0,50}microsoft\.com\/.{0,70}logo.{0,25}\.png')) + and any(body.links, + regex.icontains(.display_url.url, '.{0,50}microsoft\.com\/.{0,70}logo.{0,25}\.png') + ) // and at least one link display text is in all caps and any(body.links, regex.icontains(.display_text, '[VIEW|CLICK|DOWNLOAD|CHECK]')) @@ -23,7 +25,10 @@ source: | and any(ml.nlu_classifier(body.html.inner_text).entities, .name == "request") // sender domain matches no body domains - and not any(body.links, .href_url.domain.root_domain == sender.email.domain.root_domain and .href_url.domain.root_domain not in $tranco_1m) + and not any(body.links, + .href_url.domain.root_domain == sender.email.domain.root_domain + and .href_url.domain.root_domain not in $tranco_1m + ) // org domain in the subject of the message and any($org_domains, strings.icontains(subject.subject, .)) diff --git a/detection-rules/link_microsoft_low_reputation.yml b/detection-rules/link_microsoft_low_reputation.yml index 8c1f579ea3e..3579bb944e5 100644 --- a/detection-rules/link_microsoft_low_reputation.yml +++ b/detection-rules/link_microsoft_low_reputation.yml @@ -6,90 +6,130 @@ source: | type.inbound // suspicious link and any(body.links, - ( - .href_url.domain.domain not in $tranco_1m or - .href_url.domain.domain in $free_file_hosts or - .href_url.domain.root_domain in $free_subdomain_hosts or - .href_url.domain.domain in $url_shorteners or + ( + .href_url.domain.root_domain not in $tranco_1m + or .href_url.domain.domain in $free_file_hosts + or .href_url.domain.root_domain in $free_subdomain_hosts + or .href_url.domain.domain in $url_shorteners + or - // mass mailer link, masks the actual URL - .href_url.domain.root_domain in ( - "hubspotlinks.com", - "mandrillapp.com", - "sendgrid.net" + // mass mailer link, masks the actual URL + .href_url.domain.root_domain in ("hubspotlinks.com", "mandrillapp.com", "sendgrid.net") + + // Google AMP redirect + or ( + .href_url.domain.sld == "google" + and strings.starts_with(.href_url.path, "/amp/") + ) + ) + + // exclude sources of potential FPs + and .href_url.domain.root_domain not in ( + "svc.ms", + "sharepoint.com", + "1drv.ms", + "microsoft.com" ) - ) - - // exclude sources of potential FPs - and .href_url.domain.root_domain not in ("svc.ms", "sharepoint.com", "1drv.ms", "microsoft.com") ) // not a reply and ( - length(headers.references) == 0 - or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) + length(headers.references) == 0 + or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To"))) ) // Microsoft logo - and ( - any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft")) - ) - or any(ml.logo_detect(beta.message_screenshot()).brands, - strings.starts_with(.name, "Microsoft") - ) + any(attachments, + .file_type in $file_types_images + and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft")) + ) + or any(ml.logo_detect(beta.message_screenshot()).brands, strings.starts_with(.name, "Microsoft")) ) // suspicious content and ( - ( - strings.ilike(body.plain.raw, "*password*", "*document*", "*voicemail*", "*cache*", "*fax*", "*storage*", "*quota*", "*messages*") - and strings.ilike(body.plain.raw, "*terminated*", "*review*", "*expire*", "*click*", "*view*", "*exceed*", "*clear*", "*only works*", "*failed*", "*deleted*") + ( + strings.ilike(body.plain.raw, + "*password*", + "*document*", + "*voicemail*", + "*cache*", + "*fax*", + "*storage*", + "*quota*", + "*messages*" ) - or ( - any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') + and strings.ilike(body.plain.raw, + "*terminated*", + "*review*", + "*expire*", + "*click*", + "*view*", + "*exceed*", + "*clear*", + "*only works*", + "*failed*", + "*deleted*" + ) + ) + or ( + any(attachments, + .file_type in $file_types_images and any(file.explode(.), - strings.ilike(.scan.ocr.raw, "*password*", "*document*", "*voicemail*", "*cache*", "*fax*", "*storage*", "*quota*", "*messages*") - and strings.ilike(.scan.ocr.raw, "*terminated*", "*review*", "*expire*", "*click*", "*view*", "*exceed*", "*clear*", "*only works*", "*failed*", "*deleted*") - ) + strings.ilike(.scan.ocr.raw, + "*password*", + "*document*", + "*voicemail*", + "*cache*", + "*fax*", + "*storage*", + "*quota*", + "*messages*" + ) + and strings.ilike(.scan.ocr.raw, + "*terminated*", + "*review*", + "*expire*", + "*click*", + "*view*", + "*exceed*", + "*clear*", + "*only works*", + "*failed*", + "*deleted*" + ) ) ) + ) ) - and ( - any(ml.nlu_classifier(body.html.inner_text).intents, - .name == "cred_theft" and .confidence in~ ("medium", "high") - ) - - or any(attachments, - .file_type in ('png', 'jpeg', 'jpg', 'bmp') - and any(file.explode(.), - any(ml.nlu_classifier(.scan.ocr.raw).intents, - .name == "cred_theft" - ) - ) - ) - - or any(ml.nlu_classifier(body.html.inner_text).entities, - .name == "urgency" + any(ml.nlu_classifier(body.html.inner_text).intents, + .name == "cred_theft" and .confidence in~ ("medium", "high") + ) + or any(attachments, + .file_type in $file_types_images + and any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, .name == "cred_theft") + ) + ) + or ( + any(ml.nlu_classifier(body.html.inner_text).entities, .name == "urgency") + and not any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "benign" and .confidence == "high" ) + ) ) - - and sender.email.domain.root_domain not in $org_domains - and sender.email.domain.root_domain not in ( - "bing.com", - "microsoft.com", - "microsoftonline.com", - "microsoftsupport.com", - "microsoft365.com", - "office.com", - "onedrive.com", - "sharepointonline.com", - "yammer.com" + "bing.com", + "microsoft.com", + "microsoftonline.com", + "microsoftsupport.com", + "microsoft365.com", + "office.com", + "onedrive.com", + "sharepointonline.com", + "yammer.com" ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_notion_file_share.yml b/detection-rules/link_notion_file_share.yml index c77e215dfca..8491cd00bac 100644 --- a/detection-rules/link_notion_file_share.yml +++ b/detection-rules/link_notion_file_share.yml @@ -7,22 +7,53 @@ type: "rule" severity: "medium" source: | type.inbound - and any(body.links, .href_url.domain.root_domain =~ 'notion.so' - and (strings.ilike(.href_url.url, '*shared*', '*document*', '*secure*', '*office*', '*important*', '*wants-to*', '*share*', '*statement*') - or strings.ilike(.display_url.url, '*shared*', '*document*', '*secure*', '*office*', '*important*', '*wants-to*', '*share*', '*statement*') - or strings.ilike(.display_text, '*shared*', '*document*', '*secure*', '*office*', '*important*', '*wants-to*', '*share*', '*statement*'))) + and any(body.links, + .href_url.domain.root_domain =~ 'notion.so' + and ( + strings.ilike(.href_url.url, + '*shared*', + '*document*', + '*secure*', + '*office*', + '*important*', + '*wants-to*', + '*share*', + '*statement*' + ) + or strings.ilike(.display_url.url, + '*shared*', + '*document*', + '*secure*', + '*office*', + '*important*', + '*wants-to*', + '*share*', + '*statement*' + ) + or strings.ilike(.display_text, + '*shared*', + '*document*', + '*secure*', + '*office*', + '*important*', + '*wants-to*', + '*share*', + '*statement*' + ) + ) + ) and sender.email.domain.domain != 'mail.notion.so' // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_office365_suspicious_app_authorization.yml b/detection-rules/link_office365_suspicious_app_authorization.yml index 8a6eceb0163..73dd96e9165 100644 --- a/detection-rules/link_office365_suspicious_app_authorization.yml +++ b/detection-rules/link_office365_suspicious_app_authorization.yml @@ -9,8 +9,10 @@ type: "rule" severity: "high" source: | type.inbound - and any(body.links, .href_url.domain.domain == 'login.microsoftonline.com' - and strings.ilike(.href_url.query_params, '*offline_access*', '*.readwrite*', '*.read*')) + and any(body.links, + .href_url.domain.domain == 'login.microsoftonline.com' + and strings.ilike(.href_url.query_params, '*offline_access*', '*.readwrite*', '*.read*') + ) attack_types: - "Credential Phishing" detection_methods: diff --git a/detection-rules/link_outlook_left_to_right_exploit.yml b/detection-rules/link_outlook_left_to_right_exploit.yml index 5de1c572dc0..7089f3c794e 100644 --- a/detection-rules/link_outlook_left_to_right_exploit.yml +++ b/detection-rules/link_outlook_left_to_right_exploit.yml @@ -6,7 +6,7 @@ references: type: "rule" severity: "medium" source: | - type.inbound + type.inbound // this regex contains a Unicode U+200E character (may not be visible in many clients) and regex.contains(body.html.raw, 'base.{0,100}‎/>') attack_types: diff --git a/detection-rules/link_qr_code_suspicious_language_fts.yml b/detection-rules/link_qr_code_suspicious_language_fts.yml index 286d56d4be6..9b000eade0c 100644 --- a/detection-rules/link_qr_code_suspicious_language_fts.yml +++ b/detection-rules/link_qr_code_suspicious_language_fts.yml @@ -10,41 +10,47 @@ source: | // check image attachments for QR code, will want to add message.screenshot functionality here when it's ready and any(attachments, - .file_type in~ ('bmp', 'png', 'jpg', 'jpeg', 'gif') - and any(file.explode(.), .scan.qr.type == "url" + .file_type in $file_types_images + and any(file.explode(.), + .scan.qr.type == "url" - // recipient email address is present in the URL, a common tactic used in credential phishing attacks and the url is not in $org_domains - and any(recipients.to, strings.icontains(..scan.qr.data, .email.email)) - and .scan.qr.url.domain.root_domain not in $org_domains - ) + // recipient email address is present in the URL, a common tactic used in credential phishing attacks and the url is not in $org_domains + and any(recipients.to, strings.icontains(..scan.qr.data, .email.email)) + and .scan.qr.url.domain.root_domain not in $org_domains + ) ) // NLU has identified cred_theft language with high confidence and ( - any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, .name == "cred_theft" and .confidence == "high") - or - // the attachment contains suspicious strings - ( - any(attachments, - .file_type in~ ('bmp', 'png', 'jpg', 'jpeg', 'gif', 'pdf') - and any(file.explode(.), - any(.scan.strings.strings, regex.icontains(., - '(\b2fa\b|\bQ.?R\.?\s?\b|MFA|Muti[ -]?Factor Auth(entication)?)')) - ) + any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "cred_theft" and .confidence == "high" + ) + or + // the attachment contains suspicious strings + ( + any(attachments, + (.file_type in $file_types_images or .file_type == "pdf") + and any(file.explode(.), + any(.scan.strings.strings, + regex.icontains(., + '(\b2fa\b|\bQ.?R\.?\s?\b|MFA|Muti[ -]?Factor Auth(entication)?)' + ) + ) ) ) + ) ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/link_undisclosed_recipients_credphish.yml b/detection-rules/link_undisclosed_recipients_credphish.yml index 12650b125a5..3b10024fcee 100644 --- a/detection-rules/link_undisclosed_recipients_credphish.yml +++ b/detection-rules/link_undisclosed_recipients_credphish.yml @@ -6,19 +6,18 @@ severity: "medium" source: | type.inbound and ( - // No Recipients - length(recipients.to) == 0 - or all(recipients.to, .display_name == "Undisclosed recipients") + // No Recipients + length(recipients.to) == 0 + or all(recipients.to, .display_name == "Undisclosed recipients") ) and length(recipients.cc) == 0 and length(recipients.bcc) == 0 and ( - any(body.links, - any([beta.linkanalysis(.)], - .credphish.disposition == "phishing" - and .credphish.confidence in ("medium", "high") - ) - ) + any(body.links, + any([beta.linkanalysis(.)], + .credphish.disposition == "phishing" and .credphish.confidence in ("medium", "high") + ) + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/lookalike_sender_domain.yml b/detection-rules/lookalike_sender_domain.yml index c36d1af53bf..95b02a44186 100644 --- a/detection-rules/lookalike_sender_domain.yml +++ b/detection-rules/lookalike_sender_domain.yml @@ -5,24 +5,23 @@ type: "rule" severity: "high" source: | type.inbound - and any($org_domains, - // this rule can be duplicated in order to tune the threshold - strings.ilevenshtein(sender.email.domain.domain, .) == 1 + // this rule can be duplicated in order to tune the threshold + strings.ilevenshtein(sender.email.domain.domain, .) == 1 ) // first-time sender and unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + and sender.email.domain.domain not in $recipient_domains + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/mass_campaign_recipient_address_new_sender.yml b/detection-rules/mass_campaign_recipient_address_new_sender.yml index 28cfdbd4ca9..92faf055f48 100644 --- a/detection-rules/mass_campaign_recipient_address_new_sender.yml +++ b/detection-rules/mass_campaign_recipient_address_new_sender.yml @@ -10,7 +10,6 @@ type: "rule" severity: "medium" source: | type.inbound - and length(recipients.to) + length(recipients.bcc) + length(recipients.cc) == 1 // exclude To: Undisclosed recipients:; @@ -19,35 +18,31 @@ source: | // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) - and ( - any(recipients.to, - strings.icontains(subject.subject, .email.email) or - strings.icontains(subject.subject, .email.local_part) - ) + any(recipients.to, + strings.icontains(subject.subject, .email.email) + or strings.icontains(subject.subject, .email.local_part) + ) ) and any([body.html.inner_text, body.plain.raw], - any(recipients.to, strings.icontains(.., .email.email)) + any(recipients.to, strings.icontains(.., .email.email)) ) - and any(body.links, - any(recipients.to, strings.icontains(..href_url.query_params, .email.email)) + and any(body.links, any(recipients.to, strings.icontains(..href_url.query_params, .email.email))) + and any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, + .name in ("cred_theft") and .confidence == "high" + ) + and any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("cred_theft") and .confidence == "high" ) - - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name in ("cred_theft") and .confidence == "high" - ) - - // we could add additional logic here, such as suspicious subject, url shortener, sus link, etc. attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/open_redirect_atdmt.yml b/detection-rules/open_redirect_atdmt.yml index 759e44ed73c..efe49b5b5f4 100644 --- a/detection-rules/open_redirect_atdmt.yml +++ b/detection-rules/open_redirect_atdmt.yml @@ -9,7 +9,9 @@ authors: severity: "medium" source: | type.inbound - and any(body.links, .href_url.domain.domain == 'ad.atdmt.com' and strings.ilike(.href_url.path, '*/c*')) + and any(body.links, + .href_url.domain.domain == 'ad.atdmt.com' and strings.ilike(.href_url.path, '*/c*') + ) attack_types: - "Credential Phishing" - "Malware/Ransomware" diff --git a/detection-rules/open_redirect_avast.yml b/detection-rules/open_redirect_avast.yml index dec9e0aa290..5ff4fcde8b6 100644 --- a/detection-rules/open_redirect_avast.yml +++ b/detection-rules/open_redirect_avast.yml @@ -5,8 +5,8 @@ severity: "medium" source: | type.inbound and any(body.links, - .href_url.domain.root_domain == "avast.com" - and strings.contains(.href_url.query_params, "DisplayRedirectCustomPage") + .href_url.domain.root_domain == "avast.com" + and strings.contains(.href_url.query_params, "DisplayRedirectCustomPage") ) and sender.email.domain.root_domain != "avast.com" and ( diff --git a/detection-rules/open_redirect_googleweblight.yml b/detection-rules/open_redirect_googleweblight.yml index 6efa7b7a8a3..d6a06881541 100644 --- a/detection-rules/open_redirect_googleweblight.yml +++ b/detection-rules/open_redirect_googleweblight.yml @@ -7,9 +7,8 @@ authors: severity: "medium" source: | type.inbound - and any(body.links, - .href_url.domain.domain == 'googleweblight.com' and - strings.ilike(.href_url.url, '*/i?u=*') + and any(body.links, + .href_url.domain.domain == 'googleweblight.com' and strings.ilike(.href_url.url, '*/i?u=*') ) attack_types: - "Credential Phishing" diff --git a/detection-rules/open_redirect_hhs.yml b/detection-rules/open_redirect_hhs.yml index 5556fe70450..8116faf98f5 100644 --- a/detection-rules/open_redirect_hhs.yml +++ b/detection-rules/open_redirect_hhs.yml @@ -8,7 +8,9 @@ severity: "medium" source: | type.inbound and any(body.links, - .href_url.domain.domain == 'dcis.hhs.gov' and strings.ilike(.href_url.query_params, '*service*')) + .href_url.domain.domain == 'dcis.hhs.gov' + and strings.ilike(.href_url.query_params, '*service*') + ) attack_types: - "Credential Phishing" - "Malware/Ransomware" diff --git a/detection-rules/open_redirect_linkedin.yml b/detection-rules/open_redirect_linkedin.yml index d5e063483f3..aae9a04e205 100644 --- a/detection-rules/open_redirect_linkedin.yml +++ b/detection-rules/open_redirect_linkedin.yml @@ -9,17 +9,20 @@ severity: "medium" source: | type.inbound and ( - ( - sender.email.domain.root_domain != "linkedin.com" - and any(body.links, .href_url.domain.root_domain == 'linkedin.com' and .href_url.path == '/slink') - and any(body.links, strings.ilike(.href_url.query_params, 'code=*')) - ) - or any(attachments, .file_type == "pdf" - and any(file.explode(.), - any(.scan.url.urls, .domain.root_domain == 'linkedin.com' and .path == '/slink') - and any(.scan.url.urls, strings.ilike(.query_params, 'code=*')) - ) + ( + sender.email.domain.root_domain != "linkedin.com" + and any(body.links, + .href_url.domain.root_domain == 'linkedin.com' and .href_url.path == '/slink' ) + and any(body.links, strings.ilike(.href_url.query_params, 'code=*')) + ) + or any(attachments, + .file_type == "pdf" + and any(file.explode(.), + any(.scan.url.urls, .domain.root_domain == 'linkedin.com' and .path == '/slink') + and any(.scan.url.urls, strings.ilike(.query_params, 'code=*')) + ) + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/open_redirect_mcgill.yml b/detection-rules/open_redirect_mcgill.yml index c11b91eb90e..46421291bb8 100644 --- a/detection-rules/open_redirect_mcgill.yml +++ b/detection-rules/open_redirect_mcgill.yml @@ -5,7 +5,9 @@ type: "rule" severity: "low" source: | type.inbound - and any(body.links, .href_url.domain.domain == 'myalumni.mcgill.ca' and .href_url.path =~ '/redirect.aspx') + and any(body.links, + .href_url.domain.domain == 'myalumni.mcgill.ca' and .href_url.path =~ '/redirect.aspx' + ) and any(body.links, strings.ilike(.href_url.query_params, '*tokenUrl=*')) and sender.email.domain.root_domain != 'mcgill.ca' attack_types: diff --git a/detection-rules/open_redirect_msn.yml b/detection-rules/open_redirect_msn.yml index ecaf61f8506..3a4325a7493 100644 --- a/detection-rules/open_redirect_msn.yml +++ b/detection-rules/open_redirect_msn.yml @@ -12,9 +12,9 @@ severity: "medium" source: | type.inbound and any(body.links, - .href_url.domain.root_domain == "msn.com" - and .href_url.path =~ "/en-gb/lifestyle/rf-best-products-uk/redirect" - and strings.icontains(.href_url.query_params, "url") + .href_url.domain.root_domain == "msn.com" + and .href_url.path =~ "/en-gb/lifestyle/rf-best-products-uk/redirect" + and strings.icontains(.href_url.query_params, "url") ) attack_types: - "Credential Phishing" diff --git a/detection-rules/open_redirect_panera_bread.yml b/detection-rules/open_redirect_panera_bread.yml index acf8a71a3ed..14078365c5e 100644 --- a/detection-rules/open_redirect_panera_bread.yml +++ b/detection-rules/open_redirect_panera_bread.yml @@ -7,6 +7,7 @@ type: "rule" severity: "medium" source: | type.inbound + and 0 < length(body.links) < 10 and any(body.links, .href_url.domain.domain == 't.e1.panerabread.com' and .href_url.path =~ '/r/') and sender.email.domain.root_domain != 'panerabread.com' attack_types: diff --git a/detection-rules/open_redirect_slack.yml b/detection-rules/open_redirect_slack.yml index f2c7632c34c..f90a0f79c2c 100644 --- a/detection-rules/open_redirect_slack.yml +++ b/detection-rules/open_redirect_slack.yml @@ -5,8 +5,12 @@ type: "rule" severity: "low" source: | type.inbound + and 0 < length(body.links) < 10 and sender.email.domain.root_domain not in~ ('atlassian.net', 'slack.com', 'soundtrap.com') - and any(body.links, .href_url.domain.domain == 'slack-redir.net' and strings.ilike(.href_url.query_params, '*url=*')) + and any(body.links, + .href_url.domain.domain == 'slack-redir.net' + and strings.ilike(.href_url.query_params, '*url=*') + ) attack_types: - "Credential Phishing" - "Malware/Ransomware" diff --git a/detection-rules/open_redirect_snapchat.yml b/detection-rules/open_redirect_snapchat.yml index 20f76e0e19d..05f28d48f0d 100644 --- a/detection-rules/open_redirect_snapchat.yml +++ b/detection-rules/open_redirect_snapchat.yml @@ -6,9 +6,9 @@ authors: - twitter: "vector_sec" severity: "medium" source: | - type.inbound and - any(body.links, .href_url.domain.domain == "click.snapchat.com") and - sender.email.domain.root_domain != "snapchat.com" + type.inbound + and any(body.links, .href_url.domain.domain == "click.snapchat.com") + and sender.email.domain.root_domain != "snapchat.com" attack_types: - "Credential Phishing" - "Malware/Ransomware" diff --git a/detection-rules/open_redirect_ticketmaster.yml b/detection-rules/open_redirect_ticketmaster.yml index 49c98050f58..62627f0cd19 100644 --- a/detection-rules/open_redirect_ticketmaster.yml +++ b/detection-rules/open_redirect_ticketmaster.yml @@ -7,7 +7,9 @@ type: "rule" severity: "medium" source: | type.inbound - and any(body.links, .href_url.domain.domain == 'links.engage.ticketmaster.com' and .href_url.path =~ '/ctt') + and any(body.links, + .href_url.domain.domain == 'links.engage.ticketmaster.com' and .href_url.path =~ '/ctt' + ) and sender.email.domain.root_domain != 'ticketmaster.com' and headers.return_path.domain.root_domain != "ticketmaster.com" attack_types: diff --git a/detection-rules/open_redirect_usapdc.yml b/detection-rules/open_redirect_usapdc.yml new file mode 100644 index 00000000000..92b69306be2 --- /dev/null +++ b/detection-rules/open_redirect_usapdc.yml @@ -0,0 +1,20 @@ +name: "Open redirect: U.S. Antarctic Program Data Center (USAP-DC)" +description: | + Message contains use of the U.S. Antarctic Program Data Center (USAP-DC) open redirect. +type: "rule" +severity: "medium" +source: | + type.inbound + and any(body.links, + .href_url.domain.root_domain == "usap-dc.org" + and .href_url.path =~ "/tracker" + and strings.starts_with(.href_url.query_params, "type=dataset&url=http") + ) +attack_types: + - "Credential Phishing" + - "Malware/Ransomware" +tactics_and_techniques: + - "Open redirect" +detection_methods: + - "URL analysis" +id: "c499d041-1e95-52a5-bc7e-857376e1a873" diff --git a/detection-rules/open_redirect_youtube.yml b/detection-rules/open_redirect_youtube.yml index 3edbb9797ee..908c6eeb252 100644 --- a/detection-rules/open_redirect_youtube.yml +++ b/detection-rules/open_redirect_youtube.yml @@ -7,7 +7,10 @@ authors: - twitter: "vector_sec" source: | type.inbound - and any(body.links, .href_url.domain.root_domain == "youtube.com" and strings.icontains(.href_url.url, "attribution_link?")) + and any(body.links, + .href_url.domain.root_domain == "youtube.com" + and strings.icontains(.href_url.url, "attribution_link?") + ) and sender.email.domain.root_domain != "youtube.com" attack_types: - "Credential Phishing" diff --git a/detection-rules/paypal_invoice_abuse.yml b/detection-rules/paypal_invoice_abuse.yml index 90549fbc2f0..84b7aa9634a 100644 --- a/detection-rules/paypal_invoice_abuse.yml +++ b/detection-rules/paypal_invoice_abuse.yml @@ -14,31 +14,33 @@ source: | and not any(headers.hops, .authentication_results.dmarc == "fail") and strings.ilike(body.html.display_text, "*seller note*") and ( - ( - //phone number but not 800 number - regex.contains(body.html.inner_text, '[\s:,-]\+?\d{1,2}[\s:,-]\(?([2-7][0-9]{2}|80[1-9]|8[1-9][0-9])\)?[\s:,-]\d{3}[\s:,-]\d{4}\b') - and ( - 4 of ( - strings.ilike(body.html.inner_text, '*you did not*'), - strings.ilike(body.html.inner_text, '*subscription*'), - strings.ilike(body.html.inner_text, '*antivirus*'), - strings.ilike(body.html.inner_text, '*order*'), - strings.ilike(body.html.inner_text, '*support*'), - strings.ilike(body.html.inner_text, '*receipt*'), - strings.ilike(body.html.inner_text, '*invoice*'), - strings.ilike(body.html.inner_text, '*call*'), - strings.ilike(body.html.inner_text, '*cancel*'), - strings.ilike(body.html.inner_text, '*renew*'), - strings.ilike(body.html.inner_text, '*refund*'), - strings.ilike(body.html.inner_text, '*+1*'), - strings.ilike(body.html.inner_text, '*help*desk*') - ) - ) - ) - or ( - //Unicode confusables words obfuscated in note - regex.contains(body.html.inner_text, '\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹') - ) + ( + // phone number but not 800 number + regex.contains(body.html.inner_text, + '[\s:,-]\+?\d{1,2}[\s:,-]\(?([2-7][0-9]{2}|80[1-9]|8[1-9][0-9])\)?[\s:,-]\d{3}[\s:,-]\d{4}\b' + ) + and ( + 4 of ( + strings.ilike(body.html.inner_text, '*you did not*'), + strings.ilike(body.html.inner_text, '*subscription*'), + strings.ilike(body.html.inner_text, '*antivirus*'), + strings.ilike(body.html.inner_text, '*order*'), + strings.ilike(body.html.inner_text, '*support*'), + strings.ilike(body.html.inner_text, '*receipt*'), + strings.ilike(body.html.inner_text, '*invoice*'), + strings.ilike(body.html.inner_text, '*call*'), + strings.ilike(body.html.inner_text, '*cancel*'), + strings.ilike(body.html.inner_text, '*renew*'), + strings.ilike(body.html.inner_text, '*refund*'), + strings.ilike(body.html.inner_text, '*+1*'), + strings.ilike(body.html.inner_text, '*help*desk*') + ) + ) + ) + or ( + // Unicode confusables words obfuscated in note + regex.contains(body.html.inner_text, '\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹') + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/punycode_sender_domain.yml b/detection-rules/punycode_sender_domain.yml index fc010ad69d5..5a56d624e3d 100644 --- a/detection-rules/punycode_sender_domain.yml +++ b/detection-rules/punycode_sender_domain.yml @@ -9,7 +9,8 @@ references: type: "rule" severity: "high" source: | - type.inbound and strings.ilike(sender.email.domain.domain, "*xn--*") + type.inbound + and strings.ilike(sender.email.domain.domain, "*xn--*") attack_types: - "Credential Phishing" - "Malware/Ransomware" diff --git a/detection-rules/recipients_undisclosed_compauth_check.yml b/detection-rules/recipients_undisclosed_compauth_check.yml index 2a6d2c4bbc8..bf7b2ffbd88 100644 --- a/detection-rules/recipients_undisclosed_compauth_check.yml +++ b/detection-rules/recipients_undisclosed_compauth_check.yml @@ -4,34 +4,28 @@ type: "rule" severity: "medium" source: | type.inbound - and ( - length(recipients.to) == 0 - or all(recipients.to, .display_name == "Undisclosed recipients") - ) + and (length(recipients.to) == 0 or all(recipients.to, .display_name == "Undisclosed recipients")) and length(recipients.cc) == 0 and length(recipients.bcc) == 0 and 2 of ( - ( - any(headers.hops, - .authentication_results.compauth.verdict is not null - and .authentication_results.compauth.verdict not in ("pass", "softpass") - ) - ), - ( - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name in ("bec", "cred_theft") - and .confidence == "high" - ) - ), - ( - any(body.links, - any([beta.linkanalysis(.)], - .credphish.disposition == "phishing" - and .credphish.confidence in ("high") - ) + ( + any(headers.hops, + .authentication_results.compauth.verdict is not null + and .authentication_results.compauth.verdict not in ("pass", "softpass") + ) + ), + ( + any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("bec", "cred_theft") and .confidence == "high" + ) + ), + ( + any(body.links, + any([beta.linkanalysis(.)], + .credphish.disposition == "phishing" and .credphish.confidence in ("high") ) ) + ) ) detection_methods: - "Content analysis" diff --git a/detection-rules/recipients_undisclosed_free_subdomain_host.yml b/detection-rules/recipients_undisclosed_free_subdomain_host.yml index 192c3709b64..0554bc90112 100644 --- a/detection-rules/recipients_undisclosed_free_subdomain_host.yml +++ b/detection-rules/recipients_undisclosed_free_subdomain_host.yml @@ -5,18 +5,32 @@ type: "rule" severity: "medium" source: | type.inbound - - and any(body.links, - .href_url.domain.root_domain in $free_subdomain_hosts - and .href_url.domain.subdomain is not null - and .href_url.domain.subdomain != "www" - ) - and ( - length(recipients.to) == 0 - or all(recipients.to, .display_name == "Undisclosed recipients") + and any(body.links, + .href_url.domain.root_domain in $free_subdomain_hosts + and .href_url.domain.subdomain is not null + and .href_url.domain.subdomain != "www" ) + and (length(recipients.to) == 0 or all(recipients.to, .display_name == "Undisclosed recipients")) and length(recipients.cc) == 0 and length(recipients.bcc) == 0 + + // negate listmailers & benign threads + and not ( + any(headers.hops, any(.fields, .name == "List-Unsubscribe")) + or any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "benign" and .confidence == "high" + ) + ) + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + ) tactics_and_techniques: - "Free subdomain host" detection_methods: diff --git a/detection-rules/recipients_undisclosed_nlu_cred_theft_low_rep_links.yml b/detection-rules/recipients_undisclosed_nlu_cred_theft_low_rep_links.yml index 50ab9cacd78..6c0073e7007 100644 --- a/detection-rules/recipients_undisclosed_nlu_cred_theft_low_rep_links.yml +++ b/detection-rules/recipients_undisclosed_nlu_cred_theft_low_rep_links.yml @@ -4,25 +4,20 @@ type: "rule" severity: "medium" source: | type.inbound - and ( - length(recipients.to) == 0 - or all(recipients.to, .display_name == "Undisclosed recipients") - ) + and (length(recipients.to) == 0 or all(recipients.to, .display_name == "Undisclosed recipients")) and length(recipients.cc) == 0 and length(recipients.bcc) == 0 - and any(body.links, .href_url.domain.domain not in $tranco_1m) - + and any(body.links, .href_url.domain.root_domain not in $tranco_1m) and ( - any(body.links, regex.icontains(.display_text, - '(view|click|download|goto)?(attachment|download|file|online|document)s?') + any(body.links, + regex.icontains(.display_text, + '(view|click|download|goto)?(attachment|download|file|online|document)s?' + ) or all(body.links, regex.contains(.display_text, "^[A-Z ]+$")) - ) + ) ) - - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name in ("cred_theft") - and .confidence in ("medium", "high") + and any(ml.nlu_classifier(body.current_thread.text).intents, + .name in ("cred_theft") and .confidence in ("medium", "high") ) attack_types: - "Credential Phishing" diff --git a/detection-rules/sender_new_from_domain_first_time_sender.yml b/detection-rules/sender_new_from_domain_first_time_sender.yml index 61bf772d666..ba5fbdbf256 100644 --- a/detection-rules/sender_new_from_domain_first_time_sender.yml +++ b/detection-rules/sender_new_from_domain_first_time_sender.yml @@ -7,14 +7,14 @@ source: | type.inbound and beta.whois(sender.email.domain).days_old <= 10 and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) tags: - "Attack surface reduction" diff --git a/detection-rules/spam_campaign_excessive_display_text_with_keywords.yml b/detection-rules/spam_campaign_excessive_display_text_with_keywords.yml index ad1dbaa3f82..55e02712629 100644 --- a/detection-rules/spam_campaign_excessive_display_text_with_keywords.yml +++ b/detection-rules/spam_campaign_excessive_display_text_with_keywords.yml @@ -8,22 +8,19 @@ severity: "low" source: | type.inbound and length(body.links) > 0 - and any(body.links, length(.display_text) >3000) - - and any( - body.links, regex.icontains(.display_text, '(\bPassword:)', 'Hi.{0,5}Welcome\b') - ) + and any(body.links, length(.display_text) > 3000) + and any(body.links, regex.icontains(.display_text, '(\bPassword:)', 'Hi.{0,5}Welcome\b')) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + ) attack_types: - "Spam" detection_methods: diff --git a/detection-rules/spam_new_domain_emojis.yml b/detection-rules/spam_new_domain_emojis.yml new file mode 100644 index 00000000000..8b01256663d --- /dev/null +++ b/detection-rules/spam_new_domain_emojis.yml @@ -0,0 +1,45 @@ +name: "Spam: New link domain (<=10d) and emojis" +description: | + Detects spam from freemail senders, where the linked domain is less than 10 days old and emojis present. +type: "rule" +severity: "medium" +source: | + type.inbound + + // sender is a freemail + and sender.email.domain.root_domain in $free_email_providers + + // linked domain is less than 10 days old + and any(body.links, beta.whois(.href_url.domain).days_old < 10) + + // has an emoji in the subject or body + and ( + regex.contains(body.plain.raw, + '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}]' + ) + or regex.contains(subject.subject, + '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}]' + ) + ) + + // first-time sender + and ( + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) + ) +attack_types: + - "Spam" +tactics_and_techniques: + - "Free email provider" +detection_methods: + - "Content analysis" + - "Sender analysis" + - "URL analysis" + - "Whois" +id: "33677993-9c21-54e6-8633-e03b2063e332" diff --git a/detection-rules/spam_url_shortener_emojis.yml b/detection-rules/spam_url_shortener_emojis.yml index 9e06b64f841..e793b36b770 100644 --- a/detection-rules/spam_url_shortener_emojis.yml +++ b/detection-rules/spam_url_shortener_emojis.yml @@ -10,30 +10,31 @@ source: | and sender.email.domain.root_domain in $free_email_providers // has a URL shortener - and any(body.links, - .href_url.domain.root_domain in $url_shorteners - ) + and any(body.links, .href_url.domain.root_domain in $url_shorteners) // short body, basically just the URL and length(body.plain.raw) < 100 // has an emoji in the subject or body and ( - regex.contains(body.plain.raw, '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}]') - or regex.contains(subject.subject, '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}]') - + regex.contains(body.plain.raw, + '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}]' + ) + or regex.contains(subject.subject, + '[\x{1F300}-\x{1F5FF}\x{1F600}-\x{1F64F}\x{1F680}-\x{1F6FF}\x{1F700}-\x{1F77F}\x{1F780}-\x{1F7FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{2300}-\x{23FF}]' + ) ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) attack_types: - "Spam" diff --git a/detection-rules/spoof_dropbox.yml b/detection-rules/spoof_dropbox.yml index 32e7d3076d6..e7b73da04f8 100644 --- a/detection-rules/spoof_dropbox.yml +++ b/detection-rules/spoof_dropbox.yml @@ -6,7 +6,9 @@ severity: "medium" source: | type.inbound and sender.email.domain.root_domain == 'dropbox.com' - and any(distinct(headers.hops, .authentication_results.dmarc is not null), strings.ilike(.authentication_results.dmarc, "*fail")) + and any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) // mitigates situations where an ESG misconfiguration could cause auth failures and not strings.ends_with(headers.message_id, ".dropbox.com>") attack_types: diff --git a/detection-rules/spoofable_internal_domain_suspicious_signals.yml b/detection-rules/spoofable_internal_domain_suspicious_signals.yml index d9c07b3caf2..442aa897331 100644 --- a/detection-rules/spoofable_internal_domain_suspicious_signals.yml +++ b/detection-rules/spoofable_internal_domain_suspicious_signals.yml @@ -16,61 +16,62 @@ source: | // doesn't match an org display name (generic) // we could make this more generic later and sender.display_name not in $org_display_names - and any(headers.hops, - // find the hop Authentication-results for the org domain - .authentication_results.dmarc_details.from.domain in $org_domains + // find the hop Authentication-results for the org domain + .authentication_results.dmarc_details.from.domain in $org_domains - // internal domain is spoofable - and .authentication_results.dmarc_details.verdict == "none" - and .authentication_results.spf == "none" - and .authentication_results.compauth.verdict not in ("pass", "softpass") + // internal domain is spoofable + and .authentication_results.dmarc_details.verdict == "none" + and .authentication_results.spf == "none" + and .authentication_results.compauth.verdict not in ("pass", "softpass") ) - and 3 of ( - ( - // low reputation / suspicious link - any(body.links, - .href_url.domain.root_domain not in $org_domains - and ( - .href_url.domain.root_domain not in $tranco_1m - or .href_url.domain.domain in $free_file_hosts - or .href_url.domain.root_domain in $free_subdomain_hosts - or .href_url.domain.domain in $url_shorteners - ) - + ( + // low reputation / suspicious link + any(body.links, + .href_url.domain.root_domain not in $org_domains + and ( + .href_url.domain.root_domain not in $tranco_1m + or .href_url.domain.domain in $free_file_hosts + or .href_url.domain.root_domain in $free_subdomain_hosts + or .href_url.domain.domain in $url_shorteners ) - ), - ( - // sender domain matches no body domains - length(body.links) > 0 - and all(body.links, + ) + ), + ( + // sender domain matches no body domains + length(body.links) > 0 + and all(body.links, .href_url.domain.root_domain != sender.email.domain.root_domain and .href_url.domain.root_domain not in $org_domains - ) - ), - ( - // suspicious domain in headers - any(headers.domains, - // it's not an org domain - .root_domain not in $org_domains + ) + ), + ( + // suspicious domain in headers + any(headers.domains, + // it's not an org domain + .root_domain not in $org_domains - // low reputation - and .root_domain not in $alexa_1m - - // no one has sent an email to it before - and .root_domain not in $recipient_domains - ) - ), - ( - // suspicious language - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name != "benign" and .confidence == "high" - ) - ), + // low reputation + and .root_domain not in $alexa_1m + // no one has sent an email to it before + and .root_domain not in $recipient_domains + ) + ), + ( + // suspicious language + any(ml.nlu_classifier(body.current_thread.text).intents, + .name != "benign" and .confidence == "high" + ) + ), + ( + // suspicious language + any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, + .name != "benign" and .confidence == "high" + ) + ), ) tags: - "Attack surface reduction" diff --git a/detection-rules/stripe_invoice_abuse.yml b/detection-rules/stripe_invoice_abuse.yml index 673d28d72b2..a0bc1e14d57 100644 --- a/detection-rules/stripe_invoice_abuse.yml +++ b/detection-rules/stripe_invoice_abuse.yml @@ -6,22 +6,22 @@ description: | type: "rule" severity: "medium" source: | - type.inbound + type.inbound and length(attachments) == 2 and sender.email.domain.root_domain == "stripe.com" and any(headers.hops, .authentication_results.dmarc == "pass") - - and any(attachments, .file_extension == "pdf" - and any(file.explode(.), - length(filter(.scan.strings.strings, strings.ilike(., - "*Btc Purchase*", - "*suspicious activity*", - "*get in touch with us straight once*", - "*your phone number*", - "*due deducted*", - "*merchant security service center*", - ))) >= 4 - ) + and any(attachments, + .file_extension == "pdf" + and any(file.explode(.), + 4 of ( + strings.ilike(.scan.ocr.raw, "*Btc Purchase*"), + strings.ilike(.scan.ocr.raw, "*suspicious activity*"), + strings.ilike(.scan.ocr.raw, "*get in touch with us straight once*"), + strings.ilike(.scan.ocr.raw, "*your phone number*"), + strings.ilike(.scan.ocr.raw, "*due deducted*"), + strings.ilike(.scan.ocr.raw, "*merchant security service center*"), + ) + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/suspicious_request_for_quote_html_smuggling.yml b/detection-rules/suspicious_request_for_quote_html_smuggling.yml index 616f8ce02c5..68ad24bda48 100644 --- a/detection-rules/suspicious_request_for_quote_html_smuggling.yml +++ b/detection-rules/suspicious_request_for_quote_html_smuggling.yml @@ -9,57 +9,54 @@ source: | // RFP/RFQ language and 1 of ( - ( - regex.icontains(coalesce(body.html.display_text, body.plain.raw), '(discuss.{0,15}purchas(e|ing))') - ), - ( - regex.icontains(coalesce(body.html.display_text, body.plain.raw), '(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)') - ), - ( - regex.icontains(coalesce(body.html.display_text, body.plain.raw), '(please|kindly).{0,30}quote') - ), - ( - regex.icontains(subject.subject, '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)') - ), - ( - any(attachments, regex.icontains(.file_name, "(purchase.?order|Quot(e|ation))")) - ), - ( - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities, .name == "request") - and - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities,.name == "urgency") - ), - ( - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).tags,.name == "purchase_order" and .confidence == "high") - ) + regex.icontains(body.current_thread.text, + '(discuss.{0,15}purchas(e|ing))' + ), + regex.icontains(body.current_thread.text, + '(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)' + ), + regex.icontains(body.current_thread.text, '(please|kindly).{0,30}quote'), + regex.icontains(subject.subject, '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)'), + any(attachments, regex.icontains(.file_name, "(purchase.?order|Quot(e|ation))")), + any(ml.nlu_classifier(body.current_thread.text).entities, + .name == "request" + ) + and any(ml.nlu_classifier(body.current_thread.text).entities, + .name == "urgency" + ), + any(ml.nlu_classifier(body.current_thread.text).tags, + .name == "purchase_order" and .confidence == "high" + ) ) // HTML smuggling - and any(attachments, - ( - .file_extension in~ ("html", "htm", "shtml", "dhtml") or - .file_extension in~ $file_extensions_common_archives or - .file_type == "html" - ) - and any(file.explode(.), + and any(attachments, ( - length(filter(.scan.javascript.identifiers, strings.like (., "document", "write", "atob"))) == 3 - // usage: document['write'](atob) - or any(.scan.strings.strings, strings.ilike(., "*document*write*atob*")) - // usage: some_var = atob(); - or any(.scan.strings.strings, strings.ilike(., "*=*atob*;")) - // usage: obfuscating "atob" - or any(.scan.javascript.identifiers, strings.ilike(., '*ato\u0062*')) - // usage: document.head.insertAdjacentHTML("beforeend", atob(... - or - any(.scan.strings.strings, strings.ilike(., - "*document*write*atob*", - "*document*insertAdjacentHTML*atob*")) + .file_extension in~ ("html", "htm", "shtml", "dhtml") + or .file_extension in~ $file_extensions_common_archives + or .file_type == "html" + ) + and any(file.explode(.), + ( + length(filter(.scan.javascript.identifiers, + strings.like(., "document", "write", "atob") + ) + ) == 3 + // usage: document['write'](atob) + or any(.scan.strings.strings, strings.ilike(., "*document*write*atob*")) + // usage: some_var = atob(); + or any(.scan.strings.strings, strings.ilike(., "*=*atob*;")) + // usage: obfuscating "atob" + or any(.scan.javascript.identifiers, strings.ilike(., '*ato\u0062*')) + // usage: document.head.insertAdjacentHTML("beforeend", atob(... + or any(.scan.strings.strings, + strings.ilike(., + "*document*write*atob*", + "*document*insertAdjacentHTML*atob*" + ) + ) + ) ) - ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/suspicious_request_for_quote_or_purchase.yml b/detection-rules/suspicious_request_for_quote_or_purchase.yml index 32845806c39..c7b6a9593ed 100644 --- a/detection-rules/suspicious_request_for_quote_or_purchase.yml +++ b/detection-rules/suspicious_request_for_quote_or_purchase.yml @@ -5,50 +5,46 @@ description: | type: "rule" severity: "medium" source: | - type.inbound + type.inbound and 1 of ( - ( - ( - length(recipients.to) == 0 or - all(recipients.to, .display_name == "Undisclosed recipients") - ) - and length(recipients.cc) == 0 - and length(recipients.bcc) == 0 - ), - ( - sender.email.domain.root_domain in $free_email_providers - and any(headers.reply_to, .email.email != sender.email.email) - and any(headers.reply_to, .email.email not in $recipient_emails) - ) + ( + (length(recipients.to) == 0 or all(recipients.to, .display_name == "Undisclosed recipients")) + and length(recipients.cc) == 0 + and length(recipients.bcc) == 0 + ), + ( + sender.email.domain.root_domain in $free_email_providers + and any(headers.reply_to, .email.email != sender.email.email) + and any(headers.reply_to, .email.email not in $recipient_emails) + ) ) - and 2 of ( - ( - regex.icontains(coalesce(body.html.display_text, body.plain.raw), '(discuss.{0,15}purchas(e|ing))') - ), - ( - regex.icontains(coalesce(body.html.display_text, body.plain.raw), '(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)') - ), - ( - regex.icontains(coalesce(body.html.display_text, body.plain.raw), '(please|kindly).{0,30}quote') - ), - ( - regex.icontains(subject.subject, '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)') - ), - ( - any(attachments, regex.icontains(.file_name, "(purchase.?order|Quot(e|ation))")) - ), - ( - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities, .name == "request") - and - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).entities,.name == "urgency") - ), - ( - any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).tags,.name == "purchase_order" and .confidence == "high") + ( + regex.icontains(coalesce(body.html.display_text, body.plain.raw), + '(discuss.{0,15}purchas(e|ing))' ) + ), + ( + regex.icontains(coalesce(body.html.display_text, body.plain.raw), + '(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)' + ) + ), + (regex.icontains(coalesce(body.html.display_text, body.plain.raw), '(please|kindly).{0,30}quote')), + (regex.icontains(subject.subject, '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)')), + (any(attachments, regex.icontains(.file_name, "(purchase.?order|Quot(e|ation))"))), + ( + any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).entities, + .name == "request" + ) + and any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).entities, + .name == "urgency" + ) + ), + ( + any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).tags, + .name == "purchase_order" and .confidence == "high" + ) + ) ) attack_types: - "BEC/Fraud" diff --git a/detection-rules/suspicious_shipping_notification.yml b/detection-rules/suspicious_shipping_notification.yml index 3d1f34b6141..e28ad6e655c 100644 --- a/detection-rules/suspicious_shipping_notification.yml +++ b/detection-rules/suspicious_shipping_notification.yml @@ -7,19 +7,24 @@ source: | type.inbound // contains at least 1 link and length(body.links) > 0 - and 3 of ( - strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*(1)*"), - strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*waiting for delivery*"), - strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*delivery missed*"), - strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*tracking number*") + strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*(1)*"), + strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*waiting for delivery*"), + strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*delivery missed*"), + strings.ilike(coalesce(body.html.display_text, body.plain.raw), "*tracking number*") ) // urgent/time-sensitive language - and any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).entities, .name == "urgency") + and any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).entities, + .name == "urgency" + ) // email is not personalized with recipients name - and any(recipients.to, any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).entities, .text == ..email.local_part)) + and any(recipients.to, + any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).entities, + .text == ..email.local_part + ) + ) attack_types: - "Credential Phishing" - "Spam" diff --git a/detection-rules/uri_handler_search_ms.yml b/detection-rules/uri_handler_search_ms.yml index 3743df9390d..b5bc6a0e34f 100644 --- a/detection-rules/uri_handler_search_ms.yml +++ b/detection-rules/uri_handler_search_ms.yml @@ -10,11 +10,10 @@ type: "rule" severity: "high" source: | type.inbound - and any(attachments, .file_type == "html" + and any(attachments, + .file_type == "html" and any(file.explode(.), - any(.scan.strings.strings, - regex.contains(., 'search-ms:query.*location:\\\\') - ) + any(.scan.strings.strings, regex.contains(., 'search-ms:query.*location:\\\\')) ) ) attack_types: diff --git a/detection-rules/urlhaus_malicious_dom_in_body_or_pdf.yml b/detection-rules/urlhaus_malicious_dom_in_body_or_pdf.yml index f5f22f7b46a..7a39b636ba1 100644 --- a/detection-rules/urlhaus_malicious_dom_in_body_or_pdf.yml +++ b/detection-rules/urlhaus_malicious_dom_in_body_or_pdf.yml @@ -5,44 +5,45 @@ severity: "medium" source: | type.inbound and ( - any(body.links, - // filter potentially known good domains - // prevents FPs on entries such as drive[.]google[.]com, or - // other accidental pushes to the List - .href_url.domain.domain not in $free_file_hosts and - .href_url.domain.domain not in $tranco_1m and - .href_url.domain.domain not in $umbrella_1m and - - // this ensures we don't flag on legit FQDNs that - // aren't in the Tranco 1M, but their root domains are - // eg: support[.]google[.]com - .href_url.domain.root_domain not in $tranco_1m and - .href_url.domain.root_domain not in $umbrella_1m and - .href_url.domain.root_domain not in $free_subdomain_hosts and + any(body.links, + // filter potentially known good domains + // prevents FPs on entries such as drive[.]google[.]com, or + // other accidental pushes to the List + .href_url.domain.domain not in $free_file_hosts + and .href_url.domain.domain not in $tranco_1m + and .href_url.domain.domain not in $umbrella_1m + and - .href_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters - ) - or any(attachments, .file_type == "pdf" - and any(file.explode(.), - any(.scan.pdf.urls, - // filter potentially known good domains - // prevents FPs on entries such as drive[.]google[.]com, or - // other accidental pushes to the List - .domain.domain not in $free_file_hosts and - .domain.domain not in $free_subdomain_hosts and - .domain.domain not in $tranco_1m and - .domain.domain not in $umbrella_1m and + // this ensures we don't flag on legit FQDNs that + // aren't in the Tranco 1M, but their root domains are + // eg: support[.]google[.]com + .href_url.domain.root_domain not in $tranco_1m + and .href_url.domain.root_domain not in $umbrella_1m + and .href_url.domain.root_domain not in $free_subdomain_hosts + and .href_url.domain.root_domain in $abuse_ch_urlhaus_domains_trusted_reporters + ) + or any(attachments, + .file_type == "pdf" + and any(file.explode(.), + any(.scan.pdf.urls, + // filter potentially known good domains + // prevents FPs on entries such as drive[.]google[.]com, or + // other accidental pushes to the List + .domain.domain not in $free_file_hosts + and .domain.domain not in $free_subdomain_hosts + and .domain.domain not in $tranco_1m + and .domain.domain not in $umbrella_1m + and - // this ensures we don't flag on legit FQDNs that - // aren't in the Tranco 1M, but their root domains are - // eg: support[.]google[.]com - .domain.root_domain not in $tranco_1m and - .domain.root_domain not in $umbrella_1m and - - .domain.domain in $abuse_ch_urlhaus_domains_trusted_reporters - ) - ) - ) + // this ensures we don't flag on legit FQDNs that + // aren't in the Tranco 1M, but their root domains are + // eg: support[.]google[.]com + .domain.root_domain not in $tranco_1m + and .domain.root_domain not in $umbrella_1m + and .domain.domain in $abuse_ch_urlhaus_domains_trusted_reporters + ) + ) + ) ) tags: - "Abusech: URLhaus" diff --git a/detection-rules/vip_impersonation_attack_surface_reduction.yml b/detection-rules/vip_impersonation_attack_surface_reduction.yml index 7b1babdc6ee..34f8fe317c9 100644 --- a/detection-rules/vip_impersonation_attack_surface_reduction.yml +++ b/detection-rules/vip_impersonation_attack_surface_reduction.yml @@ -12,38 +12,37 @@ type: "rule" severity: "high" source: | type.inbound - and any($org_vips, .display_name == sender.display_name) - and ( - // ignore personal <> work emails - // where the sender and mailbox's display name are the same - length(recipients.to) > 1 or length(recipients.cc) > 1 - or sender.display_name != mailbox.display_name + // ignore personal <> work emails + // where the sender and mailbox's display name are the same + length(recipients.to) > 1 + or length(recipients.cc) > 1 + or sender.display_name != mailbox.display_name ) // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $sender_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $sender_domains + ) ) // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Attack surface reduction" diff --git a/discovery-rules/attachment_any_eml.yml b/discovery-rules/attachment_any_eml.yml index 2f89130a4bd..a679cfd4a98 100644 --- a/discovery-rules/attachment_any_eml.yml +++ b/discovery-rules/attachment_any_eml.yml @@ -7,6 +7,5 @@ authors: - twitter: "und3rf10w" source: | type.inbound - and any(attachments, - .file_extension in~ ('eml') - ) + and any(attachments, .file_extension =~ 'eml') + diff --git a/discovery-rules/attachment_suspicious_macro.yml b/discovery-rules/attachment_suspicious_macro.yml index 9889e45ea8f..104e5592972 100644 --- a/discovery-rules/attachment_suspicious_macro.yml +++ b/discovery-rules/attachment_suspicious_macro.yml @@ -4,9 +4,24 @@ description: | type: "rule" source: | type.inbound - and any(attachments, .file_extension in~ ("doc", "docm", "docx", "dot", "dotm", "pptm", "ppsm", "xlm", "xls", "xlsb", "xlsm", "xlt", "xltm") - and ml.macro_classifier(.).malicious - and ml.macro_classifier(.).confidence in ("low", "medium", "high") + and any(attachments, + .file_extension in~ ( + "doc", + "docm", + "docx", + "dot", + "dotm", + "pptm", + "ppsm", + "xlm", + "xls", + "xlsb", + "xlsm", + "xlt", + "xltm" + ) + and ml.macro_classifier(.).malicious + and ml.macro_classifier(.).confidence in ("low", "medium", "high") ) tags: - "Suspicious attachment" diff --git a/discovery-rules/attachment_with_free_subdomain_host_unsolicited.yml b/discovery-rules/attachment_with_free_subdomain_host_unsolicited.yml index a08e89838d3..cf44a8835dd 100644 --- a/discovery-rules/attachment_with_free_subdomain_host_unsolicited.yml +++ b/discovery-rules/attachment_with_free_subdomain_host_unsolicited.yml @@ -6,23 +6,27 @@ description: | type: "rule" source: | type.inbound - and any(attachments, .file_extension in~ ("pdf") - and any(file.explode(.), - any(.scan.url.urls, .domain.root_domain in $free_subdomain_hosts - and .domain.subdomain is not null - and .domain.subdomain != "www" - and .domain.domain != "sts.amazonaws.com" - and .domain.root_domain != "zendesk.com")) + and any(attachments, + .file_extension in~ ("pdf") + and any(file.explode(.), + any(.scan.url.urls, + .domain.root_domain in $free_subdomain_hosts + and .domain.subdomain is not null + and .domain.subdomain != "www" + and .domain.domain != "sts.amazonaws.com" + and .domain.root_domain != "zendesk.com" + ) + ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Suspicious attachment" diff --git a/discovery-rules/attachment_with_url_shortener_unsolicited.yml b/discovery-rules/attachment_with_url_shortener_unsolicited.yml index 1b620eae1a2..3eb8801dc5a 100644 --- a/discovery-rules/attachment_with_url_shortener_unsolicited.yml +++ b/discovery-rules/attachment_with_url_shortener_unsolicited.yml @@ -4,19 +4,19 @@ description: | type: "rule" source: | type.inbound - and any(attachments, .file_extension in~ ("pdf") - and any(file.explode(.), - any(.scan.url.urls, .domain.root_domain in $url_shorteners)) + and any(attachments, + .file_extension in~ ("pdf") + and any(file.explode(.), any(.scan.url.urls, .domain.root_domain in $url_shorteners)) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Suspicious attachment" diff --git a/discovery-rules/impersonation_dmarc_failure_high_cred_phish_conclusion.yml b/discovery-rules/impersonation_dmarc_failure_high_cred_phish_conclusion.yml index 8a49da15d7a..9a3232e8b74 100644 --- a/discovery-rules/impersonation_dmarc_failure_high_cred_phish_conclusion.yml +++ b/discovery-rules/impersonation_dmarc_failure_high_cred_phish_conclusion.yml @@ -4,11 +4,11 @@ type: "rule" severity: "high" source: | type.inbound - and any(distinct(headers.hops, .authentication_results.dmarc is not null), strings.ilike(.authentication_results.dmarc, "*fail")) - and any(ml.nlu_classifier(coalesce( - body.html.display_text, body.plain.raw)).intents, - .name in ("cred_theft") - and .confidence == "high" + and any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + and any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).intents, + .name in ("cred_theft") and .confidence == "high" ) tags: - "Brand impersonation" diff --git a/discovery-rules/impersonation_github_sawfish.yml b/discovery-rules/impersonation_github_sawfish.yml index 7be38dc9928..9a7aaf84a83 100644 --- a/discovery-rules/impersonation_github_sawfish.yml +++ b/discovery-rules/impersonation_github_sawfish.yml @@ -13,44 +13,59 @@ source: | or headers.return_path.domain.root_domain != 'github.com' ) and 2 of ( - regex.icontains(body.plain.raw, '.*account activity.*', '.*your activity.*', '.*suspicious api call.*'), - regex.icontains(body.html.inner_text, '.*account activity.*', '.*your activity.*', '.*suspicious api call.*'), - regex.icontains(subject.subject, '.*account activity.*', '.*your activity.*', '.*suspicious api call.*') + regex.icontains(body.plain.raw, + '.*account activity.*', + '.*your activity.*', + '.*suspicious api call.*' + ), + regex.icontains(body.html.inner_text, + '.*account activity.*', + '.*your activity.*', + '.*suspicious api call.*' + ), + regex.icontains(subject.subject, + '.*account activity.*', + '.*your activity.*', + '.*suspicious api call.*' + ) ) and 1 of ( strings.ilike(sender.display_name, '*github*'), strings.ilike(sender.email.email, '*github*'), strings.ilike(subject.subject, '*github*') - ) - or any(body.links, .href_url.domain.root_domain in - ('secure-git.org', - 'auth-glthub.com', - 'secure-glthub.com', - 'githb.net', - 'github-team.com', - 'githubb.net', - 'aws-update.net', - 'corp-github.com', - 'ensure-https.com', - 'git-hub.co', - 'git-secure-service.in', - 'githb.co', - 'glt-app.net', - 'glt-hub.com', - 'glthub.co', - 'glthub.info', - 'glthub.net', - 'glthubb.info', - 'glthube.app', - 'glthubs.com', - 'glthubs.info', - 'glthubs.net', - 'glthubse.info', - 'slack-app.net', - 'ssl-connection.net', - 'sso-github.com', - 'sts-github.com', - 'tsl-github.com')) + ) + or any(body.links, + .href_url.domain.root_domain in ( + 'secure-git.org', + 'auth-glthub.com', + 'secure-glthub.com', + 'githb.net', + 'github-team.com', + 'githubb.net', + 'aws-update.net', + 'corp-github.com', + 'ensure-https.com', + 'git-hub.co', + 'git-secure-service.in', + 'githb.co', + 'glt-app.net', + 'glt-hub.com', + 'glthub.co', + 'glthub.info', + 'glthub.net', + 'glthubb.info', + 'glthube.app', + 'glthubs.com', + 'glthubs.info', + 'glthubs.net', + 'glthubse.info', + 'slack-app.net', + 'ssl-connection.net', + 'sso-github.com', + 'sts-github.com', + 'tsl-github.com' + ) + ) and sender.email.email not in $recipient_emails tags: - "Brand impersonation" diff --git a/discovery-rules/invoice_from_freemail_sender.yml b/discovery-rules/invoice_from_freemail_sender.yml index c96433c412b..1b85e6d8f3f 100644 --- a/discovery-rules/invoice_from_freemail_sender.yml +++ b/discovery-rules/invoice_from_freemail_sender.yml @@ -9,14 +9,14 @@ source: | and sender.email.domain.root_domain in $free_email_providers // Unsolicited (has my organization ever sent an email to this sender?) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) - or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains - ) + ( + sender.email.domain.root_domain in $free_email_providers + and sender.email.email not in $recipient_emails + ) + or ( + sender.email.domain.root_domain not in $free_email_providers + and sender.email.domain.domain not in $recipient_domains + ) ) tags: - "Invoice fraud" diff --git a/discovery-rules/outbound_to_disposable.yml b/discovery-rules/outbound_to_disposable.yml index 29a62a837a7..a8ddfac6e1c 100644 --- a/discovery-rules/outbound_to_disposable.yml +++ b/discovery-rules/outbound_to_disposable.yml @@ -4,14 +4,22 @@ description: | type: "rule" severity: "low" source: | - type.outbound and - any([recipients.to, recipients.cc, recipients.bcc], - any(., .email.domain.domain in $disposable_email_providers and + type.outbound + and any([recipients.to, recipients.cc, recipients.bcc], + any(., + .email.domain.domain in $disposable_email_providers + and - // once lists can be updated from Feeds, we can drop this, - // as the update has been made to the upstream disposable list - .email.domain.root_domain not in ("craigslist.org", "gmai.com", "gmal.com", "gmial.com", "spamarrest.com") - ) + // once lists can be updated from Feeds, we can drop this, + // as the update has been made to the upstream disposable list + .email.domain.root_domain not in ( + "craigslist.org", + "gmai.com", + "gmal.com", + "gmial.com", + "spamarrest.com" + ) + ) ) tags: - "DLP" diff --git a/discovery-rules/url_shortener_from_suspicious_sender_tld.yml b/discovery-rules/url_shortener_from_suspicious_sender_tld.yml index a9c4338c761..227159d5264 100644 --- a/discovery-rules/url_shortener_from_suspicious_sender_tld.yml +++ b/discovery-rules/url_shortener_from_suspicious_sender_tld.yml @@ -6,10 +6,10 @@ severity: "low" source: | type.inbound and sender.email.domain.tld in $suspicious_tlds - and any(body.links, - .href_url.domain.domain in $url_shorteners - // exempting legitimate Google Maps shortener - and not strings.ilike(.href_url.url, "http?://goo.gl/maps*") + and any(body.links, + .href_url.domain.domain in $url_shorteners + // exempting legitimate Google Maps shortener + and not strings.ilike(.href_url.url, "http?://goo.gl/maps*") ) and sender.email.email not in $recipient_emails tags: diff --git a/insights/attachments/malware_bazaar.yml b/insights/attachments/malware_bazaar.yml new file mode 100644 index 00000000000..ec3a443a929 --- /dev/null +++ b/insights/attachments/malware_bazaar.yml @@ -0,0 +1,6 @@ +name: "MalwareBazaar: Malicious attachment hash (trusted reporters)" +type: "query" +source: map(filter(attachments, (.sha256 in $abuse_ch_malwarebazaar_sha256_trusted_reporters)), .file_name) +severity: "high" +tags: + - "Attachments" diff --git a/insights/headers/utc_offset.yml b/insights/headers/utc_offset.yml new file mode 100644 index 00000000000..758befd7fa1 --- /dev/null +++ b/insights/headers/utc_offset.yml @@ -0,0 +1,7 @@ +name: "UTC offset of sender" +type: "query" +source: | + headers.date_original_offset +severity: "informational" +tags: + - "Headers"