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"