Skip to content
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
68 changes: 68 additions & 0 deletions detection-rules/link_pdf_suspicious_rfq.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: "Link: PDF with suspicious Request for Quote or Purchase (RFQ|RFP)"
description: "Detects messages with reply or forward subjects containing links that display as PDF files but redirect to free file hosting platforms or self-service creation domains, specifically targeting Request for Quotation (RFQ) or Request for Purchase (RFP) terminology."
type: "rule"
severity: "high"
source: |
type.inbound
and (subject.is_reply or subject.is_forward)
and length(body.previous_threads) <= 1
and length(body.links) > 0
// no PDF attachments
and length(filter(attachments, .file_type == "pdf")) == 0
// the display_text ends in .pdf and goes to a free file host
and any(body.current_thread.links,
strings.iends_with(.display_text, '.pdf')
and (
(
.href_url.domain.domain in $free_file_hosts
or .href_url.domain.root_domain in $free_file_hosts
or .href_url.domain.domain in $self_service_creation_platform_domains
or .href_url.domain.root_domain in $self_service_creation_platform_domains
or .href_url.domain.root_domain == "html.cafe"
)
// suspicious sender behaviour
or (
sender.email.email in map(recipients.to, .email.email)
or (
length(recipients.to) == 0
or (
all(recipients.to, .email.domain.valid == false)
and all(recipients.cc, .email.domain.valid == false)
)
)
)
)
// the display text references a Request for Quotation (RFQ) or Request for Purchase (RFP)
and (
regex.icontains(.display_text,
'(?:\bR\.?F\.?P\b|\bR\.?F\.?Q\b)|(?:Request.for.(?:Quot(e|ation)|Purchas(e|ing)))'
)
)
// negate links which make use of google icons inside of a bounding box
// filter down to the link with the same display text
and not any(filter(html.xpath(body.html,
'//a[img[@src] or .//img[@src]][.//div[contains(@style, "border:1px solid")] or ancestor::div[contains(@style, "border:1px solid")]]'
).nodes,
// the display text is the link we're inspecting
..display_text == .display_text
),
// inside this is a reference to the google icon
strings.icontains(.raw, 'gstatic.com/docs/doclist/images/')
)
)


attack_types:
- "BEC/Fraud"
- "Malware/Ransomware"
tactics_and_techniques:
- "Free file host"
- "Social engineering"
- "Evasion"
detection_methods:
- "Content analysis"
- "Header analysis"
- "HTML analysis"
- "Sender analysis"
- "URL analysis"
id: "9b0e6a27-5f3f-5e9f-ab63-e481e4bd30c1"