Detection rules › Sublime MQL
Brand impersonation: Punchbowl
Detects messages impersonating Punchbowl invitations not originating from legitimate Punchbowl domain.
Threat classification
Sublime's own taxonomy (not MITRE ATT&CK).
| Category | Values |
|---|---|
| Attack types | Credential Phishing |
| Tactics and techniques | Impersonation: Brand, Social engineering |
Event coverage
| Message attribute |
|---|
| body |
| body.current_thread |
| body.html |
| sender.email |
| type |
Rule body MQL
type.inbound
// Looking for Punchbowl phrasing in all body threads
and (
strings.icontains(body.current_thread.text, "punchbowl")
// Look for alt text in HTML for standardized Punchbowl formatting if string is not avail.
or strings.icontains(body.html.raw, 'alt="Punchbowl"')
// image sourced from punchbowl
or any(html.xpath(body.html, '//img/@src').nodes,
strings.parse_url(.raw).domain.domain == "static.punchbowl.com"
and strings.icontains(strings.parse_url(.raw).path, '/invitation')
)
)
// Phrasing is typically "You're invited"
and (
strings.icontains(body.current_thread.text, "you're invited")
or any([
html.xpath(body.html,
'//a//img[contains(@src, "btn_open_invitation")]'
).nodes,
html.xpath(body.html,
'//a//img[contains(@src, "btn_open_save_the_date")]'
).nodes,
],
any(.,
regex.icontains(.inner_text,
'(?:open|save).{0,10}(?:invitation|the date)'
)
)
)
)
// Legitimate sender will be from punchbowl, negating known non-associated domains.
and not sender.email.domain.root_domain in ("punchbowl.com", "punchbowl.news")
// Capping length to limit FP's
and length(body.current_thread.text) < 1500
Detection logic
Scope: inbound message.
Detects messages impersonating Punchbowl invitations not originating from legitimate Punchbowl domain.
- inbound message
any of:
- body.current_thread.text contains 'punchbowl'
- body.html.raw contains 'alt="Punchbowl"'
any of
html.xpath(body.html, '//img/@src').nodeswhere all hold:- strings.parse_url(.raw).domain.domain is 'static.punchbowl.com'
- strings.parse_url(.raw).path contains '/invitation'
any of:
- body.current_thread.text contains "you're invited"
any of
[html.xpath(body.html, '//a//img[contains(@src, "btn_open_invitation")]').nodes, html.xpath(body.html, '//a//img[contains(@src, "btn_open_save_the_date")]').nodes]where:any of
.where:- .inner_text matches '(?:open|save).{0,10}(?:invitation|the date)'
not:
- sender.email.domain.root_domain in ('punchbowl.com', 'punchbowl.news')
- length(body.current_thread.text) < 1500
Inspects: body.current_thread.text, body.html, body.html.raw, sender.email.domain.root_domain, type.inbound. Sensors: html.xpath, regex.icontains, strings.icontains, strings.parse_url.
Indicators matched (7)
| Field | Match | Value |
|---|---|---|
strings.icontains | substring | punchbowl |
strings.icontains | substring | alt="Punchbowl" |
strings.icontains | substring | /invitation |
strings.icontains | substring | you're invited |
regex.icontains | regex | (?:open|save).{0,10}(?:invitation|the date) |
sender.email.domain.root_domain | member | punchbowl.com |
sender.email.domain.root_domain | member | punchbowl.news |