From 254c6cb884899bc450da1191a5f24d709f28eef4 Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Tue, 3 Oct 2023 14:01:54 -0700 Subject: [PATCH 01/16] Updating Rule: attachment_docusign_image_suspicious_links.yml (#761) Co-authored-by: Sam Scholten --- ...chment_docusign_image_suspicious_links.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/detection-rules/attachment_docusign_image_suspicious_links.yml b/detection-rules/attachment_docusign_image_suspicious_links.yml index 514b82554c1..32fae6b6654 100644 --- a/detection-rules/attachment_docusign_image_suspicious_links.yml +++ b/detection-rules/attachment_docusign_image_suspicious_links.yml @@ -27,12 +27,23 @@ source: | ) and ( ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails + ( + 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 ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + sender.email.email in $sender_emails + and any(distinct(headers.hops, .received_spf.verdict is not null), + regex.icontains(.received_spf.verdict, "fail|error") + or any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) ) ) attack_types: From 8369b78f608d6f23f281372edb1552c980dc6b14 Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Wed, 4 Oct 2023 10:46:56 -0700 Subject: [PATCH 02/16] Updating rule: attachment_microsoft_image_lure_qr_code.yml (#812) Co-authored-by: Sam Scholten --- .../attachment_microsoft_image_lure_qr_code.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/detection-rules/attachment_microsoft_image_lure_qr_code.yml b/detection-rules/attachment_microsoft_image_lure_qr_code.yml index 7b024a35f89..8ad0f0d1947 100644 --- a/detection-rules/attachment_microsoft_image_lure_qr_code.yml +++ b/detection-rules/attachment_microsoft_image_lure_qr_code.yml @@ -7,13 +7,18 @@ source: | type.inbound and ( any(attachments, - .file_type in $file_types_images + (.file_type in $file_types_images or .file_type == "pdf") 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")) + or (any(attachments, .file_type in~ $file_extensions_macros)) ) and any(attachments, - .file_type in $file_types_images + ( + .file_type in $file_types_images + or .file_type == "pdf" + or .file_type in $file_extensions_macros + ) and ( any(file.explode(.), regex.icontains(.scan.ocr.raw, 'scan|camera') @@ -72,6 +77,7 @@ attack_types: - "Credential Phishing" tactics_and_techniques: - "Impersonation: Brand" + - "PDF" - "QR code" - "Social engineering" detection_methods: From 9b20913cebe372cfc883546dc2a94f692ace38c6 Mon Sep 17 00:00:00 2001 From: Sam Scholten Date: Wed, 4 Oct 2023 18:39:28 -0400 Subject: [PATCH 03/16] Sender Profiles: Prevalence and Past behavior (#815) Co-authored-by: Cameron Dunn Co-authored-by: Josh Kamdjou --- .../attachment_adobe_image_lure_fts.yml | 9 +++----- ...chment_any_html_in_archive_unsolicited.yml | 9 +++----- .../attachment_any_html_new_sender.yml | 11 +++------- .../attachment_any_html_unsolicited.yml | 11 +++------- .../attachment_callback_phish_with_img.yml | 9 +++----- .../attachment_callback_phish_with_pdf.yml | 9 +++----- ...chment_docusign_image_suspicious_links.yml | 21 ++++--------------- ...achment_dropbox_image_suspicious_links.yml | 9 +++----- detection-rules/attachment_eml_cred_theft.yml | 11 +++------- .../attachment_eml_with_html_attachment.yml | 11 +++------- ...hment_emotet_heavily_padded_doc_in_zip.yml | 9 +++----- .../attachment_encrypted_ole_unsolicited.yml | 9 +++----- .../attachment_html_attachment_login_page.yml | 10 +++------ ...ment_html_smuggling_double_encoded_zip.yml | 9 +++----- ...chment_html_smuggling_microsoft_signin.yml | 9 +++----- .../attachment_js_file_execution.yml | 10 +++------ detection-rules/attachment_malwarebazaar.yml | 9 +++----- .../attachment_mht_embedded_vbscript.yml | 11 +++------- ...ttachment_microsoft_image_lure_qr_code.yml | 10 +++------ .../attachment_office365_image.yml | 10 +++------ ...nt_office_file_relationship_cred_theft.yml | 9 +++----- .../attachment_pdf_link_to_dmg.yml | 12 +++-------- ...pdf_linking_to_password_protected_file.yml | 9 +++----- ...ow_reputation_link_to_suspicious_files.yml | 10 +++------ ...f_with_low_reputation_link_to_zip_file.yml | 10 +++------ ...tachment_qr_code_suspicious_components.yml | 2 -- .../attachment_soliciting_enable_macros.yml | 9 +++----- ...suspicious_vba_macro_first_time_sender.yml | 9 +++----- .../attachment_svg_embedded_js.yml | 11 +++------- ...chment_vba_macro_auto_exec_unsolicited.yml | 9 +++----- ...chment_vba_macro_auto_open_unsolicited.yml | 9 +++----- ...hment_vba_macro_employee_impersonation.yml | 9 +++----- .../attachment_vba_macro_high_risk.yml | 9 +++----- ...achment_with_encrypted_zip_unsolicited.yml | 9 +++----- ...ent_with_suspicious_author_unsolicited.yml | 9 +++----- ...with_unknown_encrypted_zip_unsolicited.yml | 9 +++----- ...y_business_email_compromise_new_sender.yml | 10 +++------ ..._business_email_compromise_unsolicited.yml | 11 +++------- .../body_callback_phishing_no_attachment.yml | 9 +++----- detection-rules/body_job_scam_new_sender.yml | 9 +++----- ...lback_phishing_nlu_body_or_attachments.yml | 9 +++----- ...ing_link_from_suspicious_sender_domain.yml | 9 +++----- .../file_sharing_link_suspicious_subject.yml | 9 +++----- ...d_recipients_no_links_freemail_replyto.yml | 9 +++----- ...headers_replyto_new_domain_nlu_request.yml | 11 +++------- .../headers_russia_return_path.yml | 9 +++----- .../impersonation_amazon_suspicious_text.yml | 10 +++------ detection-rules/impersonation_barracuda.yml | 14 +++++-------- detection-rules/impersonation_chase.yml | 13 +++++------- detection-rules/impersonation_dhl.yml | 10 +++------ detection-rules/impersonation_docusign.yml | 10 +++------ .../impersonation_employee_payroll_fraud.yml | 9 +++----- .../impersonation_employee_subject.yml | 10 +++------ .../impersonation_employee_urgent_request.yml | 11 +++------- ...hread_mismatched_from_freemail_replyto.yml | 11 +++------- detection-rules/impersonation_finra.yml | 11 +++------- detection-rules/impersonation_github.yml | 9 +++----- .../impersonation_human_resources.yml | 9 +++----- detection-rules/impersonation_microsoft.yml | 11 +++------- detection-rules/impersonation_paypal.yml | 11 +++------- .../impersonation_recipient_domain.yml | 10 +++------ ...tion_recipient_sld_in_sender_local_fts.yml | 9 +++----- detection-rules/impersonation_ripple.yml | 9 +++----- detection-rules/impersonation_spotify.yml | 10 +++------ detection-rules/impersonation_stellar.yml | 9 +++----- .../impersonation_sublime_security.yml | 10 +++------ .../impersonation_vip_urgent_request.yml | 10 +++------ detection-rules/inline_image_as_message.yml | 9 +++----- detection-rules/link_credential_phishing.yml | 10 +++------ ...l_phishing_intent_and_other_indicators.yml | 11 +++------- ...ink_credential_phishing_secure_message.yml | 11 +++------- ...hing_suspicious_sender_tld_and_signals.yml | 10 +++------ ...credential_phishing_voicemail_language.yml | 9 +++----- ...k_download_disk_image_in_encrypted_zip.yml | 10 +++------ .../link_download_suspicious_file.yml | 10 +++------ .../link_fake_fax_low_reputation.yml | 11 +++------- .../link_google_apps_script_macro.yml | 10 +++------ detection-rules/link_google_translate.yml | 9 +++----- ...ink_html_smuggling_with_adobe_branding.yml | 10 +++------ ...l_smuggling_with_google_drive_branding.yml | 10 +++------ ..._fake_customer_service_freemail_sender.yml | 1 - detection-rules/link_ipfs_phishing.yml | 10 +++------ detection-rules/link_login_or_captcha.yml | 11 +++------- .../link_microsoft_device_code_phish.yml | 11 +++------- ...crosoft_impersonation_using_hosted_png.yml | 11 +++------- ...k_new_domain_in_link_first_time_sender.yml | 9 +++----- detection-rules/link_notion_file_share.yml | 11 +++------- .../link_qr_code_suspicious_language_fts.yml | 10 +++------ ...icious_language_undisclosed_recipients.yml | 10 +++------ ..._campaign_recipient_address_new_sender.yml | 11 +++------- detection-rules/open_redirect_avast.yml | 9 +++----- ...pients_undisclosed_free_subdomain_host.yml | 9 +++----- ...nder_new_from_domain_first_time_sender.yml | 9 +++----- ...n_excessive_display_text_with_keywords.yml | 10 +++------ detection-rules/spam_new_domain_emojis.yml | 11 +++------- detection-rules/spam_url_shortener_emojis.yml | 11 +++------- ...impersonation_attack_surface_reduction.yml | 20 ++++++------------ 97 files changed, 293 insertions(+), 672 deletions(-) diff --git a/detection-rules/attachment_adobe_image_lure_fts.yml b/detection-rules/attachment_adobe_image_lure_fts.yml index 78125362de3..1c222cd97d9 100644 --- a/detection-rules/attachment_adobe_image_lure_fts.yml +++ b/detection-rules/attachment_adobe_image_lure_fts.yml @@ -20,13 +20,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_any_html_in_archive_unsolicited.yml b/detection-rules/attachment_any_html_in_archive_unsolicited.yml index ddf0659e54e..f7ab205f57a 100644 --- a/detection-rules/attachment_any_html_in_archive_unsolicited.yml +++ b/detection-rules/attachment_any_html_in_archive_unsolicited.yml @@ -14,13 +14,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_any_html_new_sender.yml b/detection-rules/attachment_any_html_new_sender.yml index cc22e73e915..117804f24ce 100644 --- a/detection-rules/attachment_any_html_new_sender.yml +++ b/detection-rules/attachment_any_html_new_sender.yml @@ -11,16 +11,11 @@ severity: "medium" source: | type.inbound 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_any_html_unsolicited.yml b/detection-rules/attachment_any_html_unsolicited.yml index 075feda5569..c5549895fd3 100644 --- a/detection-rules/attachment_any_html_unsolicited.yml +++ b/detection-rules/attachment_any_html_unsolicited.yml @@ -11,16 +11,11 @@ severity: "low" source: | type.inbound 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_callback_phish_with_img.yml b/detection-rules/attachment_callback_phish_with_img.yml index e9ce44623c7..19c4f46b120 100644 --- a/detection-rules/attachment_callback_phish_with_img.yml +++ b/detection-rules/attachment_callback_phish_with_img.yml @@ -10,13 +10,10 @@ severity: "high" source: | type.inbound and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) and sender.email.domain.root_domain in $free_email_providers diff --git a/detection-rules/attachment_callback_phish_with_pdf.yml b/detection-rules/attachment_callback_phish_with_pdf.yml index 1b6f24a320b..e707ca72c80 100644 --- a/detection-rules/attachment_callback_phish_with_pdf.yml +++ b/detection-rules/attachment_callback_phish_with_pdf.yml @@ -8,13 +8,10 @@ severity: "high" source: | type.inbound and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) diff --git a/detection-rules/attachment_docusign_image_suspicious_links.yml b/detection-rules/attachment_docusign_image_suspicious_links.yml index 32fae6b6654..7d802543568 100644 --- a/detection-rules/attachment_docusign_image_suspicious_links.yml +++ b/detection-rules/attachment_docusign_image_suspicious_links.yml @@ -26,24 +26,11 @@ source: | ) ) 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 - ) - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.email in $sender_emails - and any(distinct(headers.hops, .received_spf.verdict is not null), - regex.icontains(.received_spf.verdict, "fail|error") - or any(distinct(headers.hops, .authentication_results.dmarc is not null), - strings.ilike(.authentication_results.dmarc, "*fail") - ) - ) + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) ) attack_types: diff --git a/detection-rules/attachment_dropbox_image_suspicious_links.yml b/detection-rules/attachment_dropbox_image_suspicious_links.yml index 1de0a856b31..478744466bc 100644 --- a/detection-rules/attachment_dropbox_image_suspicious_links.yml +++ b/detection-rules/attachment_dropbox_image_suspicious_links.yml @@ -14,13 +14,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_eml_cred_theft.yml b/detection-rules/attachment_eml_cred_theft.yml index a85a54f7777..d3b647aa504 100644 --- a/detection-rules/attachment_eml_cred_theft.yml +++ b/detection-rules/attachment_eml_cred_theft.yml @@ -29,16 +29,11 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_eml_with_html_attachment.yml b/detection-rules/attachment_eml_with_html_attachment.yml index 68fac95489f..f719bf69097 100644 --- a/detection-rules/attachment_eml_with_html_attachment.yml +++ b/detection-rules/attachment_eml_with_html_attachment.yml @@ -40,16 +40,11 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: 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 b23bcff7ba2..0f1e36c18ac 100644 --- a/detection-rules/attachment_emotet_heavily_padded_doc_in_zip.yml +++ b/detection-rules/attachment_emotet_heavily_padded_doc_in_zip.yml @@ -19,13 +19,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_encrypted_ole_unsolicited.yml b/detection-rules/attachment_encrypted_ole_unsolicited.yml index 6e591479b56..10df0004afc 100644 --- a/detection-rules/attachment_encrypted_ole_unsolicited.yml +++ b/detection-rules/attachment_encrypted_ole_unsolicited.yml @@ -13,13 +13,10 @@ source: | and file.oletools(.).indicators.encryption.exists ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_html_attachment_login_page.yml b/detection-rules/attachment_html_attachment_login_page.yml index 6f720efda3f..0f513c19103 100644 --- a/detection-rules/attachment_html_attachment_login_page.yml +++ b/detection-rules/attachment_html_attachment_login_page.yml @@ -68,15 +68,11 @@ source: | ) ) ) - // Unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_html_smuggling_double_encoded_zip.yml b/detection-rules/attachment_html_smuggling_double_encoded_zip.yml index d1d56ea9890..0d7374033c7 100644 --- a/detection-rules/attachment_html_smuggling_double_encoded_zip.yml +++ b/detection-rules/attachment_html_smuggling_double_encoded_zip.yml @@ -13,13 +13,10 @@ authors: source: | type.inbound and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) and any(attachments, diff --git a/detection-rules/attachment_html_smuggling_microsoft_signin.yml b/detection-rules/attachment_html_smuggling_microsoft_signin.yml index 5bc76594293..ec988219191 100644 --- a/detection-rules/attachment_html_smuggling_microsoft_signin.yml +++ b/detection-rules/attachment_html_smuggling_microsoft_signin.yml @@ -25,13 +25,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) // allow Microsoft domains just to be safe diff --git a/detection-rules/attachment_js_file_execution.yml b/detection-rules/attachment_js_file_execution.yml index 642e8a53016..788d141ed21 100644 --- a/detection-rules/attachment_js_file_execution.yml +++ b/detection-rules/attachment_js_file_execution.yml @@ -15,15 +15,11 @@ source: | ) ) ) - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_malwarebazaar.yml b/detection-rules/attachment_malwarebazaar.yml index 96091611291..b8b6025bcd1 100644 --- a/detection-rules/attachment_malwarebazaar.yml +++ b/detection-rules/attachment_malwarebazaar.yml @@ -6,13 +6,10 @@ source: | type.inbound and any(attachments, .sha256 in $abuse_ch_malwarebazaar_sha256_trusted_reporters) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_mht_embedded_vbscript.yml b/detection-rules/attachment_mht_embedded_vbscript.yml index dd75945472b..7820e2b3caa 100644 --- a/detection-rules/attachment_mht_embedded_vbscript.yml +++ b/detection-rules/attachment_mht_embedded_vbscript.yml @@ -14,16 +14,11 @@ source: | and any(file.explode(.), .file_extension =~ "mht") and any(file.explode(.), any(.scan.html.scripts, .language == "VBScript")) ) - - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_microsoft_image_lure_qr_code.yml b/detection-rules/attachment_microsoft_image_lure_qr_code.yml index 8ad0f0d1947..f130fcdcaaa 100644 --- a/detection-rules/attachment_microsoft_image_lure_qr_code.yml +++ b/detection-rules/attachment_microsoft_image_lure_qr_code.yml @@ -61,15 +61,11 @@ source: | and sender.email.domain.domain == "microsoft.com" ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) diff --git a/detection-rules/attachment_office365_image.yml b/detection-rules/attachment_office365_image.yml index 012788a6b7a..9622f79a11f 100644 --- a/detection-rules/attachment_office365_image.yml +++ b/detection-rules/attachment_office365_image.yml @@ -54,15 +54,11 @@ source: | and sender.email.domain.domain in ("microsoft.com", "sharepointonline.com") ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_office_file_relationship_cred_theft.yml b/detection-rules/attachment_office_file_relationship_cred_theft.yml index bf5dd44065f..f7735b69322 100644 --- a/detection-rules/attachment_office_file_relationship_cred_theft.yml +++ b/detection-rules/attachment_office_file_relationship_cred_theft.yml @@ -23,13 +23,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_pdf_link_to_dmg.yml b/detection-rules/attachment_pdf_link_to_dmg.yml index da3da87d685..81874a50ef1 100644 --- a/detection-rules/attachment_pdf_link_to_dmg.yml +++ b/detection-rules/attachment_pdf_link_to_dmg.yml @@ -39,17 +39,11 @@ source: | ) ) ) - - - // first time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_pdf_linking_to_password_protected_file.yml b/detection-rules/attachment_pdf_linking_to_password_protected_file.yml index ee11e2e24b8..14cc93e7b84 100644 --- a/detection-rules/attachment_pdf_linking_to_password_protected_file.yml +++ b/detection-rules/attachment_pdf_linking_to_password_protected_file.yml @@ -19,13 +19,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_pdf_with_low_reputation_link_to_suspicious_files.yml b/detection-rules/attachment_pdf_with_low_reputation_link_to_suspicious_files.yml index c89d21b1247..1b322cbc3a6 100644 --- a/detection-rules/attachment_pdf_with_low_reputation_link_to_suspicious_files.yml +++ b/detection-rules/attachment_pdf_with_low_reputation_link_to_suspicious_files.yml @@ -17,15 +17,11 @@ source: | ) ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_pdf_with_low_reputation_link_to_zip_file.yml b/detection-rules/attachment_pdf_with_low_reputation_link_to_zip_file.yml index b198d9f3d6b..d7e2cc43fe0 100644 --- a/detection-rules/attachment_pdf_with_low_reputation_link_to_zip_file.yml +++ b/detection-rules/attachment_pdf_with_low_reputation_link_to_zip_file.yml @@ -18,15 +18,11 @@ source: | ) ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/attachment_qr_code_suspicious_components.yml b/detection-rules/attachment_qr_code_suspicious_components.yml index bb2a94dfca4..c081611dfd6 100644 --- a/detection-rules/attachment_qr_code_suspicious_components.yml +++ b/detection-rules/attachment_qr_code_suspicious_components.yml @@ -55,8 +55,6 @@ source: | ) ) ) - - // first time sender and ( ( sender.email.domain.root_domain in $free_email_providers diff --git a/detection-rules/attachment_soliciting_enable_macros.yml b/detection-rules/attachment_soliciting_enable_macros.yml index 3ba77138bc1..c502919588b 100644 --- a/detection-rules/attachment_soliciting_enable_macros.yml +++ b/detection-rules/attachment_soliciting_enable_macros.yml @@ -19,13 +19,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_suspicious_vba_macro_first_time_sender.yml b/detection-rules/attachment_suspicious_vba_macro_first_time_sender.yml index c76d0b80421..5cc38d278ec 100644 --- a/detection-rules/attachment_suspicious_vba_macro_first_time_sender.yml +++ b/detection-rules/attachment_suspicious_vba_macro_first_time_sender.yml @@ -11,13 +11,10 @@ source: | and ml.macro_classifier(.).confidence in ("high") ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_svg_embedded_js.yml b/detection-rules/attachment_svg_embedded_js.yml index 0daca577a33..1bb935303aa 100644 --- a/detection-rules/attachment_svg_embedded_js.yml +++ b/detection-rules/attachment_svg_embedded_js.yml @@ -21,16 +21,11 @@ source: | and any(.scan.strings.strings, strings.icontains(., "CDATA")) ) ) - - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml b/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml index 37e28fd0864..8cc39d8b582 100644 --- a/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml +++ b/detection-rules/attachment_vba_macro_auto_exec_unsolicited.yml @@ -14,13 +14,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) diff --git a/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml b/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml index 15d1abef2b1..7bbe7543329 100644 --- a/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml +++ b/detection-rules/attachment_vba_macro_auto_open_unsolicited.yml @@ -15,13 +15,10 @@ source: | and any(file.explode(.), any(.scan.vba.auto_exec, . == "AutoOpen")) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_vba_macro_employee_impersonation.yml b/detection-rules/attachment_vba_macro_employee_impersonation.yml index 56297c4fc66..ac8d8b2fbba 100644 --- a/detection-rules/attachment_vba_macro_employee_impersonation.yml +++ b/detection-rules/attachment_vba_macro_employee_impersonation.yml @@ -21,13 +21,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_vba_macro_high_risk.yml b/detection-rules/attachment_vba_macro_high_risk.yml index 87e0802a0d1..8b9ab322c5e 100644 --- a/detection-rules/attachment_vba_macro_high_risk.yml +++ b/detection-rules/attachment_vba_macro_high_risk.yml @@ -12,13 +12,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_with_encrypted_zip_unsolicited.yml b/detection-rules/attachment_with_encrypted_zip_unsolicited.yml index 02c3d167ed8..e21351fe9b1 100644 --- a/detection-rules/attachment_with_encrypted_zip_unsolicited.yml +++ b/detection-rules/attachment_with_encrypted_zip_unsolicited.yml @@ -12,13 +12,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_with_suspicious_author_unsolicited.yml b/detection-rules/attachment_with_suspicious_author_unsolicited.yml index b1a0aefa868..29e1e71901e 100644 --- a/detection-rules/attachment_with_suspicious_author_unsolicited.yml +++ b/detection-rules/attachment_with_suspicious_author_unsolicited.yml @@ -13,13 +13,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml b/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml index ea490e8480e..badc0f2862d 100644 --- a/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml +++ b/detection-rules/attachment_with_unknown_encrypted_zip_unsolicited.yml @@ -16,13 +16,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/body_business_email_compromise_new_sender.yml b/detection-rules/body_business_email_compromise_new_sender.yml index 16fb9df2d5f..ffec5179bee 100644 --- a/detection-rules/body_business_email_compromise_new_sender.yml +++ b/detection-rules/body_business_email_compromise_new_sender.yml @@ -21,15 +21,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/body_business_email_compromise_unsolicited.yml b/detection-rules/body_business_email_compromise_unsolicited.yml index a3181b43bd8..2eb2383c0c6 100644 --- a/detection-rules/body_business_email_compromise_unsolicited.yml +++ b/detection-rules/body_business_email_compromise_unsolicited.yml @@ -42,16 +42,11 @@ source: | ) ) ) - - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) diff --git a/detection-rules/body_callback_phishing_no_attachment.yml b/detection-rules/body_callback_phishing_no_attachment.yml index b946d070b17..b4a1caf7d3d 100644 --- a/detection-rules/body_callback_phishing_no_attachment.yml +++ b/detection-rules/body_callback_phishing_no_attachment.yml @@ -9,13 +9,10 @@ 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) and sender.email.domain.root_domain in $free_email_providers diff --git a/detection-rules/body_job_scam_new_sender.yml b/detection-rules/body_job_scam_new_sender.yml index e8f38c799a2..9d002d17203 100644 --- a/detection-rules/body_job_scam_new_sender.yml +++ b/detection-rules/body_job_scam_new_sender.yml @@ -11,13 +11,10 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/callback_phishing_nlu_body_or_attachments.yml b/detection-rules/callback_phishing_nlu_body_or_attachments.yml index 2eaa5c00728..b5b1f1a0c7f 100644 --- a/detection-rules/callback_phishing_nlu_body_or_attachments.yml +++ b/detection-rules/callback_phishing_nlu_body_or_attachments.yml @@ -25,13 +25,10 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: 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 025a1355b86..09b81756466 100644 --- a/detection-rules/file_sharing_link_from_suspicious_sender_domain.yml +++ b/detection-rules/file_sharing_link_from_suspicious_sender_domain.yml @@ -8,13 +8,10 @@ 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/file_sharing_link_suspicious_subject.yml b/detection-rules/file_sharing_link_suspicious_subject.yml index 88d8b23f04c..09ed51da703 100644 --- a/detection-rules/file_sharing_link_suspicious_subject.yml +++ b/detection-rules/file_sharing_link_suspicious_subject.yml @@ -18,13 +18,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: 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 f255d1269da..4970785d8d3 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 @@ -16,13 +16,10 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) 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 ca6fcd540c8..c26b16bc096 100644 --- a/detection-rules/headers_replyto_new_domain_nlu_request.yml +++ b/detection-rules/headers_replyto_new_domain_nlu_request.yml @@ -24,16 +24,11 @@ source: | .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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/headers_russia_return_path.yml b/detection-rules/headers_russia_return_path.yml index a1aa279d27f..2daabd83ce5 100644 --- a/detection-rules/headers_russia_return_path.yml +++ b/detection-rules/headers_russia_return_path.yml @@ -8,13 +8,10 @@ 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_amazon_suspicious_text.yml b/detection-rules/impersonation_amazon_suspicious_text.yml index 018882fa9dc..e2c7744ad7e 100644 --- a/detection-rules/impersonation_amazon_suspicious_text.yml +++ b/detection-rules/impersonation_amazon_suspicious_text.yml @@ -33,15 +33,11 @@ source: | ) ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) and sender.email.domain.root_domain not in~ ( diff --git a/detection-rules/impersonation_barracuda.yml b/detection-rules/impersonation_barracuda.yml index ac9b348cb8c..76987ffe608 100644 --- a/detection-rules/impersonation_barracuda.yml +++ b/detection-rules/impersonation_barracuda.yml @@ -20,16 +20,12 @@ source: | 'sharkssports.net', 'sjbarracuda.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 - ) + profile.by_sender().prevalence in ("new", "outlier") + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_chase.yml b/detection-rules/impersonation_chase.yml index 40990223d26..15a8108ef0b 100644 --- a/detection-rules/impersonation_chase.yml +++ b/detection-rules/impersonation_chase.yml @@ -24,14 +24,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) ) attack_types: - "Credential Phishing" diff --git a/detection-rules/impersonation_dhl.yml b/detection-rules/impersonation_dhl.yml index 3fee425bae3..99d9d08539b 100644 --- a/detection-rules/impersonation_dhl.yml +++ b/detection-rules/impersonation_dhl.yml @@ -24,15 +24,11 @@ source: | '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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_docusign.yml b/detection-rules/impersonation_docusign.yml index 07d58391c7a..cfb1539a93b 100644 --- a/detection-rules/impersonation_docusign.yml +++ b/detection-rules/impersonation_docusign.yml @@ -51,15 +51,11 @@ source: | ) 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_employee_payroll_fraud.yml b/detection-rules/impersonation_employee_payroll_fraud.yml index 253133f8f10..108b809ed80 100644 --- a/detection-rules/impersonation_employee_payroll_fraud.yml +++ b/detection-rules/impersonation_employee_payroll_fraud.yml @@ -25,13 +25,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_employee_subject.yml b/detection-rules/impersonation_employee_subject.yml index 1897f23e05d..7704a421d80 100644 --- a/detection-rules/impersonation_employee_subject.yml +++ b/detection-rules/impersonation_employee_subject.yml @@ -15,15 +15,11 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_employee_urgent_request.yml b/detection-rules/impersonation_employee_urgent_request.yml index 3f6978174c4..e8d2abda54a 100644 --- a/detection-rules/impersonation_employee_urgent_request.yml +++ b/detection-rules/impersonation_employee_urgent_request.yml @@ -23,16 +23,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: 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 126d35c2cd8..ec61e357ec8 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 @@ -8,16 +8,11 @@ type: "rule" severity: "medium" source: | type.inbound - - // First-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) diff --git a/detection-rules/impersonation_finra.yml b/detection-rules/impersonation_finra.yml index 8922f317c38..65c10058643 100644 --- a/detection-rules/impersonation_finra.yml +++ b/detection-rules/impersonation_finra.yml @@ -12,16 +12,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_github.yml b/detection-rules/impersonation_github.yml index 8b3b3e79a5f..7606ceab8ff 100644 --- a/detection-rules/impersonation_github.yml +++ b/detection-rules/impersonation_github.yml @@ -29,13 +29,10 @@ source: | 'lithub.com' ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_human_resources.yml b/detection-rules/impersonation_human_resources.yml index 96c9e0d6bdc..00516688e71 100644 --- a/detection-rules/impersonation_human_resources.yml +++ b/detection-rules/impersonation_human_resources.yml @@ -18,13 +18,10 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_microsoft.yml b/detection-rules/impersonation_microsoft.yml index 19f7c44aa24..d67692062f6 100644 --- a/detection-rules/impersonation_microsoft.yml +++ b/detection-rules/impersonation_microsoft.yml @@ -42,16 +42,11 @@ source: | 'office.com', 'teams-events.com' ) - - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) diff --git a/detection-rules/impersonation_paypal.yml b/detection-rules/impersonation_paypal.yml index f8c180384a7..dfb3d3f7e8e 100644 --- a/detection-rules/impersonation_paypal.yml +++ b/detection-rules/impersonation_paypal.yml @@ -52,16 +52,11 @@ source: | 'paypal-prepaid.com', 'xoom.com' ) - - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_recipient_domain.yml b/detection-rules/impersonation_recipient_domain.yml index d02e2a84f81..89a05768ac4 100644 --- a/detection-rules/impersonation_recipient_domain.yml +++ b/detection-rules/impersonation_recipient_domain.yml @@ -32,15 +32,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: 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 193fc25d260..53985558905 100644 --- a/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml +++ b/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml @@ -27,13 +27,10 @@ source: | ) and sender.email.domain.root_domain not in $org_domains and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_ripple.yml b/detection-rules/impersonation_ripple.yml index da3450cfb57..b3ddee751d1 100644 --- a/detection-rules/impersonation_ripple.yml +++ b/detection-rules/impersonation_ripple.yml @@ -11,13 +11,10 @@ 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/impersonation_spotify.yml b/detection-rules/impersonation_spotify.yml index cfddbc55737..c1fe24ce78d 100644 --- a/detection-rules/impersonation_spotify.yml +++ b/detection-rules/impersonation_spotify.yml @@ -20,15 +20,11 @@ source: | '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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_stellar.yml b/detection-rules/impersonation_stellar.yml index 0a6c3a65b1e..9cea84869ec 100644 --- a/detection-rules/impersonation_stellar.yml +++ b/detection-rules/impersonation_stellar.yml @@ -11,13 +11,10 @@ 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/impersonation_sublime_security.yml b/detection-rules/impersonation_sublime_security.yml index 092022258c8..e69db5c1101 100644 --- a/detection-rules/impersonation_sublime_security.yml +++ b/detection-rules/impersonation_sublime_security.yml @@ -12,15 +12,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/impersonation_vip_urgent_request.yml b/detection-rules/impersonation_vip_urgent_request.yml index a0b24a6fd91..13f1a9ab7a9 100644 --- a/detection-rules/impersonation_vip_urgent_request.yml +++ b/detection-rules/impersonation_vip_urgent_request.yml @@ -15,15 +15,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/inline_image_as_message.yml b/detection-rules/inline_image_as_message.yml index ce0948fce12..d9cdfc3b964 100644 --- a/detection-rules/inline_image_as_message.yml +++ b/detection-rules/inline_image_as_message.yml @@ -21,13 +21,10 @@ source: | ) and strings.ilike(body.html.raw, "*img*cid*") and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_credential_phishing.yml b/detection-rules/link_credential_phishing.yml index 214ae9fda81..08e9ef5f47e 100644 --- a/detection-rules/link_credential_phishing.yml +++ b/detection-rules/link_credential_phishing.yml @@ -9,15 +9,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: 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 c564026ff9a..a9ecc3b8de4 100644 --- a/detection-rules/link_credential_phishing_intent_and_other_indicators.yml +++ b/detection-rules/link_credential_phishing_intent_and_other_indicators.yml @@ -296,16 +296,11 @@ source: | // doesn't match any links in the body or all(body.links, .href_url.domain.root_domain != sender.email.domain.root_domain) ) - - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_credential_phishing_secure_message.yml b/detection-rules/link_credential_phishing_secure_message.yml index 60f0fe56787..1960d5ee9e5 100644 --- a/detection-rules/link_credential_phishing_secure_message.yml +++ b/detection-rules/link_credential_phishing_secure_message.yml @@ -29,16 +29,11 @@ source: | // Negate known secure mailer(s) and not all(body.links, .href_url.domain.root_domain in ("mimecast.com")) ) - - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: 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 f8d7ac3732c..a0019a6fe00 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 @@ -44,15 +44,11 @@ source: | 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_credential_phishing_voicemail_language.yml b/detection-rules/link_credential_phishing_voicemail_language.yml index e9259e4983a..dc215ca3218 100644 --- a/detection-rules/link_credential_phishing_voicemail_language.yml +++ b/detection-rules/link_credential_phishing_voicemail_language.yml @@ -65,13 +65,10 @@ source: | ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: 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 4d4019a331e..264ebacb2bc 100644 --- a/detection-rules/link_download_disk_image_in_encrypted_zip.yml +++ b/detection-rules/link_download_disk_image_in_encrypted_zip.yml @@ -24,15 +24,11 @@ source: | ) ) ) - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/link_download_suspicious_file.yml b/detection-rules/link_download_suspicious_file.yml index 969c0ef8cdb..367753b3220 100644 --- a/detection-rules/link_download_suspicious_file.yml +++ b/detection-rules/link_download_suspicious_file.yml @@ -33,15 +33,11 @@ source: | ) ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_fake_fax_low_reputation.yml b/detection-rules/link_fake_fax_low_reputation.yml index 0974ab392d0..f2654141930 100644 --- a/detection-rules/link_fake_fax_low_reputation.yml +++ b/detection-rules/link_fake_fax_low_reputation.yml @@ -43,16 +43,11 @@ source: | ) ) ) - - // first time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_google_apps_script_macro.yml b/detection-rules/link_google_apps_script_macro.yml index 646a0a9f669..a71f3ae38bb 100644 --- a/detection-rules/link_google_apps_script_macro.yml +++ b/detection-rules/link_google_apps_script_macro.yml @@ -11,15 +11,11 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_google_translate.yml b/detection-rules/link_google_translate.yml index e77a82d2eb9..06a07041f60 100644 --- a/detection-rules/link_google_translate.yml +++ b/detection-rules/link_google_translate.yml @@ -12,13 +12,10 @@ source: | type.inbound and any(body.links, .href_url.domain.root_domain == "translate.goog") and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/link_html_smuggling_with_adobe_branding.yml b/detection-rules/link_html_smuggling_with_adobe_branding.yml index 28d17dd563f..2a5e63ff55d 100644 --- a/detection-rules/link_html_smuggling_with_adobe_branding.yml +++ b/detection-rules/link_html_smuggling_with_adobe_branding.yml @@ -25,15 +25,11 @@ source: | ) ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: 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 0038b4ffdf7..68c8ae319e3 100644 --- a/detection-rules/link_html_smuggling_with_google_drive_branding.yml +++ b/detection-rules/link_html_smuggling_with_google_drive_branding.yml @@ -30,15 +30,11 @@ source: | ) ) ) - // Unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: 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 bd50ed86d42..020199d5b67 100644 --- a/detection-rules/link_invoice_fake_customer_service_freemail_sender.yml +++ b/detection-rules/link_invoice_fake_customer_service_freemail_sender.yml @@ -20,7 +20,6 @@ source: | ) ) ) - // First time sender exclusions are in place to avoid legitimate messages from known freemail senders. and sender.email.email not in $sender_emails attack_types: - "BEC/Fraud" diff --git a/detection-rules/link_ipfs_phishing.yml b/detection-rules/link_ipfs_phishing.yml index bb6973c2c02..84337314f44 100644 --- a/detection-rules/link_ipfs_phishing.yml +++ b/detection-rules/link_ipfs_phishing.yml @@ -31,15 +31,11 @@ source: | // 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_login_or_captcha.yml b/detection-rules/link_login_or_captcha.yml index 5e9aed2b023..70b12b721a0 100644 --- a/detection-rules/link_login_or_captcha.yml +++ b/detection-rules/link_login_or_captcha.yml @@ -28,16 +28,11 @@ source: | // exclude FP prone senders and sender.email.domain.root_domain not in ("sharepointonline.com") - - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_microsoft_device_code_phish.yml b/detection-rules/link_microsoft_device_code_phish.yml index 6553b9b081d..c9e50476872 100644 --- a/detection-rules/link_microsoft_device_code_phish.yml +++ b/detection-rules/link_microsoft_device_code_phish.yml @@ -32,16 +32,11 @@ source: | // 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 - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_microsoft_impersonation_using_hosted_png.yml b/detection-rules/link_microsoft_impersonation_using_hosted_png.yml index 1469d86d458..330c173024a 100644 --- a/detection-rules/link_microsoft_impersonation_using_hosted_png.yml +++ b/detection-rules/link_microsoft_impersonation_using_hosted_png.yml @@ -32,16 +32,11 @@ source: | // org domain in the subject of the message and any($org_domains, strings.icontains(subject.subject, .)) - - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_new_domain_in_link_first_time_sender.yml b/detection-rules/link_new_domain_in_link_first_time_sender.yml index ea1ed146a45..6f303b2fbaa 100644 --- a/detection-rules/link_new_domain_in_link_first_time_sender.yml +++ b/detection-rules/link_new_domain_in_link_first_time_sender.yml @@ -8,13 +8,10 @@ source: | and length(body.links) > 0 and any(body.links, beta.whois(.href_url.domain).days_old <= 10) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: diff --git a/detection-rules/link_notion_file_share.yml b/detection-rules/link_notion_file_share.yml index 8491cd00bac..b7a7cd744c2 100644 --- a/detection-rules/link_notion_file_share.yml +++ b/detection-rules/link_notion_file_share.yml @@ -43,16 +43,11 @@ source: | ) ) 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) 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 cdae99e81c3..526c001c888 100644 --- a/detection-rules/link_qr_code_suspicious_language_fts.yml +++ b/detection-rules/link_qr_code_suspicious_language_fts.yml @@ -44,15 +44,11 @@ source: | ) ) - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/link_suspicious_language_undisclosed_recipients.yml b/detection-rules/link_suspicious_language_undisclosed_recipients.yml index 7fcb7a130ba..b2a20cbb845 100644 --- a/detection-rules/link_suspicious_language_undisclosed_recipients.yml +++ b/detection-rules/link_suspicious_language_undisclosed_recipients.yml @@ -37,15 +37,11 @@ source: | // subject is in all caps and regex.match(subject.subject, "[A-Z ]+") - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/mass_campaign_recipient_address_new_sender.yml b/detection-rules/mass_campaign_recipient_address_new_sender.yml index 92faf055f48..3c6a51ba966 100644 --- a/detection-rules/mass_campaign_recipient_address_new_sender.yml +++ b/detection-rules/mass_campaign_recipient_address_new_sender.yml @@ -15,16 +15,11 @@ source: | // exclude To: Undisclosed recipients:; // since we won't have a valid recipient email and any(recipients.to, .email.domain.valid == true) - - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) and ( diff --git a/detection-rules/open_redirect_avast.yml b/detection-rules/open_redirect_avast.yml index 5ff4fcde8b6..4468bf1bfdc 100644 --- a/detection-rules/open_redirect_avast.yml +++ b/detection-rules/open_redirect_avast.yml @@ -10,13 +10,10 @@ source: | ) and sender.email.domain.root_domain != "avast.com" and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/recipients_undisclosed_free_subdomain_host.yml b/detection-rules/recipients_undisclosed_free_subdomain_host.yml index b66cf12cb3c..91ab346d706 100644 --- a/detection-rules/recipients_undisclosed_free_subdomain_host.yml +++ b/detection-rules/recipients_undisclosed_free_subdomain_host.yml @@ -22,13 +22,10 @@ source: | ) ) and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: 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 ba5fbdbf256..d623bcb7187 100644 --- a/detection-rules/sender_new_from_domain_first_time_sender.yml +++ b/detection-rules/sender_new_from_domain_first_time_sender.yml @@ -7,13 +7,10 @@ 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: 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 55e02712629..e2f035b548e 100644 --- a/detection-rules/spam_campaign_excessive_display_text_with_keywords.yml +++ b/detection-rules/spam_campaign_excessive_display_text_with_keywords.yml @@ -10,15 +10,11 @@ source: | 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')) - // first-time sender and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $sender_emails - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/spam_new_domain_emojis.yml b/detection-rules/spam_new_domain_emojis.yml index 8b01256663d..f9f729955b7 100644 --- a/detection-rules/spam_new_domain_emojis.yml +++ b/detection-rules/spam_new_domain_emojis.yml @@ -21,16 +21,11 @@ source: | '[\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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/spam_url_shortener_emojis.yml b/detection-rules/spam_url_shortener_emojis.yml index e793b36b770..121f88ea7d0 100644 --- a/detection-rules/spam_url_shortener_emojis.yml +++ b/detection-rules/spam_url_shortener_emojis.yml @@ -24,16 +24,11 @@ source: | '[\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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) attack_types: diff --git a/detection-rules/vip_impersonation_attack_surface_reduction.yml b/detection-rules/vip_impersonation_attack_surface_reduction.yml index 34f8fe317c9..36971da13ad 100644 --- a/detection-rules/vip_impersonation_attack_surface_reduction.yml +++ b/detection-rules/vip_impersonation_attack_surface_reduction.yml @@ -21,27 +21,19 @@ source: | 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 - ) + profile.by_sender().prevalence in ("new", "outlier") or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $sender_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) - // unsolicited and ( - ( - sender.email.domain.root_domain in $free_email_providers - and sender.email.email not in $recipient_emails - ) + not profile.by_sender().solicited or ( - sender.email.domain.root_domain not in $free_email_providers - and sender.email.domain.domain not in $recipient_domains + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives ) ) tags: From 1dc009e994a60a8602cdce0ace3783a0ef614b37 Mon Sep 17 00:00:00 2001 From: Sam Scholten Date: Thu, 5 Oct 2023 12:03:53 -0400 Subject: [PATCH 04/16] New Rule: QR Code with suspicious indicators (#817) Co-authored-by: ID Generator --- .../qr_code_suspicious_indicators.yml | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 detection-rules/qr_code_suspicious_indicators.yml diff --git a/detection-rules/qr_code_suspicious_indicators.yml b/detection-rules/qr_code_suspicious_indicators.yml new file mode 100644 index 00000000000..b929c268a99 --- /dev/null +++ b/detection-rules/qr_code_suspicious_indicators.yml @@ -0,0 +1,59 @@ +name: "QR Code with suspicious indicators" +description: | + This rule flags messages with QR codes in attachments when there are three or fewer attachments. If no attachments are present, the rule captures a screenshot of the message for analysis. Additional triggers include: sender's name containing the recipient's SLD, recipient's email mentioned in the body, an empty message body, a suspicious subject, or undisclosed recipients. +type: "rule" +severity: "high" +source: | + type.inbound + and ( + length(attachments) <= 3 + and ( + any(attachments, + .file_type in $file_types_images and (any(file.explode(.), .scan.qr.type == "url")) + ) + or ( + length(attachments) == 0 + and any(file.explode(beta.message_screenshot()), .scan.qr.type == "url") + ) + ) + and not sender.email.domain.root_domain in $org_display_names + and ( + any(recipients.to, strings.icontains(sender.display_name, .email.domain.sld)) + or any(recipients.to, strings.icontains(body.current_thread.text, .email.local_part)) + or length(body.current_thread.text) is null + or body.current_thread.text == "" + or regex.contains(subject.subject, + "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)" + ) + or (any(recipients.to, strings.icontains(subject.subject, .display_name))) + or ( + (length(recipients.to) == 0 or all(recipients.to, .display_name == "Undisclosed recipients")) + and length(recipients.cc) == 0 + and length(recipients.bcc) == 0 + ) + ) + ) + + // sender profile is new or outlier + and ( + profile.by_sender().prevalence in ("new", "outlier") + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) + ) + +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "QR code" + - "Social engineering" +detection_methods: + - "Content analysis" + - "Header analysis" + - "Computer Vision" + - "Natural Language Understanding" + - "QR code analysis" + - "Sender analysis" + - "URL analysis" +id: "04f5c34f-6518-512d-916c-4c2c2827c6a9" From c67418bfbfd892d7f0f0ee99dfa0d35846158d66 Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Thu, 5 Oct 2023 13:53:43 -0700 Subject: [PATCH 05/16] Update link_microsoft_low_reputation.yml (#846) Co-authored-by: Ross Wolf <31489089+rw-access@users.noreply.github.com> --- detection-rules/link_microsoft_low_reputation.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/detection-rules/link_microsoft_low_reputation.yml b/detection-rules/link_microsoft_low_reputation.yml index 5e467937174..eb4fec631e1 100644 --- a/detection-rules/link_microsoft_low_reputation.yml +++ b/detection-rules/link_microsoft_low_reputation.yml @@ -32,6 +32,7 @@ source: | ) or any(body.links, .href_url.domain.domain in $free_file_hosts) ) + and .href_url.domain.root_domain not in $org_domains ) // not a reply From 46a0b492b6ecacfe8ad5b27946872a7a9501833f Mon Sep 17 00:00:00 2001 From: Bobby Filar <29960025+bfilar@users.noreply.github.com> Date: Thu, 5 Oct 2023 21:28:16 -0500 Subject: [PATCH 06/16] adding signal whois for sender domain (#793) --- signals/sender/sender_domain_whois_days_old.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 signals/sender/sender_domain_whois_days_old.yml diff --git a/signals/sender/sender_domain_whois_days_old.yml b/signals/sender/sender_domain_whois_days_old.yml new file mode 100644 index 00000000000..ae013c92491 --- /dev/null +++ b/signals/sender/sender_domain_whois_days_old.yml @@ -0,0 +1,4 @@ +name: "Sender: Whois on sender domain" +type: "query" +source: | + beta.whois(sender.email.domain).days_old From 32cb236f545c7b698a1b2fec269ae7dcfd50970c Mon Sep 17 00:00:00 2001 From: Bobby Filar <29960025+bfilar@users.noreply.github.com> Date: Fri, 6 Oct 2023 09:33:40 -0500 Subject: [PATCH 07/16] Signals: Collection of sender, header, content, and link-based signals (#847) --- signals/attachments/attachment_file_name_rfq.yml | 4 ++++ signals/content/body_contains_btc_wallet.yml | 4 ++++ signals/content/body_contains_emoji.yml | 6 ++++++ signals/content/body_contains_recipient_email.yml | 4 ++++ .../content/body_contains_recipient_local_part.yml | 7 +++++++ signals/content/body_contains_rfq_language.yml | 8 ++++++++ signals/content/body_contains_vm_language.yml | 4 ++++ signals/content/body_excessive_space.yml | 4 ++++ signals/content/body_length.yml | 4 ++++ signals/content/subject_contains_auth_language.yml | 6 ++++++ signals/content/subject_contains_emoji.yml | 6 ++++++ signals/content/subject_contains_recipient_sld.yml | 4 ++++ signals/content/subject_contains_rfq_language.yml | 4 ++++ signals/content/subject_contains_vm_language.yml | 4 ++++ signals/headers/headers_all_recipients_bcc.yml | 6 ++++++ .../headers/headers_replyto_similar_to_sender.yml | 12 ++++++++++++ signals/links/link_contains_recipient_email.yml | 5 +++++ signals/sender/sender_display_contains_honorific.yml | 4 ++++ .../sender_display_contains_recipient_local_part.yml | 5 +++++ .../sender/sender_display_contains_vm_language.yml | 4 ++++ signals/sender/sender_display_is_upper.yml | 4 ++++ signals/sender/sender_display_name_contains_via.yml | 4 ++++ signals/sender/sender_domain_not_in_tranco10k.yml | 4 ++++ signals/sender/sender_domain_not_in_tranco1m.yml | 4 ++++ .../sender_domain_similar_to_recipient_domain.yml | 9 +++++++++ .../sender_email_mismatched_from_and_reply-to.yml | 7 +++++++ signals/sender/sender_length_local_part.yml | 4 ++++ 27 files changed, 141 insertions(+) create mode 100644 signals/attachments/attachment_file_name_rfq.yml create mode 100644 signals/content/body_contains_btc_wallet.yml create mode 100644 signals/content/body_contains_emoji.yml create mode 100644 signals/content/body_contains_recipient_email.yml create mode 100644 signals/content/body_contains_recipient_local_part.yml create mode 100644 signals/content/body_contains_rfq_language.yml create mode 100644 signals/content/body_contains_vm_language.yml create mode 100644 signals/content/body_excessive_space.yml create mode 100644 signals/content/body_length.yml create mode 100644 signals/content/subject_contains_auth_language.yml create mode 100644 signals/content/subject_contains_emoji.yml create mode 100644 signals/content/subject_contains_recipient_sld.yml create mode 100644 signals/content/subject_contains_rfq_language.yml create mode 100644 signals/content/subject_contains_vm_language.yml create mode 100644 signals/headers/headers_all_recipients_bcc.yml create mode 100644 signals/headers/headers_replyto_similar_to_sender.yml create mode 100644 signals/links/link_contains_recipient_email.yml create mode 100644 signals/sender/sender_display_contains_honorific.yml create mode 100644 signals/sender/sender_display_contains_recipient_local_part.yml create mode 100644 signals/sender/sender_display_contains_vm_language.yml create mode 100644 signals/sender/sender_display_is_upper.yml create mode 100644 signals/sender/sender_display_name_contains_via.yml create mode 100644 signals/sender/sender_domain_not_in_tranco10k.yml create mode 100644 signals/sender/sender_domain_not_in_tranco1m.yml create mode 100644 signals/sender/sender_domain_similar_to_recipient_domain.yml create mode 100644 signals/sender/sender_email_mismatched_from_and_reply-to.yml create mode 100644 signals/sender/sender_length_local_part.yml diff --git a/signals/attachments/attachment_file_name_rfq.yml b/signals/attachments/attachment_file_name_rfq.yml new file mode 100644 index 00000000000..e27288359e3 --- /dev/null +++ b/signals/attachments/attachment_file_name_rfq.yml @@ -0,0 +1,4 @@ +name: "Attachment: Contains RFQ File Name" +type: "query" +source: | + any(attachments, regex.icontains(.file_name, "(purchase.?order|Quot(e|ation))")) diff --git a/signals/content/body_contains_btc_wallet.yml b/signals/content/body_contains_btc_wallet.yml new file mode 100644 index 00000000000..84f02c7c5d7 --- /dev/null +++ b/signals/content/body_contains_btc_wallet.yml @@ -0,0 +1,4 @@ +name: "Body: Bitcoin address" +type: "query" +source: | + any([body.plain.raw, body.html.display_text], regex.contains(., '\b[13]{1}[a-km-zA-HJ-NP-Z1-9]{25,34}\b')) \ No newline at end of file diff --git a/signals/content/body_contains_emoji.yml b/signals/content/body_contains_emoji.yml new file mode 100644 index 00000000000..052185b6932 --- /dev/null +++ b/signals/content/body_contains_emoji.yml @@ -0,0 +1,6 @@ +name: "Body: Contains Emoji" +type: "query" +source: | + 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}]' + ) \ No newline at end of file diff --git a/signals/content/body_contains_recipient_email.yml b/signals/content/body_contains_recipient_email.yml new file mode 100644 index 00000000000..4383663f2b7 --- /dev/null +++ b/signals/content/body_contains_recipient_email.yml @@ -0,0 +1,4 @@ +name: "Body: Contains Recipient Email" +type: "query" +source: | + any(recipients.to, strings.icontains(body.current_thread.text, .email.email)) diff --git a/signals/content/body_contains_recipient_local_part.yml b/signals/content/body_contains_recipient_local_part.yml new file mode 100644 index 00000000000..7814ec0a5ed --- /dev/null +++ b/signals/content/body_contains_recipient_local_part.yml @@ -0,0 +1,7 @@ +name: "Body: Contains Recipient Local Part" +type: "query" +source: | + any(recipients.to, + strings.icontains(body.current_thread.text, .email.local_part) and not + strings.icontains(body.current_thread.text, .email.email) + ) \ No newline at end of file diff --git a/signals/content/body_contains_rfq_language.yml b/signals/content/body_contains_rfq_language.yml new file mode 100644 index 00000000000..3ddfa2c0179 --- /dev/null +++ b/signals/content/body_contains_rfq_language.yml @@ -0,0 +1,8 @@ +name: "Body: Contains RFQ Language" +type: "query" +source: | + 1 of ( + (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')) + ) \ No newline at end of file diff --git a/signals/content/body_contains_vm_language.yml b/signals/content/body_contains_vm_language.yml new file mode 100644 index 00000000000..d949e1deceb --- /dev/null +++ b/signals/content/body_contains_vm_language.yml @@ -0,0 +1,4 @@ +name: "Body: Contains Voicemail Language" +type: "query" +source: | + regex.contains(body.current_thread.text, '(voice)\s?(mail|message|recording|call)') \ No newline at end of file diff --git a/signals/content/body_excessive_space.yml b/signals/content/body_excessive_space.yml new file mode 100644 index 00000000000..949bfef384c --- /dev/null +++ b/signals/content/body_excessive_space.yml @@ -0,0 +1,4 @@ +name: "Body: Space Obfuscation" +type: "query" +source: | + regex.icontains(coalesce(body.html.inner_text, body.html.display_text), '([a-zA-Z\d\.]\s){30,}') diff --git a/signals/content/body_length.yml b/signals/content/body_length.yml new file mode 100644 index 00000000000..2b032f6289c --- /dev/null +++ b/signals/content/body_length.yml @@ -0,0 +1,4 @@ +name: "Content: Body Length" +type: "query" +source: | + length(body.current_thread.text) diff --git a/signals/content/subject_contains_auth_language.yml b/signals/content/subject_contains_auth_language.yml new file mode 100644 index 00000000000..afac8ec40f9 --- /dev/null +++ b/signals/content/subject_contains_auth_language.yml @@ -0,0 +1,6 @@ +name: "Subject: Contains Authentication Language" +type: "query" +source: | + regex.contains(subject.subject, + "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)" + ) diff --git a/signals/content/subject_contains_emoji.yml b/signals/content/subject_contains_emoji.yml new file mode 100644 index 00000000000..b3ed06b018b --- /dev/null +++ b/signals/content/subject_contains_emoji.yml @@ -0,0 +1,6 @@ +name: "Subject: Contains Emoji" +type: "query" +source: | + 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}]' + ) \ No newline at end of file diff --git a/signals/content/subject_contains_recipient_sld.yml b/signals/content/subject_contains_recipient_sld.yml new file mode 100644 index 00000000000..b1b2f21d28e --- /dev/null +++ b/signals/content/subject_contains_recipient_sld.yml @@ -0,0 +1,4 @@ +name: "Subject: Contains Recipient SLD" +type: "query" +source: | + any(recipients.to, strings.icontains(subject.subject, .email.domain.sld)) diff --git a/signals/content/subject_contains_rfq_language.yml b/signals/content/subject_contains_rfq_language.yml new file mode 100644 index 00000000000..910ae916548 --- /dev/null +++ b/signals/content/subject_contains_rfq_language.yml @@ -0,0 +1,4 @@ +name: "Subject: Contains RFQ Language" +type: "query" +source: | + regex.icontains(subject.subject, '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b)') \ No newline at end of file diff --git a/signals/content/subject_contains_vm_language.yml b/signals/content/subject_contains_vm_language.yml new file mode 100644 index 00000000000..b4d7d6ac60c --- /dev/null +++ b/signals/content/subject_contains_vm_language.yml @@ -0,0 +1,4 @@ +name: "Subject: Contains Voicemail Language" +type: "query" +source: | + regex.icontains(subject.subject, 'voice.*?(mail|message|recording|call)') \ No newline at end of file diff --git a/signals/headers/headers_all_recipients_bcc.yml b/signals/headers/headers_all_recipients_bcc.yml new file mode 100644 index 00000000000..7af0f3986d4 --- /dev/null +++ b/signals/headers/headers_all_recipients_bcc.yml @@ -0,0 +1,6 @@ +name: "Headers: All recipients BCCd" +type: "query" +source: | + length(recipients.to) == 0 + and length(recipients.cc) == 0 + and length(recipients.bcc) == 1 diff --git a/signals/headers/headers_replyto_similar_to_sender.yml b/signals/headers/headers_replyto_similar_to_sender.yml new file mode 100644 index 00000000000..4946a704c9e --- /dev/null +++ b/signals/headers/headers_replyto_similar_to_sender.yml @@ -0,0 +1,12 @@ +name: "Headers: Reply-to Domain Similar To Sender Domain" +type: "query" +source: | + any(headers.reply_to, + length(headers.reply_to) > 0 + and all(headers.reply_to, + ( + strings.ilevenshtein(.email.domain.root_domain, sender.email.domain.root_domain) <= 1 + and .email.domain.root_domain != sender.email.domain.root_domain + ) + ) + ) diff --git a/signals/links/link_contains_recipient_email.yml b/signals/links/link_contains_recipient_email.yml new file mode 100644 index 00000000000..f1ab8f78932 --- /dev/null +++ b/signals/links/link_contains_recipient_email.yml @@ -0,0 +1,5 @@ +name: "Link: Contains Recipient Email" +type: "query" +source: | + any(body.links, any(recipients.to, strings.icontains(..href_url.query_params, .email.email))) + diff --git a/signals/sender/sender_display_contains_honorific.yml b/signals/sender/sender_display_contains_honorific.yml new file mode 100644 index 00000000000..2c8ee120a28 --- /dev/null +++ b/signals/sender/sender_display_contains_honorific.yml @@ -0,0 +1,4 @@ +name: "Sender: Display Name Contains Honorific" +type: "query" +source: | + regex.icontains(sender.display_name, "(?:Mr.?|Mrs.?|Ms.?|Miss.?|Dr.?|Prof.?|Sir.?|Lady.?|Rev.?)[ \t]+") \ No newline at end of file diff --git a/signals/sender/sender_display_contains_recipient_local_part.yml b/signals/sender/sender_display_contains_recipient_local_part.yml new file mode 100644 index 00000000000..c3d5297572d --- /dev/null +++ b/signals/sender/sender_display_contains_recipient_local_part.yml @@ -0,0 +1,5 @@ +name: "Sender: Display Name Contains Recipient Local-Part" +type: "query" +source: | + any(recipients.to, strings.icontains(sender.display_name, .email.local_part)) + and not any(recipients.to, strings.icontains(.display_name, "recipients")) \ No newline at end of file diff --git a/signals/sender/sender_display_contains_vm_language.yml b/signals/sender/sender_display_contains_vm_language.yml new file mode 100644 index 00000000000..7f142f2161b --- /dev/null +++ b/signals/sender/sender_display_contains_vm_language.yml @@ -0,0 +1,4 @@ +name: "Sender: Display Name Contains Voicemail Language" +type: "query" +source: | + regex.icontains(sender.display_name, 'voice.*?(mail|message|recording|call)') \ No newline at end of file diff --git a/signals/sender/sender_display_is_upper.yml b/signals/sender/sender_display_is_upper.yml new file mode 100644 index 00000000000..04a29ffc9e5 --- /dev/null +++ b/signals/sender/sender_display_is_upper.yml @@ -0,0 +1,4 @@ +name: "Sender: Display Name Contains All Capital Letters" +type: "query" +source: | + regex.match(sender.display_name, "^[^a-z]*[A-Z][^a-z]*$") \ No newline at end of file diff --git a/signals/sender/sender_display_name_contains_via.yml b/signals/sender/sender_display_name_contains_via.yml new file mode 100644 index 00000000000..6901b2786ac --- /dev/null +++ b/signals/sender/sender_display_name_contains_via.yml @@ -0,0 +1,4 @@ +name: "Sender: Display Name Contains All Capital Letters" +type: "query" +source: | + regex.icontains(sender.display_name, "(?:^|[^a-zA-Z0-9])via(?:$|[^a-zA-Z0-9])|[\"']via[\"']") \ No newline at end of file diff --git a/signals/sender/sender_domain_not_in_tranco10k.yml b/signals/sender/sender_domain_not_in_tranco10k.yml new file mode 100644 index 00000000000..97148597d21 --- /dev/null +++ b/signals/sender/sender_domain_not_in_tranco10k.yml @@ -0,0 +1,4 @@ +name: "Sender: Domain not in Tranco 10k" +type: "query" +source: | + sender.email.domain.domain not in $tranco_10k diff --git a/signals/sender/sender_domain_not_in_tranco1m.yml b/signals/sender/sender_domain_not_in_tranco1m.yml new file mode 100644 index 00000000000..a38a2d288ce --- /dev/null +++ b/signals/sender/sender_domain_not_in_tranco1m.yml @@ -0,0 +1,4 @@ +name: "Sender: Domain not in Tranco 1m" +type: "query" +source: | + sender.email.domain.domain not in $tranco_1m diff --git a/signals/sender/sender_domain_similar_to_recipient_domain.yml b/signals/sender/sender_domain_similar_to_recipient_domain.yml new file mode 100644 index 00000000000..89eb3ad8c9b --- /dev/null +++ b/signals/sender/sender_domain_similar_to_recipient_domain.yml @@ -0,0 +1,9 @@ +name: "Sender: Domain Similar To Recipient Domain" +type: "query" +source: | + any(recipients.to, + ( + strings.ilevenshtein(.email.email, sender.email.email) <= 1 and + .email.email != sender.email.email + ) + ) diff --git a/signals/sender/sender_email_mismatched_from_and_reply-to.yml b/signals/sender/sender_email_mismatched_from_and_reply-to.yml new file mode 100644 index 00000000000..5b9bcd37900 --- /dev/null +++ b/signals/sender/sender_email_mismatched_from_and_reply-to.yml @@ -0,0 +1,7 @@ +name: "Sender: Mismatched From and Reply-to Email" +type: "query" +source: | + any(headers.reply_to, + length(headers.reply_to) > 0 + and all(headers.reply_to, .email.email != sender.email.email) + ) diff --git a/signals/sender/sender_length_local_part.yml b/signals/sender/sender_length_local_part.yml new file mode 100644 index 00000000000..c2aed250c49 --- /dev/null +++ b/signals/sender/sender_length_local_part.yml @@ -0,0 +1,4 @@ +name: "Sender: Local-Part Length" +type: "query" +source: | + length(sender.email.local_part) From a50d0c50e510d04d1933225cd7c781ac427f8dab Mon Sep 17 00:00:00 2001 From: Bobby Filar <29960025+bfilar@users.noreply.github.com> Date: Fri, 6 Oct 2023 09:38:25 -0500 Subject: [PATCH 08/16] First batch of NLU signals (#501) Co-authored-by: Cameron Dunn Co-authored-by: Sam Scholten Co-authored-by: Sam Scholten --- signals/content/nlu_bec_high_conf.yml | 7 +++++++ signals/content/nlu_bec_low_conf.yml | 7 +++++++ signals/content/nlu_bec_med_conf.yml | 7 +++++++ signals/content/nlu_callback_scam_high_conf.yml | 7 +++++++ signals/content/nlu_callback_scam_low_conf.yml | 7 +++++++ signals/content/nlu_callback_scam_medium_conf.yml | 7 +++++++ signals/content/nlu_credtheft_high_conf.yml | 8 ++++++++ signals/content/nlu_credtheft_low_conf.yml | 8 ++++++++ signals/content/nlu_credtheft_med_conf.yml | 8 ++++++++ signals/content/nlu_extortion_high_conf.yml | 8 ++++++++ signals/content/nlu_extortion_low_conf.yml | 8 ++++++++ signals/content/nlu_extortion_med_conf.yml | 8 ++++++++ signals/content/nlu_financial_entity.yml | 7 +++++++ signals/content/nlu_greeting_entity.yml | 7 +++++++ signals/content/nlu_invoice_high_conf.yml | 7 +++++++ signals/content/nlu_invoice_low_conf.yml | 7 +++++++ signals/content/nlu_invoice_medium_conf.yml | 7 +++++++ signals/content/nlu_job_scam_high_conf.yml | 7 +++++++ signals/content/nlu_job_scam_low_conf.yml | 7 +++++++ signals/content/nlu_job_scam_medium_conf.yml | 7 +++++++ signals/content/nlu_org_entity.yml | 7 +++++++ signals/content/nlu_payment_high_conf.yml | 7 +++++++ signals/content/nlu_payment_low_conf.yml | 7 +++++++ signals/content/nlu_payment_medium_conf.yml | 7 +++++++ signals/content/nlu_purchase_order_high_conf.yml | 7 +++++++ signals/content/nlu_purchase_order_low_conf.yml | 7 +++++++ signals/content/nlu_purchase_order_medium_conf.yml | 7 +++++++ signals/content/nlu_recipient_entity.yml | 7 +++++++ signals/content/nlu_request_entity.yml | 7 +++++++ signals/content/nlu_salutation_entity.yml | 7 +++++++ signals/content/nlu_sender_entity.yml | 7 +++++++ signals/content/nlu_steal_pii_high_conf.yml | 7 +++++++ signals/content/nlu_steal_pii_low_conf.yml | 7 +++++++ signals/content/nlu_steal_pii_medium_conf.yml | 7 +++++++ signals/content/nlu_urgency_entity.yml | 7 +++++++ 35 files changed, 251 insertions(+) create mode 100644 signals/content/nlu_bec_high_conf.yml create mode 100644 signals/content/nlu_bec_low_conf.yml create mode 100644 signals/content/nlu_bec_med_conf.yml create mode 100644 signals/content/nlu_callback_scam_high_conf.yml create mode 100644 signals/content/nlu_callback_scam_low_conf.yml create mode 100644 signals/content/nlu_callback_scam_medium_conf.yml create mode 100644 signals/content/nlu_credtheft_high_conf.yml create mode 100644 signals/content/nlu_credtheft_low_conf.yml create mode 100644 signals/content/nlu_credtheft_med_conf.yml create mode 100644 signals/content/nlu_extortion_high_conf.yml create mode 100644 signals/content/nlu_extortion_low_conf.yml create mode 100644 signals/content/nlu_extortion_med_conf.yml create mode 100644 signals/content/nlu_financial_entity.yml create mode 100644 signals/content/nlu_greeting_entity.yml create mode 100644 signals/content/nlu_invoice_high_conf.yml create mode 100644 signals/content/nlu_invoice_low_conf.yml create mode 100644 signals/content/nlu_invoice_medium_conf.yml create mode 100644 signals/content/nlu_job_scam_high_conf.yml create mode 100644 signals/content/nlu_job_scam_low_conf.yml create mode 100644 signals/content/nlu_job_scam_medium_conf.yml create mode 100644 signals/content/nlu_org_entity.yml create mode 100644 signals/content/nlu_payment_high_conf.yml create mode 100644 signals/content/nlu_payment_low_conf.yml create mode 100644 signals/content/nlu_payment_medium_conf.yml create mode 100644 signals/content/nlu_purchase_order_high_conf.yml create mode 100644 signals/content/nlu_purchase_order_low_conf.yml create mode 100644 signals/content/nlu_purchase_order_medium_conf.yml create mode 100644 signals/content/nlu_recipient_entity.yml create mode 100644 signals/content/nlu_request_entity.yml create mode 100644 signals/content/nlu_salutation_entity.yml create mode 100644 signals/content/nlu_sender_entity.yml create mode 100644 signals/content/nlu_steal_pii_high_conf.yml create mode 100644 signals/content/nlu_steal_pii_low_conf.yml create mode 100644 signals/content/nlu_steal_pii_medium_conf.yml create mode 100644 signals/content/nlu_urgency_entity.yml diff --git a/signals/content/nlu_bec_high_conf.yml b/signals/content/nlu_bec_high_conf.yml new file mode 100644 index 00000000000..20c5f37a036 --- /dev/null +++ b/signals/content/nlu_bec_high_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Business Email Compromise - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "bec" and .confidence == "high") +tags: + - "Natural Language Understanding" + - "Business Email Compromise" diff --git a/signals/content/nlu_bec_low_conf.yml b/signals/content/nlu_bec_low_conf.yml new file mode 100644 index 00000000000..c94c12c06f1 --- /dev/null +++ b/signals/content/nlu_bec_low_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Business Email Compromise - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "bec" and .confidence == "low") +tags: + - "Natural Language Understanding" + - "Business Email Compromise" diff --git a/signals/content/nlu_bec_med_conf.yml b/signals/content/nlu_bec_med_conf.yml new file mode 100644 index 00000000000..70521baffcd --- /dev/null +++ b/signals/content/nlu_bec_med_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Business Email Compromise - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "bec" and .confidence == "medium") +tags: + - "Natural Language Understanding" + - "Business Email Compromise" diff --git a/signals/content/nlu_callback_scam_high_conf.yml b/signals/content/nlu_callback_scam_high_conf.yml new file mode 100644 index 00000000000..1a27d1b09cc --- /dev/null +++ b/signals/content/nlu_callback_scam_high_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Callback Scam - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" and .confidence == "high") +tags: + - "Natural Language Understanding" + - "Callback Scam" \ No newline at end of file diff --git a/signals/content/nlu_callback_scam_low_conf.yml b/signals/content/nlu_callback_scam_low_conf.yml new file mode 100644 index 00000000000..05a69e83197 --- /dev/null +++ b/signals/content/nlu_callback_scam_low_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Callback Scam - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" and .confidence == "low") +tags: + - "Natural Language Understanding" + - "Callback Scam" \ No newline at end of file diff --git a/signals/content/nlu_callback_scam_medium_conf.yml b/signals/content/nlu_callback_scam_medium_conf.yml new file mode 100644 index 00000000000..1facc9db9fe --- /dev/null +++ b/signals/content/nlu_callback_scam_medium_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Callback Scam - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "callback_scam" and .confidence == "medium") +tags: + - "Natural Language Understanding" + - "Callback Scam" \ No newline at end of file diff --git a/signals/content/nlu_credtheft_high_conf.yml b/signals/content/nlu_credtheft_high_conf.yml new file mode 100644 index 00000000000..b137a29762f --- /dev/null +++ b/signals/content/nlu_credtheft_high_conf.yml @@ -0,0 +1,8 @@ +name: "NLU Intent: Credential Theft - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence == "high") +severity: "medium" +tags: + - "Natural Language Understanding" + - "Credential Theft" diff --git a/signals/content/nlu_credtheft_low_conf.yml b/signals/content/nlu_credtheft_low_conf.yml new file mode 100644 index 00000000000..0c0beed8131 --- /dev/null +++ b/signals/content/nlu_credtheft_low_conf.yml @@ -0,0 +1,8 @@ +name: "NLU Intent: Credential Theft - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence == "low") +severity: "medium" +tags: + - "Natural Language Understanding" + - "Credential Theft" diff --git a/signals/content/nlu_credtheft_med_conf.yml b/signals/content/nlu_credtheft_med_conf.yml new file mode 100644 index 00000000000..f0eb2ea3c37 --- /dev/null +++ b/signals/content/nlu_credtheft_med_conf.yml @@ -0,0 +1,8 @@ +name: "NLU Intent: Credential Theft - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "cred_theft" and .confidence == "medium") +severity: "medium" +tags: + - "Natural Language Understanding" + - "Credential Theft" diff --git a/signals/content/nlu_extortion_high_conf.yml b/signals/content/nlu_extortion_high_conf.yml new file mode 100644 index 00000000000..1b78bd3c20d --- /dev/null +++ b/signals/content/nlu_extortion_high_conf.yml @@ -0,0 +1,8 @@ +name: "NLU Intent: Extortion - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "extortion" and .confidence == "high") +severity: "medium" +tags: + - "Natural Language Understanding" + - "Extortion" diff --git a/signals/content/nlu_extortion_low_conf.yml b/signals/content/nlu_extortion_low_conf.yml new file mode 100644 index 00000000000..918a8dc74ac --- /dev/null +++ b/signals/content/nlu_extortion_low_conf.yml @@ -0,0 +1,8 @@ +name: "NLU Intent: Extortion - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "extortion" and .confidence == "low") +severity: "medium" +tags: + - "Natural Language Understanding" + - "Extortion" diff --git a/signals/content/nlu_extortion_med_conf.yml b/signals/content/nlu_extortion_med_conf.yml new file mode 100644 index 00000000000..32f0355e5e7 --- /dev/null +++ b/signals/content/nlu_extortion_med_conf.yml @@ -0,0 +1,8 @@ +name: "NLU Intent: Extortion - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "extortion" and .confidence == "medium") +severity: "medium" +tags: + - "Natural Language Understanding" + - "Extortion" diff --git a/signals/content/nlu_financial_entity.yml b/signals/content/nlu_financial_entity.yml new file mode 100644 index 00000000000..0ba3bccd299 --- /dev/null +++ b/signals/content/nlu_financial_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Financial" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "financial") +tags: + - "Natural Language Understanding" + \ No newline at end of file diff --git a/signals/content/nlu_greeting_entity.yml b/signals/content/nlu_greeting_entity.yml new file mode 100644 index 00000000000..d1d83eb3503 --- /dev/null +++ b/signals/content/nlu_greeting_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Greeting" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "greeting") +tags: + - "Natural Language Understanding" + \ No newline at end of file diff --git a/signals/content/nlu_invoice_high_conf.yml b/signals/content/nlu_invoice_high_conf.yml new file mode 100644 index 00000000000..aa94fd0f933 --- /dev/null +++ b/signals/content/nlu_invoice_high_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Invoice - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice" and .confidence == "high") +tags: + - "Natural Language Understanding" + - "Invoice" \ No newline at end of file diff --git a/signals/content/nlu_invoice_low_conf.yml b/signals/content/nlu_invoice_low_conf.yml new file mode 100644 index 00000000000..af0a17e126c --- /dev/null +++ b/signals/content/nlu_invoice_low_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Invoice - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice" and .confidence == "low") +tags: + - "Natural Language Understanding" + - "Invoice" \ No newline at end of file diff --git a/signals/content/nlu_invoice_medium_conf.yml b/signals/content/nlu_invoice_medium_conf.yml new file mode 100644 index 00000000000..85ff75d1955 --- /dev/null +++ b/signals/content/nlu_invoice_medium_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Invoice - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "invoice" and .confidence == "medium") +tags: + - "Natural Language Understanding" + - "Invoice" \ No newline at end of file diff --git a/signals/content/nlu_job_scam_high_conf.yml b/signals/content/nlu_job_scam_high_conf.yml new file mode 100644 index 00000000000..1236e7ef5f6 --- /dev/null +++ b/signals/content/nlu_job_scam_high_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Job Scam - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "job_scam" and .confidence == "high") +tags: + - "Natural Language Understanding" + - "Job Scam" \ No newline at end of file diff --git a/signals/content/nlu_job_scam_low_conf.yml b/signals/content/nlu_job_scam_low_conf.yml new file mode 100644 index 00000000000..67b0143c933 --- /dev/null +++ b/signals/content/nlu_job_scam_low_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Job Scam - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "job_scam" and .confidence == "low") +tags: + - "Natural Language Understanding" + - "Job Scam" \ No newline at end of file diff --git a/signals/content/nlu_job_scam_medium_conf.yml b/signals/content/nlu_job_scam_medium_conf.yml new file mode 100644 index 00000000000..082c1fd347b --- /dev/null +++ b/signals/content/nlu_job_scam_medium_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Job Scam - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "job_scam" and .confidence == "medium") +tags: + - "Natural Language Understanding" + - "Job Scam" \ No newline at end of file diff --git a/signals/content/nlu_org_entity.yml b/signals/content/nlu_org_entity.yml new file mode 100644 index 00000000000..d29cde883ab --- /dev/null +++ b/signals/content/nlu_org_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Organization" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "org") +tags: + - "Natural Language Understanding" + \ No newline at end of file diff --git a/signals/content/nlu_payment_high_conf.yml b/signals/content/nlu_payment_high_conf.yml new file mode 100644 index 00000000000..eed7bd8b0e5 --- /dev/null +++ b/signals/content/nlu_payment_high_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Payment - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "payment" and .confidence == "high") +tags: + - "Natural Language Understanding" + - "Payment" \ No newline at end of file diff --git a/signals/content/nlu_payment_low_conf.yml b/signals/content/nlu_payment_low_conf.yml new file mode 100644 index 00000000000..7d964112b32 --- /dev/null +++ b/signals/content/nlu_payment_low_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Payment - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "payment" and .confidence == "low") +tags: + - "Natural Language Understanding" + - "Payment" \ No newline at end of file diff --git a/signals/content/nlu_payment_medium_conf.yml b/signals/content/nlu_payment_medium_conf.yml new file mode 100644 index 00000000000..12dcc38846b --- /dev/null +++ b/signals/content/nlu_payment_medium_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Payment - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "payment" and .confidence == "medium") +tags: + - "Natural Language Understanding" + - "Payment" \ No newline at end of file diff --git a/signals/content/nlu_purchase_order_high_conf.yml b/signals/content/nlu_purchase_order_high_conf.yml new file mode 100644 index 00000000000..35df25f3274 --- /dev/null +++ b/signals/content/nlu_purchase_order_high_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Purchase Order - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "purchase_order" and .confidence == "high") +tags: + - "Natural Language Understanding" + - "Purchase Order" \ No newline at end of file diff --git a/signals/content/nlu_purchase_order_low_conf.yml b/signals/content/nlu_purchase_order_low_conf.yml new file mode 100644 index 00000000000..6b5786bd0bd --- /dev/null +++ b/signals/content/nlu_purchase_order_low_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Purchase Order - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "purchase_order" and .confidence == "low") +tags: + - "Natural Language Understanding" + - "Purchase Order" \ No newline at end of file diff --git a/signals/content/nlu_purchase_order_medium_conf.yml b/signals/content/nlu_purchase_order_medium_conf.yml new file mode 100644 index 00000000000..9866c11ce64 --- /dev/null +++ b/signals/content/nlu_purchase_order_medium_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Tag: Purchase Order - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).tags, .name == "purchase_order" and .confidence == "medium") +tags: + - "Natural Language Understanding" + - "Purchase Order" \ No newline at end of file diff --git a/signals/content/nlu_recipient_entity.yml b/signals/content/nlu_recipient_entity.yml new file mode 100644 index 00000000000..47963cc3921 --- /dev/null +++ b/signals/content/nlu_recipient_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Recipient" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "recipient") +tags: + - "Natural Language Understanding" + \ No newline at end of file diff --git a/signals/content/nlu_request_entity.yml b/signals/content/nlu_request_entity.yml new file mode 100644 index 00000000000..168d1d38d6f --- /dev/null +++ b/signals/content/nlu_request_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Request" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") +tags: + - "Natural Language Understanding" + \ No newline at end of file diff --git a/signals/content/nlu_salutation_entity.yml b/signals/content/nlu_salutation_entity.yml new file mode 100644 index 00000000000..c22ba076704 --- /dev/null +++ b/signals/content/nlu_salutation_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Salutation" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "salutation") +tags: + - "Natural Language Understanding" + \ No newline at end of file diff --git a/signals/content/nlu_sender_entity.yml b/signals/content/nlu_sender_entity.yml new file mode 100644 index 00000000000..da32e4e3e4d --- /dev/null +++ b/signals/content/nlu_sender_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Sender" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "sender") +tags: + - "Natural Language Understanding" + \ No newline at end of file diff --git a/signals/content/nlu_steal_pii_high_conf.yml b/signals/content/nlu_steal_pii_high_conf.yml new file mode 100644 index 00000000000..0bd6937019b --- /dev/null +++ b/signals/content/nlu_steal_pii_high_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Steal PII - High Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "steal_pii" and .confidence == "high") +tags: + - "Natural Language Understanding" + - "Steal PII" \ No newline at end of file diff --git a/signals/content/nlu_steal_pii_low_conf.yml b/signals/content/nlu_steal_pii_low_conf.yml new file mode 100644 index 00000000000..a90fad957db --- /dev/null +++ b/signals/content/nlu_steal_pii_low_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Steal PII - Low Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "steal_pii" and .confidence == "low") +tags: + - "Natural Language Understanding" + - "Steal PII" \ No newline at end of file diff --git a/signals/content/nlu_steal_pii_medium_conf.yml b/signals/content/nlu_steal_pii_medium_conf.yml new file mode 100644 index 00000000000..e12c0c02b31 --- /dev/null +++ b/signals/content/nlu_steal_pii_medium_conf.yml @@ -0,0 +1,7 @@ +name: "NLU Intent: Steal PII - Medium Confidence" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).intents, .name == "steal_pii" and .confidence == "medium") +tags: + - "Natural Language Understanding" + - "Steal PII" \ No newline at end of file diff --git a/signals/content/nlu_urgency_entity.yml b/signals/content/nlu_urgency_entity.yml new file mode 100644 index 00000000000..a13b76426b8 --- /dev/null +++ b/signals/content/nlu_urgency_entity.yml @@ -0,0 +1,7 @@ +name: "NLU Entity: Urgency" +type: "query" +source: | + any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency") +tags: + - "Natural Language Understanding" + \ No newline at end of file From 37c26543c5c5925b90fab4d351cb15d895d16d8e Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Tue, 10 Oct 2023 11:01:45 -0700 Subject: [PATCH 09/16] Updating rule: impersonation_recipient_sld_in_sender_local_fts.yml (#850) --- .../impersonation_recipient_sld_in_sender_local_fts.yml | 5 +++++ 1 file changed, 5 insertions(+) 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 53985558905..3f999ac31b1 100644 --- a/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml +++ b/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml @@ -25,6 +25,11 @@ source: | ) ) ) + // negating listservs + and not ( + any(headers.hops, any(.fields, .name == "List-Unsubscribe")) + and strings.contains(sender.display_name, "via") + ) and sender.email.domain.root_domain not in $org_domains and ( profile.by_sender().prevalence in ("new", "outlier") From 319297749a2319f4feaf61e9d4c3dde05e58b8df Mon Sep 17 00:00:00 2001 From: Bobby Filar <29960025+bfilar@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:25:08 -0500 Subject: [PATCH 10/16] Adding negation for auto-survey emails (#849) --- .../impersonation_recipient_sld_in_sender_local_fts.yml | 1 + 1 file changed, 1 insertion(+) 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 3f999ac31b1..b74e05bc24d 100644 --- a/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml +++ b/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml @@ -31,6 +31,7 @@ source: | and strings.contains(sender.display_name, "via") ) and sender.email.domain.root_domain not in $org_domains + and sender.email.domain.root_domain not in ("medallia.com", "icims.com", "workday.com") and ( profile.by_sender().prevalence in ("new", "outlier") or ( From 595aa7b031256505d467c03040794e1d492a3b91 Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Tue, 10 Oct 2023 16:55:04 -0700 Subject: [PATCH 11/16] Fixing insight naming to match UI and MDM (#852) --- insights/headers/mismatched_from_reply_to.yml | 2 +- insights/headers/mismatched_from_return_path.yml | 2 +- insights/headers/suspicious_recipient_pattern.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/insights/headers/mismatched_from_reply_to.yml b/insights/headers/mismatched_from_reply_to.yml index 8bd00b62bae..ac9a2761923 100644 --- a/insights/headers/mismatched_from_reply_to.yml +++ b/insights/headers/mismatched_from_reply_to.yml @@ -1,4 +1,4 @@ -name: "Mismatched From and Reply-to" +name: "Mismatched Sender (From) and Reply-to" type: "query" source: | map(filter(headers.reply_to, diff --git a/insights/headers/mismatched_from_return_path.yml b/insights/headers/mismatched_from_return_path.yml index ff91e842db5..d891ad80560 100644 --- a/insights/headers/mismatched_from_return_path.yml +++ b/insights/headers/mismatched_from_return_path.yml @@ -1,4 +1,4 @@ -name: "Mismatched From and Return-Path" +name: "Mismatched Sender (From) and Return-Path" type: "query" source: | filter([headers.return_path.email], diff --git a/insights/headers/suspicious_recipient_pattern.yml b/insights/headers/suspicious_recipient_pattern.yml index 270444a77a6..72f52f9e5ea 100644 --- a/insights/headers/suspicious_recipient_pattern.yml +++ b/insights/headers/suspicious_recipient_pattern.yml @@ -1,6 +1,6 @@ # name: "Suspicious Recipient pattern" -name: "To matches From but not Return-Path" -description: "To is the same as the From with a different Return-Path" +name: "To matches Sender (From) but not Return-Path" +description: "To is the same as the sender with a different Return-Path" references: - "https://docs.sublimesecurity.com/docs/how-to-write-a-rule-for-a-phishing-attack" type: "query" From 68f430f1ee581137996f8fdc7c6d78bef5c6541b Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Wed, 11 Oct 2023 08:24:08 -0700 Subject: [PATCH 12/16] Moving rule to discovery + creating insight (#854) --- ...rsonation_recipient_sld_in_sender_local_fts.yml | 0 insights/sender/recipient_sld_in_sender_local.yml | 14 ++++++++++++++ 2 files changed, 14 insertions(+) rename {detection-rules => discovery-rules}/impersonation_recipient_sld_in_sender_local_fts.yml (100%) create mode 100644 insights/sender/recipient_sld_in_sender_local.yml diff --git a/detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml b/discovery-rules/impersonation_recipient_sld_in_sender_local_fts.yml similarity index 100% rename from detection-rules/impersonation_recipient_sld_in_sender_local_fts.yml rename to discovery-rules/impersonation_recipient_sld_in_sender_local_fts.yml diff --git a/insights/sender/recipient_sld_in_sender_local.yml b/insights/sender/recipient_sld_in_sender_local.yml new file mode 100644 index 00000000000..7c6b8d7bfc3 --- /dev/null +++ b/insights/sender/recipient_sld_in_sender_local.yml @@ -0,0 +1,14 @@ +name: "Recipient SLD in sender's email address local part" +description: | + The sender's email address local part contains the recipient's SLD. +type: "query" +source: | + type.inbound + 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 + ) + ) +severity: "medium" From a0a8541ffade435441b49752692542e3a9f5a5d1 Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Fri, 13 Oct 2023 09:43:38 -0700 Subject: [PATCH 13/16] Updating rule: attachment_any_html_unsolicited.yml (#855) --- detection-rules/attachment_any_html_unsolicited.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/detection-rules/attachment_any_html_unsolicited.yml b/detection-rules/attachment_any_html_unsolicited.yml index c5549895fd3..4b3daf7f348 100644 --- a/detection-rules/attachment_any_html_unsolicited.yml +++ b/detection-rules/attachment_any_html_unsolicited.yml @@ -12,11 +12,8 @@ source: | type.inbound and any(attachments, .file_extension in~ ('htm', 'html') or .file_type == "html") and ( - not profile.by_sender().solicited - or ( - profile.by_sender().any_messages_malicious_or_spam - and not profile.by_sender().any_false_positives - ) + not profile.by_sender().any_false_positives + and not profile.by_sender().solicited ) tags: - "Attack surface reduction" From ae46cc84568915f237e3f9d5a623a5bcf8df4571 Mon Sep 17 00:00:00 2001 From: Bobby Filar <29960025+bfilar@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:14:40 -0500 Subject: [PATCH 14/16] Signals: additional contextual signals (#848) --- .../body_contains_shipping_language.yml | 16 ++++++++++++ signals/content/body_is_inline_image.yml | 6 +++++ .../content/subject_suspicious_keywords.yml | 3 ++- signals/headers/headers_urlhaus_domain.yml | 7 +++++ .../links/link_contains_recipient_email.yml | 2 +- .../link_contains_unicode_characters.yml | 5 ++++ .../link_count_distinct_display_text.yml | 4 +++ ...ink_domains_do_not_match_sender_domain.yml | 8 ++++++ signals/links/link_ipfs.yml | 26 +++++++++++++++++++ signals/links/link_same_through_msg.yml | 6 +++++ ...nder_display_contains_recipient_domain.yml | 4 +++ .../sender_display_name_contains_email.yml | 5 ++++ 12 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 signals/content/body_contains_shipping_language.yml create mode 100644 signals/content/body_is_inline_image.yml create mode 100644 signals/headers/headers_urlhaus_domain.yml create mode 100644 signals/links/link_contains_unicode_characters.yml create mode 100644 signals/links/link_count_distinct_display_text.yml create mode 100644 signals/links/link_domains_do_not_match_sender_domain.yml create mode 100644 signals/links/link_ipfs.yml create mode 100644 signals/links/link_same_through_msg.yml create mode 100644 signals/sender/sender_display_contains_recipient_domain.yml create mode 100644 signals/sender/sender_display_name_contains_email.yml diff --git a/signals/content/body_contains_shipping_language.yml b/signals/content/body_contains_shipping_language.yml new file mode 100644 index 00000000000..4962537122e --- /dev/null +++ b/signals/content/body_contains_shipping_language.yml @@ -0,0 +1,16 @@ +name: "Body: Contains Shipping Language" +type: "query" +source: | + regex.icontains(body.current_thread.text, + "abandon.*package", + "courier.*able", + "missed.*shipping.*notification", + "missed.shipment.notification", + "unable.*deliver", + "delivery.*attempt.*failed", + "signed.*delivery", + "status of your (.{314})? ?delivery", + "delivery attempt", + "delivery stopped for shipment", + "fedex tracking", + ) diff --git a/signals/content/body_is_inline_image.yml b/signals/content/body_is_inline_image.yml new file mode 100644 index 00000000000..13fe0e0337b --- /dev/null +++ b/signals/content/body_is_inline_image.yml @@ -0,0 +1,6 @@ +name: "Content: Body is an Inline Image" +type: "query" +source: | + length(body.html.raw) < 200 + and length(body.links) > 0 + and strings.ilike(body.html.raw, "*img*cid*") diff --git a/signals/content/subject_suspicious_keywords.yml b/signals/content/subject_suspicious_keywords.yml index 276d4d6234e..28dd8596fef 100644 --- a/signals/content/subject_suspicious_keywords.yml +++ b/signals/content/subject_suspicious_keywords.yml @@ -93,9 +93,10 @@ source: | "scanned.?invoice", "secured?.update", "security breach", + "security.notice", "securlty", "signed.*delivery", - "status of your .{314}? ?delivery", + "status of your (.{314})? ?delivery", "susp[il1]+c[il1]+ous.*act[il1]+v[il1]+ty", "suspicious.*sign.*[io]n", "suspicious.activit", diff --git a/signals/headers/headers_urlhaus_domain.yml b/signals/headers/headers_urlhaus_domain.yml new file mode 100644 index 00000000000..3816bed8601 --- /dev/null +++ b/signals/headers/headers_urlhaus_domain.yml @@ -0,0 +1,7 @@ +name: "Headers: URLHaus Domain" +type: "query" +source: | + any(headers.domains, + .root_domain in $abuse_ch_urlhaus_domains_trusted_reporters + and .root_domain not in $tranco_1m + ) \ No newline at end of file diff --git a/signals/links/link_contains_recipient_email.yml b/signals/links/link_contains_recipient_email.yml index f1ab8f78932..25b2b187055 100644 --- a/signals/links/link_contains_recipient_email.yml +++ b/signals/links/link_contains_recipient_email.yml @@ -1,5 +1,5 @@ name: "Link: Contains Recipient Email" type: "query" source: | - any(body.links, any(recipients.to, strings.icontains(..href_url.query_params, .email.email))) + any(body.links, any(recipients.to, strings.icontains(..href_url.url, .email.email))) diff --git a/signals/links/link_contains_unicode_characters.yml b/signals/links/link_contains_unicode_characters.yml new file mode 100644 index 00000000000..109549ac9e2 --- /dev/null +++ b/signals/links/link_contains_unicode_characters.yml @@ -0,0 +1,5 @@ +name: "Link: URL with Unicode U+2044 (⁄) or U+2215 (∕) characters" +type: "query" +source: | + regex.icontains(body.plain.raw, 'https?:\/\/[^\s⁄∕]+(?:\/[^\s⁄∕]+)*[⁄∕][^\s⁄∕]+') + or any(body.links, regex.icontains(.href_url.url, 'https?:\/\/[^\s⁄∕]+(?:\/[^\s⁄∕]+)*[⁄∕][^\s⁄∕]+')) diff --git a/signals/links/link_count_distinct_display_text.yml b/signals/links/link_count_distinct_display_text.yml new file mode 100644 index 00000000000..a149a7d56bf --- /dev/null +++ b/signals/links/link_count_distinct_display_text.yml @@ -0,0 +1,4 @@ +name: "Link: Count Unique Display Text" +type: "query" +source: | + length(distinct(body.links, .href_url.url)) diff --git a/signals/links/link_domains_do_not_match_sender_domain.yml b/signals/links/link_domains_do_not_match_sender_domain.yml new file mode 100644 index 00000000000..85d2dac7395 --- /dev/null +++ b/signals/links/link_domains_do_not_match_sender_domain.yml @@ -0,0 +1,8 @@ +name: "Link: Sender domain does not match any body links" +type: "query" +source: | + 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 + ) diff --git a/signals/links/link_ipfs.yml b/signals/links/link_ipfs.yml new file mode 100644 index 00000000000..7c72380158d --- /dev/null +++ b/signals/links/link_ipfs.yml @@ -0,0 +1,26 @@ +name: "Link: IPFS" +type: "query" +source: | + any(body.links, + // Any body link domains contain "ipfs" + strings.icontains(.href_url.domain.domain, "ipfs") + + // 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 + ) + ) + ) + + // adding negation block for legitimate domains with ipfs in their name + and not sender.email.domain.domain in ("shipfsl.com") diff --git a/signals/links/link_same_through_msg.yml b/signals/links/link_same_through_msg.yml new file mode 100644 index 00000000000..cdea808029d --- /dev/null +++ b/signals/links/link_same_through_msg.yml @@ -0,0 +1,6 @@ +name: "Link: Same URL with different Display Texts" +type: "query" +source: | + length(body.links) > 1 + and length(distinct(body.links, .href_url.url)) == 1 + and length(distinct(body.links, .display_text)) > 1 diff --git a/signals/sender/sender_display_contains_recipient_domain.yml b/signals/sender/sender_display_contains_recipient_domain.yml new file mode 100644 index 00000000000..832d5a76014 --- /dev/null +++ b/signals/sender/sender_display_contains_recipient_domain.yml @@ -0,0 +1,4 @@ +name: "Sender: Display Name Contains Recipient Root Domain" +type: "query" +source: | + any(recipients.to, strings.icontains(sender.display_name, .email.domain.root_domain)) diff --git a/signals/sender/sender_display_name_contains_email.yml b/signals/sender/sender_display_name_contains_email.yml new file mode 100644 index 00000000000..3727c526200 --- /dev/null +++ b/signals/sender/sender_display_name_contains_email.yml @@ -0,0 +1,5 @@ + +name: "Sender: Display Name Contains Email Address" +type: "query" +source: | + regex.contains(sender.display_name, '[a-z0-9]+@[a-z]+') From f107a5a5b32c262968dfec9cb0a3d53286f6c59c Mon Sep 17 00:00:00 2001 From: Bobby Filar <29960025+bfilar@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:29:02 -0500 Subject: [PATCH 15/16] New Rule: Body contains Advance Fee language (#856) Co-authored-by: ID Generator Co-authored-by: Sam Scholten --- .../body_advance_fee_new_sender.yml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 detection-rules/body_advance_fee_new_sender.yml diff --git a/detection-rules/body_advance_fee_new_sender.yml b/detection-rules/body_advance_fee_new_sender.yml new file mode 100644 index 00000000000..64bd291bc40 --- /dev/null +++ b/detection-rules/body_advance_fee_new_sender.yml @@ -0,0 +1,46 @@ +name: "Body: Advanced Fee Fraud (AFF) from Freemail providers or Suspicious TLDs" +description: | + Advanced Fee Fraud (AFF) is a type of BEC/Fraud involving upfront fees for promised + future returns, such as lottery scams, inheritance payouts, and investment opportunities. + This rule identifies messages from Freemail domains or suspicious TLDS, including those + with suspicious reply-to addresses. It utilizes Natural Language Understanding to detect + AFF language in their contents. +type: "rule" +severity: "medium" +source: | + type.inbound + and ( + sender.email.domain.domain in $free_email_providers + or ( + length(headers.reply_to) > 0 + and all(headers.reply_to, + ( + .email.domain.root_domain in $free_email_providers + or .email.domain.tld in $suspicious_tlds + ) + and .email.email != sender.email.email + ) + ) + or sender.email.domain.tld in $suspicious_tlds + ) + and any(ml.nlu_classifier(body.current_thread.text).tags, + .name == "advance_fee" and .confidence in ("medium", "high") + ) + and ( + profile.by_sender().prevalence in ("new", "outlier") + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) + ) + +attack_types: + - "BEC/Fraud" +tactics_and_techniques: + - "Social engineering" +detection_methods: + - "Content analysis" + - "Header analysis" + - "Natural Language Understanding" + - "Sender analysis" +id: "6a5af373-a97b-5013-aeec-42ac8b4b8ba1" From 234287d70807cd10ba00892ad4c059c4f168b5cb Mon Sep 17 00:00:00 2001 From: Aiden Mitchell Date: Tue, 17 Oct 2023 11:00:44 -0700 Subject: [PATCH 16/16] Updating rule: link_download_suspicious_file.yml (#851) --- detection-rules/link_download_suspicious_file.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/detection-rules/link_download_suspicious_file.yml b/detection-rules/link_download_suspicious_file.yml index 367753b3220..711a0f56079 100644 --- a/detection-rules/link_download_suspicious_file.yml +++ b/detection-rules/link_download_suspicious_file.yml @@ -24,12 +24,13 @@ source: | // .zip.attempted_files "encrypted_zip" in .flavors.yara and any(.scan.zip.attempted_files, - strings.ilike(., "*.lnk", "*.js", "*.vba", "*.vbs", "*.vbe") + strings.ilike(., "*.???*.exe", "*.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") + or strings.ilike(.file_name, "*.???*.exe") ) ) )