diff --git a/detection-rules/attachment_any_html_new_sender.yml b/detection-rules/attachment_any_html_new_sender.yml index 303df0db404..24b9045117d 100644 --- a/detection-rules/attachment_any_html_new_sender.yml +++ b/detection-rules/attachment_any_html_new_sender.yml @@ -12,7 +12,10 @@ source: | type.inbound and any(attachments, .file_extension in~ ('htm', 'html') or .file_type == "html") and ( - profile.by_sender().prevalence in ("new", "outlier") + ( + profile.by_sender().prevalence in ("new", "outlier") + and not profile.by_sender().solicited + ) or profile.by_sender().any_messages_malicious_or_spam ) and not profile.by_sender().any_false_positives diff --git a/detection-rules/attachment_eml_cred_theft.yml b/detection-rules/attachment_eml_cred_theft.yml index 39555ddc1e5..e6b862102d5 100644 --- a/detection-rules/attachment_eml_cred_theft.yml +++ b/detection-rules/attachment_eml_cred_theft.yml @@ -1,36 +1,61 @@ name: "Attachment: EML with link to credential phishing page" description: | - Attached EML links to a credential phishing site. + Attached EML links to a credential phishing site or exhibits unusual behavior such as multiple suspicious redirects. type: "rule" severity: "medium" source: | type.inbound and length(attachments) == 1 and any(attachments, - .content_type == "message/rfc822" - and ( - any(file.explode(.), - any(.scan.url.urls, - ( - ( - .domain.root_domain in $free_subdomain_hosts - or .domain.root_domain in ("sharepoint.com") - or .domain.root_domain not in $tranco_1m - ) - and beta.linkanalysis(.).credphish.disposition == "phishing" - ) - // or any links in the final dom lead to a suspicious tld - or any(beta.linkanalysis(.).final_dom.links, - beta.linkanalysis(.href_url).effective_url.domain.tld in $suspicious_tlds + (.content_type == "message/rfc822" or .file_extension =~ "eml") + and any(file.parse_eml(.).body.links, + ( + beta.linkanalysis(., mode="aggressive").credphish.disposition == "phishing" + and beta.linkanalysis(., mode="aggressive").credphish.confidence in ( + "medium", + "high" ) - ) + ) + + // or any links in the final dom lead to a suspicious tld + or any(beta.linkanalysis(.).final_dom.links, + .href_url.domain.tld in $suspicious_tlds + or beta.linkanalysis(.href_url).effective_url.domain.tld in $suspicious_tlds + ) + + // link redirects to a suspicious TLD + or any(beta.linkanalysis(., mode="aggressive").redirect_history, + .domain.tld in $suspicious_tlds + ) + or ( + // suspicious redirects + // 3 or more different domains with 2 or more different TLDs + // careful because click trackers will always make this at least 2 + // different domains and not unlikely 2 or more TLDs + length(distinct(map(beta.linkanalysis(., mode="aggressive").redirect_history, + .domain.tld + ) + ) + ) >= 2 + and length(distinct(map(beta.linkanalysis(., + mode="aggressive" + ).redirect_history, + .domain.domain + ) + ) + ) >= 3 + ) + ) + // engaging language in the original body or EML + and ( + any(ml.nlu_classifier(body.html.display_text).entities, + .name == "request" + ) + or any(ml.nlu_classifier(file.parse_eml(.).body.html.display_text).entities, + .name == "request" ) ) ) - - // engaging language in the original body - and any(ml.nlu_classifier(body.html.display_text).entities, .name == "request") - // exclude bounce backs & read receipts and not strings.like(sender.email.local_part, "*postmaster*", @@ -48,6 +73,7 @@ source: | and not profile.by_sender().any_false_positives ) ) + and not profile.by_sender().any_false_positives attack_types: - "Credential Phishing" diff --git a/detection-rules/attachment_office_suspicious_functions.yml b/detection-rules/attachment_office_suspicious_functions.yml new file mode 100644 index 00000000000..305e00f0d34 --- /dev/null +++ b/detection-rules/attachment_office_suspicious_functions.yml @@ -0,0 +1,41 @@ +name: "Attachment: Office file with suspicious function calls or downloaded file path" +description: "Attached Office file contains suspicious function calls or known malicious file path pattern." +references: + - "https://app.docguard.io/c3e75d7a32a4959724f24c1004724951482cd732db7d287989c873c09166ff95/c3036de5-89b1-49c6-9681-706f5b9af264/0/results/dashboard" +type: "rule" +severity: "high" +source: | + type.inbound + and any(attachments, + ( + // office files + .file_extension in~ $file_extensions_macros + or .file_extension in~ $file_extensions_common_archives + or ( + .file_extension is null + and .file_type == "unknown" + and .content_type == "application/octet-stream" + and .size < 100000 + ) + ) + and ( + any(file.explode(.), + ( + any(.scan.strings.strings, strings.ilike(., '*URLDownloadToFile*')) + and any(.scan.strings.strings, strings.ilike(., '*Auto_Open*')) + ) + or any(.scan.strings.strings, + regex.icontains(., 'C:\\[A-Za-z]{7}\\[A-Za-z]{7}\\[A-Za-z]{7}') + ) + ) + ) + ) +attack_types: + - "Malware/Ransomware" +tactics_and_techniques: + - "Evasion" + - "Scripting" +detection_methods: + - "Archive analysis" + - "File analysis" +id: "4c78b969-9df8-59e1-8f65-43afdb06c817" diff --git a/detection-rules/credential_phishing_docusign_embedded_image_lure.yml b/detection-rules/credential_phishing_docusign_embedded_image_lure.yml new file mode 100644 index 00000000000..809dddbe2a4 --- /dev/null +++ b/detection-rules/credential_phishing_docusign_embedded_image_lure.yml @@ -0,0 +1,53 @@ +name: "Credential Phishing: DocuSign embedded image lure with no DocuSign domains in links" +description: "Detects DocuSign phishing emails with no DocuSign links, a DocuSign logo embedded in the body of the message, from a new sender." +type: "rule" +severity: "high" +source: | + type.inbound + and length(attachments) == 0 + and any(body.links, + not strings.ilike(.href_url.domain.root_domain, "docusign.*") + ) + and ( + any(ml.logo_detect(beta.message_screenshot()).brands, + .name == "DocuSign" + or any(file.explode(beta.message_screenshot()), + strings.ilike(.scan.ocr.raw, "*DocuSign*") + and any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence != "low" + ) + ) + ) + ) + and any(file.explode(beta.message_screenshot()), + regex.icontains(.scan.ocr.raw, + "review document", + "[^d][^o][^c][^u]sign", + "important edocs", + "completed document" + ) + ) + and ( + ( + not profile.by_sender().solicited + 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: + - "Impersonation: Brand" + - "Social engineering" +detection_methods: + - "Computer Vision" + - "Content analysis" + - "Header analysis" + - "Natural Language Understanding" + - "Optical Character Recognition" + - "Sender analysis" +id: "dfe8715e-6318-579b-9131-ddfc9854dc95" diff --git a/detection-rules/headers_replyto_new_domain_nlu_request.yml b/detection-rules/headers_replyto_new_domain_nlu_request.yml index 65b1bd2945b..3196791752e 100644 --- a/detection-rules/headers_replyto_new_domain_nlu_request.yml +++ b/detection-rules/headers_replyto_new_domain_nlu_request.yml @@ -21,6 +21,13 @@ source: | .name is not null and .confidence in ("medium", "high") ) ) + and ( + not profile.by_sender().solicited + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) + ) and not profile.by_sender().any_false_positives attack_types: diff --git a/detection-rules/image_as_content_open_redir.yml b/detection-rules/image_as_content_open_redir.yml new file mode 100644 index 00000000000..8deb03c68b7 --- /dev/null +++ b/detection-rules/image_as_content_open_redir.yml @@ -0,0 +1,51 @@ +name: "Image as content linking to an open redirect" +description: "Body contains little, no, or only disclaimer text, and an image linking to an open redirect." +type: "rule" +severity: "high" +source: | + type.inbound + and length(body.links) < 3 + and 0 < (length(attachments)) < 3 + and all(attachments, (.file_type in $file_types_images)) + and ( + // body text is very short + ( + 0 <= (length(body.current_thread.text)) < 10 + or body.current_thread.text is null + ) + or ( + length(body.current_thread.text) < 900 + // or body is most likely all warning banner (text contains the sender and common warning banner language) + and ( + ( + strings.contains(body.current_thread.text, sender.email.email) + and strings.contains(body.current_thread.text, 'caution') + ) + or regex.icontains(body.current_thread.text, + "intended recipient's use only|external email|sent from outside|you don't often|confidential" + ) + ) + ) + ) + and ( + any(body.links, + any(.href_url.rewrite.encoders, strings.icontains(., "open_redirect")) + ) + or any(body.links, + .href_url.domain.root_domain == 'sng.link' + and strings.ilike(.href_url.query_params, "*fallback_redirect*") + ) + ) +attack_types: + - "Credential Phishing" + - "Malware/Ransomware" +tactics_and_techniques: + - "Evasion" + - "Image as content" + - "Open redirect" + - "Social engineering" +detection_methods: + - "Content analysis" + - "HTML analysis" + - "URL analysis" +id: "f5cec36b-76ea-5cd6-958b-74f819d73a47" diff --git a/detection-rules/impersonation_adobe_suspicious_language_link.yml b/detection-rules/impersonation_adobe_suspicious_language_link.yml new file mode 100644 index 00000000000..5cce19644c1 --- /dev/null +++ b/detection-rules/impersonation_adobe_suspicious_language_link.yml @@ -0,0 +1,63 @@ +name: "Brand impersonation: Adobe with suspicious language and link" +description: "Email contains an Adobe logo, at least one link, and suspicious link language from a new sender." +type: "rule" +severity: "high" +source: | + type.inbound + and length(attachments) == 0 + and length(body.links) > 0 + and any(ml.logo_detect(beta.message_screenshot()).brands, + .name == "Adobe" and .confidence in ("high") + ) + and ( + any(file.explode(beta.message_screenshot()), + strings.ilike(.scan.ocr.raw, + "*review*", + "*sign*", + "*view*", + "*completed document*", + "*open agreement*", + "*open document*" + ) + ) + or any(body.links, + strings.ilike(.display_text, + "*review*", + "*sign*", + "*view*", + "*completed document*", + "*open agreement*", + "*open document*" + ) + ) + ) + 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 + ) + ) + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "Impersonation: Brand" + - "Social engineering" +detection_methods: + - "Computer Vision" + - "Content analysis" + - "Header analysis" + - "Sender analysis" +id: "32cc8bf1-f4d7-549f-a970-eade24b7c6ae" diff --git a/detection-rules/impersonation_dotloop.yml b/detection-rules/impersonation_dotloop.yml new file mode 100644 index 00000000000..7c0797e311d --- /dev/null +++ b/detection-rules/impersonation_dotloop.yml @@ -0,0 +1,41 @@ +name: "Brand impersonation: Dotloop" +description: "Impersonation of Dotloop, a real estate transaction management platform." +type: "rule" +severity: "medium" +source: | + type.inbound + and ( + strings.ilike(sender.display_name, '*dotloop*') + or strings.ilike(sender.email.domain.domain, '*dotloop*') + ) + and sender.email.domain.root_domain not in~ ('dotloop.com', 'showingtime.com') + and ( + ( + profile.by_sender().prevalence in ("new", "outlier") + and not profile.by_sender().solicited + ) + or profile.by_sender().any_messages_malicious_or_spam + ) + and not profile.by_sender().any_false_positives + + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "Impersonation: Brand" + - "Social engineering" +detection_methods: + - "Header analysis" + - "Sender analysis" +id: "f997581a-ca08-5b21-8a52-ee0ca78fcea5" diff --git a/detection-rules/impersonation_human_resources.yml b/detection-rules/impersonation_human_resources.yml index 0e4a77e8fe4..316da757473 100644 --- a/detection-rules/impersonation_human_resources.yml +++ b/detection-rules/impersonation_human_resources.yml @@ -12,7 +12,15 @@ source: | // Negate common marketing mailers and not regex.icontains(sender.display_name, 'HR (Events|Expert)') - and (0 < length(body.links) < 10 or length(attachments) > 0) + and ( + (0 < length(body.links) < 10 or length(attachments) > 0) + // mass-mailer infra abuse results in an inflated link count due to mailer templates that include links for unsubbing, changing preferences, etc. + // loosening the link count check as a result ensures we fire even with these conditions + or ( + any(body.links, strings.ilike(.display_text, "*unsubscribe*", "update your preferences", "add us to your address book")) + and 0 < length(body.links) < 15 + ) + ) // Request and Urgency and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "request") and any(ml.nlu_classifier(body.current_thread.text).entities, .name == "urgency") diff --git a/detection-rules/impersonation_recipient_domain_display_name.yml b/detection-rules/impersonation_recipient_domain_display_name.yml new file mode 100644 index 00000000000..8093026b2a9 --- /dev/null +++ b/detection-rules/impersonation_recipient_domain_display_name.yml @@ -0,0 +1,77 @@ +name: "Display name impersonation using recipient SLD (new sender)" +description: | + The recipient domain's SLD is used in the sender's display name + in order to impersonate the organization. +type: "rule" +severity: "medium" +source: | + type.inbound + and ( + // recipient SLD is being impersonated in the subject + display name + ( + // these are usually targeted with just 1 recipient, + // but sometimes they CC themselves or have a blank CC + length(recipients.to) + length(recipients.cc) + length(recipients.bcc) <= 2 + and any(recipients.to, + // ensure that we're checking the org SLD + .email.domain.sld in $org_slds + and strings.icontains(sender.display_name, .email.domain.sld) + ) + ) + or ( + // accounts for BCC'd messages where the recipients are empty + // if BCC, sometimes the recipient will be the attacker's email + length(recipients.to) + length(recipients.cc) + length(recipients.bcc) <= 2 + and strings.icontains(sender.display_name, mailbox.email.domain.sld) + ) + ) + + and ( + // at least 1 link or non-image attachment + ( + length(body.links) > 0 + // these attacks all use compromosed senders, so we look for a domain + // that doesn't match the sender's domain to weed out legit messages + and any(body.links, .href_url.domain.root_domain != sender.email.domain.root_domain) + ) + or length(filter(attachments, .file_type not in $file_types_images)) > 0 + ) + + and not ( + strings.contains(sender.display_name, "on behalf of") + and sender.email.domain.root_domain == "microsoftonline.com" + ) + + and all(recipients.to, .email.email != sender.email.email) + + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) + and ( + ( + profile.by_sender().prevalence in ("new", "outlier") + and not profile.by_sender().solicited + ) + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) + ) + and not profile.by_sender().any_false_positives +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "Social engineering" +detection_methods: + - "Header analysis" + - "Sender analysis" +id: "81a8ed12-0e26-5998-90ae-03334f358704" diff --git a/detection-rules/impersonation_recipient_domain_display_name_subject.yml b/detection-rules/impersonation_recipient_domain_display_name_subject.yml new file mode 100644 index 00000000000..6b48c49a252 --- /dev/null +++ b/detection-rules/impersonation_recipient_domain_display_name_subject.yml @@ -0,0 +1,79 @@ +name: "Display name and subject impersonation using recipient SLD (new sender)" +description: | + The recipient domain's SLD is used in the sender's display name + and in the subject to impersonate the organization. +type: "rule" +severity: "medium" +source: | + type.inbound + and ( + // recipient SLD is being impersonated in the subject + display name + ( + // these are usually targeted with just 1 recipient, + // but sometimes they CC themselves or have a blank CC + length(recipients.to) + length(recipients.cc) + length(recipients.bcc) <= 2 + and any(recipients.to, + // ensure that we're checking the org SLD + .email.domain.sld in $org_slds + and strings.icontains(subject.subject, .email.domain.sld) + and strings.icontains(sender.display_name, .email.domain.sld) + ) + ) + or ( + // accounts for BCC'd messages where the recipients are empty + // if BCC, sometimes the recipient will be the attacker's email + length(recipients.to) + length(recipients.cc) + length(recipients.bcc) <= 2 + and strings.icontains(subject.subject, mailbox.email.domain.sld) + and strings.icontains(sender.display_name, mailbox.email.domain.sld) + ) + ) + + and ( + // at least 1 link or non-image attachment + ( + length(body.links) > 0 + // these attacks all use compromosed senders, so we look for a domain + // that doesn't match the sender's domain to weed out legit messages + and any(body.links, .href_url.domain.root_domain != sender.email.domain.root_domain) + ) + or length(filter(attachments, .file_type not in $file_types_images)) > 0 + ) + + and not ( + strings.contains(sender.display_name, "on behalf of") + and sender.email.domain.root_domain == "microsoftonline.com" + ) + + and all(recipients.to, .email.email != sender.email.email) + + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) + and ( + ( + profile.by_sender().prevalence in ("new", "outlier") + and not profile.by_sender().solicited + ) + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) + ) + and not profile.by_sender().any_false_positives +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "Social engineering" +detection_methods: + - "Header analysis" + - "Sender analysis" +id: "cb2b3ed3-268f-5753-9d2b-194d2ee1ed2e" diff --git a/detection-rules/impersonation_twitter.yml b/detection-rules/impersonation_twitter.yml index 82ec602f085..2039f9bed6d 100644 --- a/detection-rules/impersonation_twitter.yml +++ b/detection-rules/impersonation_twitter.yml @@ -12,7 +12,7 @@ source: | or strings.ilevenshtein(sender.display_name, 'twitter') <= 1 or strings.ilike(sender.email.domain.domain, '*twitter*') ) - and sender.email.domain.domain not in~ ('twitter.com', 'privaterelay.appleid.com', 'stripe.com', 'x.com') + and sender.email.domain.domain not in~ ('twitter.com', 'privaterelay.appleid.com', 'stripe.com', 'x.com', 'twitter.discoursemail.com') and sender.email.email not in $recipient_emails attack_types: - "Credential Phishing" diff --git a/detection-rules/link_content_credential_phishing.yml b/detection-rules/link_content_credential_phishing.yml new file mode 100644 index 00000000000..733dfe4874e --- /dev/null +++ b/detection-rules/link_content_credential_phishing.yml @@ -0,0 +1,61 @@ +name: "Credential phishing content and link (first-time sender)" +description: | + Message contains credential theft language and a link to a credential phishing page from an unknown sender. + We use Link Analysis in aggressive mode to increase our chances of scanning. +type: "rule" +severity: "high" +source: | + type.inbound + and ( + any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "cred_theft" and .confidence in ("medium", "high") + ) + // embedded in an image attachment + // note: don't use message_screenshot() for now + // because it's not limited to current_thread and may FP + or any(attachments, + .file_type in $file_types_images + and any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence in ("medium", "high") + ) + ) + ) + ) + and any(body.links, + beta.linkanalysis(., mode="aggressive").credphish.disposition == "phishing" + and beta.linkanalysis(., mode="aggressive").credphish.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 + ) + ) + + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "Social engineering" +detection_methods: + - "Computer Vision" + - "Sender analysis" + - "URL analysis" + - "URL screenshot" +id: "f0c95bb7-afeb-5c8d-a654-74b5e026007f" 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 c75a5b61962..02a008bb949 100644 --- a/detection-rules/link_credential_phishing_intent_and_other_indicators.yml +++ b/detection-rules/link_credential_phishing_intent_and_other_indicators.yml @@ -331,6 +331,18 @@ source: | and not profile.by_sender().any_false_positives ) ) + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) attack_types: - "Credential Phishing" tactics_and_techniques: diff --git a/detection-rules/link_credential_phishing_intent_and_other_indicators_2.yml b/detection-rules/link_credential_phishing_intent_and_other_indicators_2.yml new file mode 100644 index 00000000000..eab55a5ff08 --- /dev/null +++ b/detection-rules/link_credential_phishing_intent_and_other_indicators_2.yml @@ -0,0 +1,112 @@ +name: "Credential phishing language and suspicious indicators (unknown sender)" +description: | + Message contains various suspicious indicators as well as engaging language resembling credential theft from an unknown sender. +type: "rule" +severity: "medium" +source: | + type.inbound + and ( + any(ml.nlu_classifier(body.current_thread.text).intents, + .name == "cred_theft" and .confidence in ("medium", "high") + ) + // embedded in an image attachment + // note: don't use message_screenshot() + // because it's not limited to current_thread and may FP + or any(attachments, + .file_type in $file_types_images + and any(file.explode(.), + any(ml.nlu_classifier(.scan.ocr.raw).intents, + .name == "cred_theft" and .confidence == "high" + ) + ) + ) + ) + and 4 of ( + // impersonation of the recipient's domain or email address + // in the subject to make it look more personalized + any(recipients.to, + strings.icontains(subject.subject, .email.local_part) + or strings.icontains(subject.subject, .email.domain.sld) + ), + // recipient's email address in the body. this is not very uncommon + // for legit credential themed messages either + any(recipients.to, + .email.domain.valid + and strings.icontains(body.current_thread.text, .email.email) + ), + ( + // freemail providers should never be sending this type of email + sender.email.domain.domain in $free_email_providers + + // if not freemail, it's suspicious if the sender's root domain + // doesn't match any links in the body + or ( + length(body.links) > 0 + and all(body.links, + .href_url.domain.root_domain != sender.email.domain.root_domain + ) + ) + ), + strings.contains(body.current_thread.text, + "Your mailbox can no longer send or receive messages." + ), + // link redirects to a suspicious TLD + any(body.links, + any(beta.linkanalysis(., mode="aggressive").redirect_history, .domain.tld in $suspicious_tlds) + ), + ( + // suspicious redirects + // 3 or more different domains with 2 or more different TLDs + // careful because click trackers will always make this at least 2 + // different domains and not unlikely 2 or more TLDs + any(body.links, + length(distinct(map(beta.linkanalysis(., mode="aggressive").redirect_history, + .domain.tld + ) + ) + ) >= 2 + and length(distinct(map(beta.linkanalysis(., mode="aggressive").redirect_history, + .domain.domain + ) + ) + ) >= 3 + ) + ), + // maybe: any brand logo with high confidence + // maybe: recipients BCCd or undisclosed + ) + and ( + ( + profile.by_sender().prevalence in ("new", "outlier") + and not profile.by_sender().solicited + ) + or ( + profile.by_sender().any_messages_malicious_or_spam + and not profile.by_sender().any_false_positives + ) + ) + + // negate highly trusted sender domains unless they fail DMARC authentication + and ( + ( + sender.email.domain.root_domain in $high_trust_sender_root_domains + and ( + any(distinct(headers.hops, .authentication_results.dmarc is not null), + strings.ilike(.authentication_results.dmarc, "*fail") + ) + ) + ) + or sender.email.domain.root_domain not in $high_trust_sender_root_domains + ) +attack_types: + - "Credential Phishing" +tactics_and_techniques: + - "Free email provider" + - "Social engineering" +detection_methods: + - "Content analysis" + - "Header analysis" + - "Natural Language Understanding" + - "Sender analysis" + - "URL analysis" +id: "89c186f7-8c8d-55db-8b6f-da6ead587b1d" diff --git a/detection-rules/qr_code_suspicious_indicators.yml b/detection-rules/qr_code_suspicious_indicators.yml index 838bf8e4756..ded089aca61 100644 --- a/detection-rules/qr_code_suspicious_indicators.yml +++ b/detection-rules/qr_code_suspicious_indicators.yml @@ -15,21 +15,27 @@ source: | // exclude images taken with mobile cameras and screenshots from android and not any(.scan.exiftool.fields, .key == "Model" - or .key == "Software" and strings.starts_with(.value, "Android") + or .key == "Software" + and strings.starts_with(.value, "Android") ) // exclude images taken with mobile cameras and screenshots from Apple and not any(.scan.exiftool.fields, - .key == "DeviceManufacturer" and .value == "Apple Computer Inc." + .key == "DeviceManufacturer" + and .value == "Apple Computer Inc." ) ) ) or ( length(attachments) == 0 - and any(file.explode(beta.message_screenshot()), .scan.qr.type is not null) + and any(file.explode(beta.message_screenshot()), + .scan.qr.type is not null and regex.contains(.scan.qr.data, '\.') + ) ) ) and ( - any(recipients.to, strings.icontains(sender.display_name, .email.domain.sld)) + any(recipients.to, + strings.icontains(sender.display_name, .email.domain.sld) + ) or length(body.current_thread.text) is null or body.current_thread.text == "" or regex.contains(subject.subject, @@ -37,11 +43,16 @@ source: | ) or (any(recipients.to, strings.icontains(subject.subject, .display_name))) or ( - (length(recipients.to) == 0 or all(recipients.to, .display_name == "Undisclosed recipients")) + ( + length(recipients.to) == 0 + or all(recipients.to, .display_name == "Undisclosed recipients") + ) and length(recipients.cc) == 0 and length(recipients.bcc) == 0 ) - or any(file.explode(beta.message_screenshot()), (.scan.qr.url.domain.tld in $suspicious_tlds)) + or any(file.explode(beta.message_screenshot()), + (.scan.qr.url.domain.tld in $suspicious_tlds) + ) or any(attachments, .file_type in $file_types_images and any(file.explode(.), .scan.qr.url.domain.tld in $suspicious_tlds) diff --git a/insights/attachments/links_recipient_email.yml b/insights/attachments/links_recipient_email.yml new file mode 100644 index 00000000000..69527074ca4 --- /dev/null +++ b/insights/attachments/links_recipient_email.yml @@ -0,0 +1,12 @@ +name: "Recipient email in attachment link" +type: "query" +source: | + filter( + map(attachments, + map(file.explode(.), + distinct(map(filter(.scan.url.urls, any(recipients.to, strings.icontains(..url, .email.email))), .url), .) + ) + ), + length(.) > 0 + ) +severity: "medium" diff --git a/insights/links/recipient_address_in_link.yml b/insights/links/recipient_address_in_link.yml new file mode 100644 index 00000000000..b81fd2924d7 --- /dev/null +++ b/insights/links/recipient_address_in_link.yml @@ -0,0 +1,7 @@ +name: "Recipient email in link" +type: "query" +source: | + distinct(map(filter(body.links, any(recipients.to, strings.icontains(..href_url.url, .email.email))), .href_url.url), .) +severity: "low" +tags: + - "Suspicious links"