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

Create link_sharepoint_attached_eml.yml #2177

Open
wants to merge 6 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
138 changes: 138 additions & 0 deletions detection-rules/link_sharepoint_attached_eml.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
name: "Link: SharePoint Nested Message Forgery"
description: "This detection rule identifies messages with an EML attachment containing SharePoint links, where the inner and outer messages share multiple matching characteristics, suggesting message content manipulation."
type: "rule"
severity: "medium"
source: |
type.inbound
and not any(body.links, .href_url.domain.root_domain == "sharepoint.com")
// ensure there is only a single .eml attachment
and length(filter(attachments,
(
.content_type == "message/rfc822"
or .file_extension == "eml"
)
)
) == 1
and any(
// filter to just eml attachments
filter(attachments,
(.content_type == "message/rfc822" or .file_extension == "eml")
),
// any body links go to sharepoint
any(file.parse_eml(.).body.links,
.href_url.domain.root_domain == "sharepoint.com"
and regex.icontains(.href_url.path, '/:[a-z]:/')
)
and 2 of (
// the recipients of the outer and inner messages are the same
// or there is no outer recipients
(
(
all(map(file.parse_eml(.).recipients.to, .email.email),
. in map(recipients.to, .email.email)
)
and all(map(file.parse_eml(.).recipients.bcc, .email.email),
. in map(recipients.bcc, .email.email)
)
and all(map(file.parse_eml(.).recipients.cc, .email.email),
. in map(recipients.cc, .email.email)
)
// make sure the are the same length
and sum([
length(recipients.to),
length(recipients.bcc),
length(recipients.cc)
]
) == sum([
length(file.parse_eml(.).recipients.to),
length(file.parse_eml(.).recipients.bcc),
length(file.parse_eml(.).recipients.cc)
]
)
)
or length(recipients.to) == 0
or all(recipients.to, .email.email == "")
),
// the sender of the outer and inner messages are the same
file.parse_eml(.).sender.email.email == sender.email.email,

// the subject of the outer and inner messages are the same
strings.icontains(subject.subject, file.parse_eml(.).subject.subject),

// the inner message has the recipient and sender as the same address
// without any other recipients and matches the outer message sender
(
sum([
length(filter(file.parse_eml(.).recipients.to,
.email.email != ""
)
),
length(filter(file.parse_eml(.).recipients.bcc,
.email.email != ""
)
),
length(filter(file.parse_eml(.).recipients.cc,
.email.email != ""
)
)
]
) == 1
and (
all(file.parse_eml(.).recipients.to,
.email.email == file.parse_eml(..).sender.email.email
)
)
and file.parse_eml(.).sender.email.email == sender.email.email
),

// the outer recipieint is the sender of the inner message
(
sum([
length(filter(file.parse_eml(.).recipients.to,
.email.email != ""
)
),
length(filter(file.parse_eml(.).recipients.bcc,
.email.email != ""
)
),
length(filter(file.parse_eml(.).recipients.cc,
.email.email != ""
)
)
]
) == 1
and all(recipients.to,
.email.email == file.parse_eml(..).sender.email.email
)
),

// the attached message contains a very low number of hops, as if it was never sent
(
length(file.parse_eml(.).headers.hops) <= 2
or file.parse_eml(.).headers.return_path.email is null
)
)
)

// exclude bounce backs & read receipts
and not strings.like(sender.email.local_part,
"*postmaster*",
"*mailer-daemon*",
"*administrator*"
)
and not regex.icontains(subject.subject, "^(undeliverable|read:)")
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, .))

attack_types:
- "Credential Phishing"
tactics_and_techniques:
- "Evasion"
- "Out of band pivot"
detection_methods:
- "File analysis"
- "URL analysis"
- "Header analysis"
id: "eab46d4b-39c9-568a-bb72-bf93f4cf997e"
Loading