Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update link_credential_phishing_voicemail_language.yml #2147

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 88 additions & 24 deletions detection-rules/link_credential_phishing_voicemail_language.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ source: |
any([subject.subject, sender.display_name],
regex.icontains(.,
// split phrases that occur within 3 words between or only punctuation between them
'(?: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)',
'(?:v[nm](\b|[[:punct:]])?|\bvoice(?:mail|message)?|audi[o0]|incoming|missed(?:\sa\s)?|left( a)?|wireless|v[[:punct:]])(?:\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)',
// split phrases that start with "caller" that occur within 3 words between or only punctation
'ca[li1][li1](?:er)?(?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}(?:v[nm](\b|[[:punct:]])?|\bvoice(?:mail|message)?|audio|missed(?:\sa\s)?|left( a)?)',
'ca[li1][li1](?:er)?(?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}(?:v[nm](\b|[[:punct:]])?|\bvoice(?:mail|message)?|audi[o0]|missed(?:\sa\s)?|left( a)?)',
// strong phrases
'(?: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])?|\bca[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)',
'(?:open mp3|audi[o0] 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])?|\bca[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)',
// starts in the format of `(4)` and contains some voicemail keywords
'^\(\d\)\s(?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}(?:message|voip|voice|unread|call)',
'ca[li1][li1](?:er)?(?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}(?:playback|transcript)',

// obfuscated phone number with at least one digit in the area code and at least one obfuscated number in the last group
// 555-555-555X, 555-555-XXXX, 555-5XX-XXXX
'\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]',
Expand All @@ -31,19 +31,18 @@ source: |
)
)
// body.current_thread.text inspection should be very specific to avoid FP
or regex.icontains(
strings.replace_confusables(body.current_thread.text),
//body.current_thread.text,
'you (?:have |received )*(?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}\bvoice\s?(?:mail|audio|message)',
or regex.icontains(strings.replace_confusables(body.current_thread.text),
// body.current_thread.text,
'you (?:have |received )*(?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}\bvoice\s?(?:mail|audi[o0]|message)',
'sent (?:from|by) (?:your )?voice (?:mail )?system',
'new (?:voice(?:mail)?|audio) (?:message|notification|record)',
'new (?:voice(?:mail)?|audi[o0]) (?:message|notification|record)',
'voicemail (is )?attached',
'an? (?:new )?encrypted voicemail',
'a (?:new )?pending message',
'Your? have (?: an?)?incoming voiceRec',
"you(?:\'ve| have) a (?:new )?missed ca[li1][li1]",
'New Voicemail Received',
'left you a (?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}(?:voice(?:mail)?|audio)(?: message)?',
'left you a (?:\w+(\s\w+)?|[[:punct:]]+|\s+){0,3}(?:voice(?:mail)?|audi[o0])(?: message)?',
'New missed ca[li1][li1] record',
'voicemail transcript(?:ion)?',
'Listen to VoiceMail',
Expand All @@ -53,7 +52,6 @@ source: |
or strings.icontains(body.html.raw, '<title>Voicemail Notification</title>')
or strings.icontains(body.html.raw, '<!-- Voicemail phone logo')
)

and 2 of (
(
// the sender is a freemail
Expand All @@ -74,20 +72,22 @@ source: |
),
(
regex.icontains(sender.display_name,
'(voice|audio|call|missed|caii)(\s?|-)(mail|message|recording|call|caii)|(transcription|Caller.?ID)'
'(voice|audi[o0]|call|missed|caii)(\s?|-)(mail|message|recording|call|caii)|(transcription|Caller.?ID)'
)
),
// attachment names are often HTML and voice mail related
(
any(attachments,
// this logic is reused below for eml attachments
// ensure updates occur both places
(
.content_type in ("html", "text", "text/html")
or .file_type in ("html", "unknown")
or .file_type == "pdf"
)
and (
regex.icontains(.file_name,
'(?:voice|audio|call|missed|caii|mail|message|recording|call|caii|transcription|v[nm]|audio|play|listen|unheard|msg)',
'(?:voice|audi[o0]|call|missed|caii|mail|message|recording|call|caii|transcription|v[nm]|audi[o0]|play|listen|unheard|msg)',
// contains a time
// 01min , 60secs
'0?[1-9]\s*min(?:(?:ute)?s)?',
Expand Down Expand Up @@ -117,22 +117,81 @@ source: |
.content_type in ("html", "text", "text/html")
or .file_type in ("html", "unknown")
)
and (.size < 1500 and any(file.explode(.), length(.scan.html.scripts) > 0)
and (
.size < 1500 and any(file.explode(.), length(.scan.html.scripts) > 0)
)
)
),
(
any(attachments,
(
.content_type in ("html", "text", "text/html")
or .file_type in ("html", "unknown")
.content_type in ("html", "text", "text/html")
or .file_type in ("html", "unknown")
)
and any(recipients.to,
// the html attachment contains a receipient email address
strings.contains(file.parse_html(..).raw, .email.email)
// the sld of the domain is in the attachment name
or strings.contains(..file_name, .email.domain.sld)
)
)
),
// eml attachments
(
any(filter(attachments, .content_type == "message/rfc822"),
// which contain attachments
// this is the same logic as above
any(file.parse_eml(.).attachments,
(
.content_type in ("html", "text", "text/html")
or .file_type in ("html", "unknown")
or .file_type == "pdf"
)
and (
regex.icontains(.file_name,
'(?:voice|audi[o0]|call|missed|caii|mail|message|recording|call|caii|transcription|v[nm]|audi[o0]|play|listen|unheard|msg)',
// contains a time
// 01min , 60secs
'0?[1-9]\s*min(?:(?:ute)?s)?',
'\d{1,2}\s*s(?:ec(?:ond)?s)?',
// (00:50s)
// 3:26 seconds
'[\(\[]?(?:\d{1,2}[\:\s-])\d{1,2}[\)\]]?\s*(?:s(?:(?:ecs?)onds)?)[\)\]]?',
// 03min25secs
'0?[1-9]\s*min(?:(?:ute)?s)?\d{1,2}\s*s(?:ec(?:ond)?s)?',
// [0:39]
// (0:39)
'[\(\[](?:\d{1,2}[\:\s-])\d{1,2}[\)\]]\s',
// contains an emoji
'[\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}]'
)
// somtimes there is no name, it's just the extension which is also strange
or .file_name in~ (".htm", ".html")
// or sometimes it has no name....
or .file_name is null
)
)
)
),
// attached eml sender/recipeient/subject are all the same as the outer
// and have an attachment or body links
(
any(filter(attachments, .content_type == "message/rfc822"),
// which contain attachments
// this is the same logic as above
file.parse_eml(.).subject.subject == subject.subject
and file.parse_eml(.).sender.email.email == sender.email.email

and (
length(file.parse_eml(.).recipients.to) == length(recipients.to)
and all(recipients.to, .email.email in map(file.parse_eml(..).recipients.to, .email.email))
)
and (
// there are attachments
length(file.parse_eml(.).attachments) > 0
// or body links
or length(filter(file.parse_eml(.).body.links, .href_url.domain.domain not in $org_domains and .href_url.domain.root_domain not in $org_domains)) > 0
)
)
),
// the body links contain the recipients email
Expand All @@ -155,11 +214,15 @@ source: |
// sender domain matches no body domains
// only inspect "links" that have a display_text and display_url is null to remove "plain text" email address from being caught
length(filter(body.links,
.display_text is not null and .display_url.url is null and .href_url.domain.valid
.display_text is not null
and .display_url.url is null
and .href_url.domain.valid
)
) > 0
and all(filter(body.links,
.display_text is not null and .display_url.url is null and .href_url.domain.valid
.display_text is not null
and .display_url.url is null
and .href_url.domain.valid
),
.href_url.domain.root_domain != sender.email.domain.root_domain
and .href_url.domain.root_domain not in $org_domains
Expand All @@ -177,7 +240,7 @@ source: |
any(body.links,
regex.contains(.display_text, '[^a-z]*[A-Z][^a-z]*')
and regex.icontains(.display_text,
'(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'
'(v[nm]|voice|audi[o0]|call|missed|caii)(\s?|-)(mail|message|recording|call|caii)|transcription|open mp3|audi[o0] note|listen|playback|\(?(?:\*\*\*|[0-9]{3})?.(?:\*\*\*|[0-9]{3})[^a-z]{0,2}(?:\*{4}|\d+\*+)|play'
)
// negate FP terms in link display texts
and not strings.icontains(.display_text, 'voice call center')
Expand All @@ -187,7 +250,7 @@ source: |
any(body.links,
.href_url.path == "/ctt"
and regex.icontains(.display_text,
'(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'
'(v[nm]|voice|audi[o0]|call|missed|caii)(\s?|-)(mail|message|recording|call|caii)|transcription|open mp3|audi[o0] note|listen|playback|\(?(?:\*\*\*|[0-9]{3})?.(?:\*\*\*|[0-9]{3})[^a-z]{0,2}(?:\*{4}|\d+\*+)|play'
)
// negate FP terms in link display texts
and not strings.icontains(.display_text, 'voice call center')
Expand Down Expand Up @@ -354,10 +417,10 @@ source: |
)
// bounce-back negations
and not any(attachments,
any(file.parse_eml(.).attachments,
.content_type == "message/delivery-status"
)
)
any(file.parse_eml(.).attachments,
.content_type == "message/delivery-status"
)
)
// bounce-back negations
and not (
any(attachments,
Expand All @@ -384,6 +447,7 @@ source: |
and not profile.by_sender().any_false_positives
)
)

attack_types:
- "Credential Phishing"
tactics_and_techniques:
Expand Down
Loading