-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create PR2167_link_credential_phishing_voicemail_language.yml by @zoomequipd #2167 Source SHA 327d92a Triggered by @zoomequipd
- Loading branch information
Sublime Rule Testing Bot
committed
Nov 25, 2024
1 parent
cf02228
commit 506af7e
Showing
1 changed file
with
19 additions
and
0 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
detection-rules/PR2167_link_credential_phishing_voicemail_language.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: "PR#2167 - Fake voicemail notification (untrusted sender)" | ||
description: | | ||
This rule detects a common credential phishing vector enticing the user to engage with links under the premise that they have a voicemail to retrieve. | ||
The rule looks for voicemail verbiage in the display name, body, subject or a combination of those elements with emojis or a medium to high credential theft NLU Intent from first-time + unsolicited sender. | ||
type: "rule" | ||
severity: "medium" | ||
source: "type.inbound\n// contains links or attachments\nand (0 < length(body.links) <= 15 or 0 < length(attachments) <= 3)\n// the subject or display_name need some keywords which are voicemail related\nand (\n any([subject.subject, sender.display_name],\n regex.icontains(.,\n // split phrases that occur within 3 words between or only punctuation between them\n '(?:v[nm](\\b|[[:punct:]])?|\\bvoice(?:mail|message)?|audio|incoming|missed(?:\\sa\\s)?|left( a)?|wireless)(?:\\w+(\\s\\w+)?|[[:punct:]]+|\\s+){0,3}(?:mail|message|msg|recording|received|notif|support|ca[li1][li1]\\d*\\b|ca[il1][il1](?:er)?|log|transcript(?:ion)?\\b)',\n // split phrases that start with \"caller\" that occur within 3 words between or only punctation \n 'ca[li1][li1](?:er)?(?:\\w+(\\s\\w+)?|[[:punct:]]+|\\s+){0,3}(?:v[nm](\\b|[[:punct:]])?|\\bvoice(?:mail|message)?|audio|missed(?:\\sa\\s)?|left( a)?)',\n // strong phrases\n '(?:open mp3|audio note|\\.wav|left a vm|[^\\s]+voip[^\\s]*|unanswered.*ca[li1][li1]|incoming.vm|left msg|wireless ca[li1][li1]er|VM Service|voice message|missed.ca[li1][li1](?:e[rd])?|ca[li1][li1].(?:support|service)(?: for| log)?|missed.{0,10} VM|new voicemail from|new.v.m.from.\\+?\\d+|new voicemail?(?:\\w+(\\s\\w+)?|[[:punct:]]+|\\s+){0,3}transcript(s|ion)?|message received)',\n // starts in the format of `(4)` and contains some voicemail keywords\n '^\\(\\d\\)\\s(?:\\w+(\\s\\w+)?|[[:punct:]]+|\\s+){0,3}(?:message|voip|voice|unread|call)',\n 'ca[li1][li1](?:er)?(?:\\w+(\\s\\w+)?|[[:punct:]]+|\\s+){0,3}(?:playback|transcript)',\n\n // obfuscated phone number with at least one digit in the area code and at least one obfuscated number in the last group\n // 555-555-555X, 555-555-XXXX, 555-5XX-XXXX\n '\\b1?\\(?(\\d{3}|\\d{2}[\\*X]|\\d[\\*X]{2})\\)?[^a-z0-9]{0,2}(\\d{2,3}|\\d{2}[\\*X]|\\d[\\*X]{2}|[\\*X]{2,3})[^a-z0-9]{0,4}(\\d{3}[\\*X]|\\d{2}[\\*X]{2}|\\d[\\*X]{3}|[\\*X]{3,4})[^0-9]',\n // obfuscated phone number with at least one digit in the prefix\n // XXX-555-5555, XXX-5XX-XXXX\n '\\b1?\\(?(\\d{2}[\\*X]|\\d[\\*X]{2}|[\\*X]{2,3})\\)?[^a-z0-9]{0,2}(\\d{2,3}|\\d{2}[\\*X]|\\d[\\*X]{2})[^a-z0-9]{0,4}(\\d{4}|\\d{3}[\\*X]|\\d{2}[\\*X]{2}|\\d[\\*X]{3}|[\\*X]{3,4})\\b',\n )\n )\n // body.current_thread.text inspection should be very specific to avoid FP\n or regex.icontains(\n strings.replace_confusables(body.current_thread.text),\n //body.current_thread.text,\n 'you (?:have |received )*(?:\\w+(\\s\\w+)?|[[:punct:]]+|\\s+){0,3}\\bvoice\\s?(?:mail|audio|message)',\n 'sent (?:from|by) (?:your )?voice (?:mail )?system',\n 'new (?:voice(?:mail)?|audio) (?:message|notification|record)',\n 'voicemail (is )?attached',\n 'an? (?:new )?encrypted voicemail',\n 'a (?:new )?pending message',\n 'Your? have (?: an?)?incoming voiceRec',\n \"you(?:\\'ve| have) a (?:new )?missed ca[li1][li1]\",\n 'New Voicemail Received',\n 'left you a (?:\\w+(\\s\\w+)?|[[:punct:]]+|\\s+){0,3}(?:voice(?:mail)?|audio)(?: message)?',\n 'New missed ca[li1][li1] record',\n 'voicemail transcript(?:ion)?',\n 'Listen to VoiceMail'\n )\n // phishing template observed https://platform.sublime.security/messages/341eed2be003036cdd3eeee575202df8a7472b6567d0dfa0f99c3b3fb42a8e7f\n or strings.icontains(body.html.raw, '<title>Voicemail Notification</title>')\n or strings.icontains(body.html.raw, '<!-- Voicemail phone logo')\n)\n\nand 2 of (\n (\n // the sender is a freemail\n sender.email.domain.root_domain in $free_email_providers\n ),\n (\n any(ml.nlu_classifier(body.current_thread.text).intents,\n .name in (\"cred_theft\") and .confidence in (\"medium\", \"high\")\n )\n ),\n (\n any(attachments,\n .content_type in (\"html\", \"text\", \"text/html\")\n and any(ml.logo_detect(file.html_screenshot(.)).brands,\n .name in (\"Microsoft\") and .confidence in (\"medium\", \"high\")\n )\n )\n ),\n (\n regex.icontains(sender.display_name,\n '(voice|audio|call|missed|caii)(\\s?|-)(mail|message|recording|call|caii)|(transcription|Caller.?ID)'\n )\n ),\n // attachment names are often HTML and voice mail related\n (\n any(attachments,\n (\n .content_type in (\"html\", \"text\", \"text/html\")\n or .file_type in (\"html\", \"unknown\")\n or .file_type == \"pdf\"\n )\n and (\n regex.icontains(.file_name,\n '(?:voice|audio|call|missed|caii|mail|message|recording|call|caii|transcription|v[nm]|audio|play|listen|unheard|msg)',\n // contains a time\n // 01min , 60secs\n '0?[1-9]\\s*min(?:(?:ute)?s)?',\n '\\d{1,2}\\s*s(?:ec(?:ond)?s)?',\n // (00:50s)\n // 3:26 seconds\n '[\\(\\[]?(?:\\d{1,2}[\\:\\s-])\\d{1,2}[\\)\\]]?\\s*(?:s(?:(?:ecs?)onds)?)[\\)\\]]?',\n // 03min25secs\n '0?[1-9]\\s*min(?:(?:ute)?s)?\\d{1,2}\\s*s(?:ec(?:ond)?s)?',\n // [0:39] \n // (0:39) \n '[\\(\\[](?:\\d{1,2}[\\:\\s-])\\d{1,2}[\\)\\]]\\s',\n // contains an emoji\n '[\\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}]'\n )\n // somtimes there is no name, it's just the extension which is also strange\n or .file_name in~ (\".htm\", \".html\")\n // or sometimes it has no name....\n or .file_name is null\n )\n )\n ),\n // html attachment is small and contains javascript\n (\n any(attachments,\n (\n .content_type in (\"html\", \"text\", \"text/html\")\n or .file_type in (\"html\", \"unknown\")\n )\n and (.size < 1500 and any(file.explode(.), length(.scan.html.scripts) > 0)\n )\n )\n ),\n (\n any(attachments,\n (\n .content_type in (\"html\", \"text\", \"text/html\")\n or .file_type in (\"html\", \"unknown\")\n )\n and any(recipients.to,\n // the html attachment contains a receipient email address\n strings.contains(file.parse_html(..).raw, .email.email)\n // the sld of the domain is in the attachment name\n or strings.contains(..file_name, .email.domain.sld)\n )\n )\n ),\n // the body links contain the recipients email\n (\n length(filter(recipients.to, .email.email != \"\" or .email.domain.valid)) > 0\n and any(body.links,\n any(recipients.to,\n strings.icontains(..href_url.url, .email.email)\n or strings.icontains(..href_url.url, .email.local_part)\n )\n )\n ),\n (\n length(body.current_thread.text) < 700\n and regex.icontains(body.current_thread.text,\n 'Méssãge|Méssage|Recéived|Addréss'\n )\n ),\n (\n // sender domain matches no body domains\n // only inspect \"links\" that have a display_text and display_url is null to remove \"plain text\" email address from being caught\n length(filter(body.links,\n .display_text is not null and .display_url.url is null and .href_url.domain.valid\n )\n ) > 0\n and all(filter(body.links,\n .display_text is not null and .display_url.url is null and .href_url.domain.valid\n ),\n .href_url.domain.root_domain != sender.email.domain.root_domain\n and .href_url.domain.root_domain not in $org_domains\n and .href_url.domain.root_domain not in (\"aka.ms\")\n and .href_url.domain.root_domain not in (\n \"unitelvoice.com\",\n \"googleapis.com\",\n \"dialmycalls.com\",\n \"ringcentral.biz\"\n )\n )\n ),\n // the body links contain vm related phrases\n (\n any(body.links,\n regex.contains(.display_text, '[^a-z]*[A-Z][^a-z]*')\n and regex.icontains(.display_text,\n '(v[nm]|voice|audio|call|missed|caii)(\\s?|-)(mail|message|recording|call|caii)|transcription|open mp3|audio note|listen|playback|\\(?(?:\\*\\*\\*|[0-9]{3})?.(?:\\*\\*\\*|[0-9]{3})[^a-z]{0,2}(?:\\*{4}|\\d+\\*+)|play'\n )\n // negate FP terms in link display texts\n and not strings.icontains(.display_text, 'voice call center')\n )\n ),\n (\n any(body.links,\n .href_url.path == \"/ctt\"\n and regex.icontains(.display_text,\n '(v[nm]|voice|audio|call|missed|caii)(\\s?|-)(mail|message|recording|call|caii)|transcription|open mp3|audio note|listen|playback|\\(?(?:\\*\\*\\*|[0-9]{3})?.(?:\\*\\*\\*|[0-9]{3})[^a-z]{0,2}(?:\\*{4}|\\d+\\*+)|play'\n )\n // negate FP terms in link display texts\n and not strings.icontains(.display_text, 'voice call center')\n )\n ),\n // new domains\n (\n any(body.links,\n network.whois(.href_url.domain).days_old < 10\n and not strings.icontains(.href_url.path, \"unsubscribe\")\n )\n ),\n (\n any(recipients.to,\n // recipient's SLD is in the sender's display name\n strings.icontains(sender.display_name, .email.domain.sld)\n // recipient's SLD is in the sender's display name\n or strings.icontains(subject.subject, .email.domain.sld)\n )\n ),\n // often times the subject or sender display name will contain time references\n (\n any([sender.display_name, subject.subject, body.current_thread.text],\n regex.icontains(.,\n // 01min , 60secs\n '0?[1-9]\\s*min(?:(?:ute)?s)?\\b',\n '\\d{1,2}\\s*s(?:ec(?:ond)?s)?\\b',\n // (00:50s)\n // 3:26 seconds\n '[\\(\\[]?(?:\\d{1,2}[\\:\\s-])\\d{1,2}[\\)\\]]?\\s*(?:s(?:(?:ecs?)onds)?)[\\)\\]]?',\n // 03min25secs\n '0?[1-9]\\s*min(?:(?:ute)?s)?\\d{1,2}\\s*s(?:ec(?:ond)?s)?',\n // [0:39] \n // (0:39) \n '[\\(\\[](?:\\d{1,2}[\\:\\s-])\\d{1,2}[\\)\\]]\\s'\n )\n )\n ),\n // often times the subject or sender display name will contain dates\n (\n any([sender.display_name, subject.subject],\n // days of week\n any([\n 'monday',\n 'tuesday',\n 'wednesday',\n 'thursday',\n 'friday',\n 'saturday',\n 'sunday'\n ],\n strings.icontains(.., .)\n )\n // months\n // may is problematic for words like \"Mayor\", \"Maybe\", \"MayFlower\", etc\n or any([\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\"\n ],\n strings.icontains(.., .)\n )\n // use a regex for May\n or regex.icontains(., '\\bmay\\b')\n // common date formats\n or regex.contains(.,\n // YYYY-MM-DD or YY-MM-DD (ISO 8601 format)\n '\\d{2}(\\d{2})?-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])',\n // MM/DD/YYYY or MM/DD/YY (US format)\n '(0[1-9]|1[0-2])/(0[1-9]|[12]\\d|3[01])/\\d{2}(\\d{2})?',\n // DD/MM/YYYY or DD/MM/YY (European format)\n '(0[1-9]|[12]\\d|3[01])/(0[1-9]|1[0-2])/\\d{2}(\\d{2})?',\n // Month DD, YYYY or Month DD, YY (e.g., March 15, 2024 or March 15, 24)\n '(January|February|March|April|May|June|July|August|September|October|November|December) (0[1-9]|[12]\\d|3[01]), \\d{2}(\\d{2})?'\n )\n // common time formats\n or regex.contains(.,\n // Example: 23:45, 08:30\n '([01]\\d|2[0-3]):([0-5]\\d)',\n // Example: 23:45:59, 08:30:12\n '([01]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)',\n // Example: 08:30 AM, 12:45 pm\n '(0[1-9]|1[0-2]):([0-5]\\d)\\s?([AaPp][Mm])',\n // Example: 08:30 AM, 12:45 pm\n '(0[1-9]|1[0-2]):([0-5]\\d):([0-5]\\d) ?([AaPp][Mm])'\n )\n )\n ),\n // there are often emoji in the sender display name\n (\n any([sender.display_name, subject.subject],\n // contains an emoji\n regex.contains(.,\n '[\\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}]'\n )\n // negate where the emoji occur in tags\n and not regex.contains(.,\n '^(?:\\[[^\\]]*\\]\\s*)*\\[[^\\]]*[\\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}][^\\]]*\\]'\n )\n )\n ),\n // an attachment is a pdf or image that contains a url\n (\n 1 <= length(attachments) <= 2\n and any(attachments,\n (.file_type in $file_types_images or .file_type == \"pdf\")\n and any(file.explode(.),\n .scan.qr.type == \"url\"\n or strings.icontains(.scan.qr.data, 'http')\n or any(recipients.to,\n strings.icontains(..scan.qr.data, .email.local_part)\n or strings.icontains(..scan.qr.data, .email.email)\n )\n )\n )\n )\n)\n\n// negating legit replies and legitimate audio file attachments and known voicemail senders\nand not (\n sender.email.domain.valid\n and sender.email.domain.root_domain in (\n \"magicjack.com\",\n \"unitelvoice.com\",\n \"voipinterface.net\",\n \"ringcentral.biz\",\n \"verizonwireless.com\",\n \"t-mobile.com\",\n \"justcall.io\"\n )\n)\nand not any(attachments, strings.starts_with(.content_type, \"audio\"))\nand not (\n (\n strings.istarts_with(subject.subject, \"RE:\")\n // out of office auto-reply\n // the NLU model will handle these better natively soon\n or strings.istarts_with(subject.subject, \"Automatic reply:\")\n )\n and (\n length(headers.references) > 0\n or any(headers.hops, any(.fields, strings.ilike(.name, \"In-Reply-To\")))\n )\n)\n// negate highly trusted sender domains unless they fail DMARC authentication\nand (\n (\n sender.email.domain.root_domain in $high_trust_sender_root_domains\n and not headers.auth_summary.dmarc.pass\n )\n or sender.email.domain.root_domain not in $high_trust_sender_root_domains\n)\n// bounce-back negations\nand not any(attachments,\n any(file.parse_eml(.).attachments,\n .content_type == \"message/delivery-status\"\n )\n )\n// bounce-back negations\nand not (\n any(attachments,\n .content_type in (\"message/delivery-status\", \"text/calendar\")\n )\n)\n// negate bouncebacks from proofpoint\nand not (\n sender.display_name == \"Mail Delivery Subsystem\"\n and strings.ends_with(headers.message_id, \"pphosted.com>\")\n and any(headers.hops,\n .index == 0 and strings.contains(.received.server.raw, \"pphosted.com\")\n )\n and any(attachments, .content_type == \"message/rfc822\")\n)\n// sender profile\nand (\n (\n profile.by_sender().prevalence not in (\"common\") // this avoids hitting on legitmate voicemail \n or not profile.by_sender_email().solicited\n )\n or (\n profile.by_sender().any_messages_malicious_or_spam\n and not profile.by_sender().any_false_positives\n )\n)\n" | ||
attack_types: | ||
- "Credential Phishing" | ||
tactics_and_techniques: | ||
- "Social engineering" | ||
detection_methods: | ||
- "Content analysis" | ||
- "Natural Language Understanding" | ||
- "Sender analysis" | ||
- "URL analysis" | ||
id: "c5a1d510-05f7-4cd8-bc78-d70d0d204949" | ||
testing_pr: 2167 | ||
testing_sha: 327d92a05c5b12afe6cbf52f399ea7ffc4c4dfa4 |