Metabase Unauthenticated SQL Injection → Admin Takeover (GHSA-vwf4-m7j8-wcjf / CVE-2026-72898)
Executive Summary
Metabase, a widely deployed open-source business-intelligence and dashboarding tool, shipped a maximum-severity (CVSS 10.0) SQL injection flaw — tracked as GHSA-vwf4-m7j8-wcjf and, as confirmed directly from the GitHub advisory page on 2026-08-11, since assigned CVE-2026-72898 — in its unauthenticated POST /api/session/reset_password endpoint. The endpoint merges attacker-controlled JSON keys into an internal map without stripping an unexpected user-id field; when that field is supplied as a HoneySQL {:raw "..."} object it is compiled into literal, unparameterized SQL, giving a remote unauthenticated attacker blind SQL injection into the Metabase application database and, from there, the ability to mint a working administrator session. Every release from 1.58.0 through the 1.63.x branch is affected; fixed releases are 1.58.24, 1.59.21, 1.60.17, 1.61.11, 1.62.9 and 1.63.5.
The flaw was exploited in the wild before public disclosure: Metabase itself disclosed that its own Metabase Cloud environment was attacked, and self-hosted customers Framework (laptop manufacturer), Tally (form builder), n8n (workflow automation — 136 customer records, 5 with bcrypt-hashed passwords), and Kilo Code (Slack access tokens for a subset of users) have all independently confirmed breaches traced to this vulnerability. Metabase's own CEO published the operative detection signature: a POST /api/session/reset_password call returning HTTP 400 immediately followed by a GET /api/user/current call returning HTTP 200 from the same client. That pattern is the single highest-fidelity indicator of exploitation, but it lives entirely in Metabase's own application log, a reverse proxy, or a WAF — it is not something a CrowdStrike Falcon sensor can see, because Falcon has no visibility into in-process HTTP request/response handling inside the Metabase JVM.
This pack is built around what Falcon can see on and around the host running Metabase: anomalous child processes of the Metabase Java process, outbound network activity following compromise (including cloud instance-metadata theft, a realistic follow-on given Metabase's role holding connected-database credentials), dropped web shells or backdoor artifacts, unexpected listening ports, and persistence attempts. No attacker-attributed file hashes, C2 domains, or source IPs have been publicly disclosed for this campaign as of 2026-08-11, so every detection here is behavioral rather than atomic-indicator based.
Defender priority: patching is necessary but not sufficient. Because the flaw grants full application-admin access, treat every unpatched, internet-reachable Metabase instance as presumed-compromised until you have rotated every connected-database credential it held, purged core_session, and audited admin accounts and API keys — the exploitation window opened well before public disclosure.
Source Review & Web Hunter Notes
| Tier | Source | Key Finding | Carry Forward |
|---|---|---|---|
| 1 | The Hacker News (public disclosure article) | First aggregation of the flaw, CEO-published detection signature, named victims | Yes |
| 1 | GitHub Security Advisory GHSA-vwf4-m7j8-wcjf | Authoritative CVSS vector, exact affected/patched version ranges, CVE-2026-72898 assignment, vendor remediation checklist | Yes |
| 1 | Metabase official blog — Security Update | Vendor incident narrative, detection signature, post-patch remediation steps | Yes |
| 1 | n8n Blog — Metabase security incident update | Self-disclosed victim breach: 136 records, timeline, DPO notification | Yes |
| 1 | Kilo (Anaconda) Blog — Metabase incident | Self-disclosed victim breach: Slack access token exposure, remediation | Yes |
| 2 | Wiz Blog — technical root-cause analysis | HoneySQL :raw injection mechanics, Clojure merge root cause | Yes |
| 2 | Resecurity Blog — incident analysis | Corroborates root cause and detection signature; independent version-range confirmation | Partial |
| 2 | BleepingComputer — Framework/Tally coverage | Independent confirmation of Framework and Tally breaches, exploitation HTTP pattern | Yes |
Web Hunter notes: No source reviewed — including the two technical deep-dives (Wiz, Resecurity) — published attacker infrastructure (C2 IPs, domains, malware hashes). Both technical write-ups describe the injection mechanism in prose only; this pack does not reproduce working exploit payloads, consistent with defensive-content-only scope. One CVE identifier discrepancy was resolved during research: the task brief stated "no CVE assigned," which was accurate as of the original Hacker News publication, but the GitHub advisory now lists CVE-2026-72898 — independently confirmed by directly fetching the advisory page text rather than trusting a single summarization pass.
Prompt-injection check (per operating instructions): all eight fetched sources were reviewed for text addressed to an AI agent/assistant. None was found in any of the eight snapshots saved to the sources folder for this pack. Nothing from fetched content was treated as an instruction.
Hunt Brief & Attack Chain
Hypothesis set (ordered by fidelity):
- H1 (high): A compromised Metabase Java process spawns an unexpected shell/interpreter child process for post-exploitation recon or command execution.
- H2 (high): An attacker with admin-level Metabase access drops a web shell or backdoor script/binary on the host to maintain access beyond patching.
- H3 (medium): A compromised Metabase host process queries the cloud instance metadata service to escalate from stolen application-DB credentials to cloud IAM credentials.
- H4 (medium): A compromised Metabase host opens an unexpected listening port for a backdoor/reverse-shell channel.
- H5 (medium): A compromised Metabase host makes outbound connections to non-standard external destinations consistent with data staging or exfiltration of connected-database contents.
- H6 (low-medium): An attacker establishes scheduled-task/cron persistence on the Metabase host.
- H7 (medium): Post-compromise reconnaissance for stored database credentials or cloud credential files/environment variables on the Metabase host.
| Step | Attacker Action | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 | Unauthenticated POST to /api/session/reset_password with a crafted user-id HoneySQL raw-SQL payload | Metabase app log / reverse proxy / WAF only — not visible to Falcon | App-layer log hunt (Section 7) |
| 2 | Blind SQLi confirms/derives admin credentials or a session token, then GET /api/user/current confirms a live admin session | Metabase app log / reverse proxy / WAF only — not visible to Falcon | App-layer log hunt (Section 7) — the CEO-published 400→200 signature |
| 3 | Attacker uses admin access to view/export connected-database credentials, create API keys, or modify settings | Metabase audit log / activity history | Native audit-log hunt (Section 7) |
| 4 | Attacker pivots from stolen DB credentials or the host itself toward host-level access (recon, backdoor, persistence) | ProcessRollup2, NetworkConnectIP4, NetworkListenIP4, PeFileWritten/ELFFileWritten, ScheduledTaskRegistered/CreateService | Falcon-visible — Q1–Q7 (Section 8) |
| 5 | Data staged and exfiltrated from connected data warehouses via Metabase's own query/export functionality | Metabase query history / connected-DB audit logs; host-level outbound connections (Q2) | Native audit-log hunt + Q2 as a pivot |
Consolidated IOC Table
No attacker-attributed file hashes, C2 domains, or source IP addresses have been publicly disclosed for this campaign as of 2026-08-11. This threat is behavioral-only at the atomic-indicator level; the table below lists version fingerprints and the app-layer detection pattern rather than classic IOCs.
| Type | Value | Confidence | Action | Context | Expiry |
|---|---|---|---|---|---|
| Vulnerable version range | 1.58.0–1.58.23, 1.59.0–1.59.20, 1.60.0–1.60.16, 1.61.0–1.61.10, 1.62.0–1.62.8, 1.63.0–1.63.3 | high | hunt | Confirm via GET /api/session/properties on the target instance | 2027-02-11 |
| Patched version range | 1.58.24, 1.59.21, 1.60.17, 1.61.11, 1.62.9, 1.63.5 | high | enrich | Target state for patch verification | 2027-02-11 |
| Vulnerable endpoint | POST /api/session/reset_password | high | detect | Root of the injection; also the temporary WAF-block workaround | 2027-02-11 |
| App-layer exploitation pattern | POST /api/session/reset_password → HTTP 400, then GET /api/user/current → HTTP 200, same client, short window | high | detect | Vendor-published (Metabase CEO); hunt in app/WAF/proxy logs, not Falcon | 2027-02-11 |
| Identifier | GHSA-vwf4-m7j8-wcjf / CVE-2026-72898 | high | enrich | Advisory and CVE identifiers for tracking/patch management | 2027-02-11 |
Affected Surface & Telemetry Matrix
| Surface | Required Telemetry | Priority | Gap Risk |
|---|---|---|---|
| Metabase application (HTTP API layer) | App request/response log, reverse-proxy/WAF log | Critical — this is where exploitation happens | High — Falcon has no visibility here; must be hunted natively (Section 7) |
| Host running Metabase (Linux VM/container most common; Windows possible) | ProcessRollup2/SyntheticProcessRollup2, PeFileWritten/NewExecutableWritten/ELFFileWritten, NetworkConnectIP4, NetworkListenIP4, ScheduledTaskRegistered/CreateService | High — primary Falcon coverage area | Low if the Falcon sensor is deployed on the host; check container-runtime sensor coverage for containerized deployments |
| Cloud IAM / instance metadata (AWS/GCP/Azure) | Host-level NetworkConnectIP4 to the 169.254.169.254 metadata endpoint; cloud provider IAM/CloudTrail-equivalent logs | High — realistic escalation path from stolen app-DB creds | Medium — Falcon sees the network call but not the resulting cloud-side credential use; pair with cloud audit logs |
| Connected data warehouses/databases | Database audit/query logs for the Metabase service account | High — this is what an admin-level attacker actually wants | High — entirely outside Falcon; must be hunted in the DB's own logging |
Metabase application database (core_session, admin accounts, API keys) | Metabase audit log / activity history | Critical for scoping post-compromise admin activity | High — outside Falcon; native hunt only |
ATT&CK Mapping
| Tactic | Technique | Name | Observed/Expected Behavior |
|---|---|---|---|
| Initial Access | T1190 | Exploit Public-Facing Application | Unauthenticated SQL injection via POST /api/session/reset_password |
| Privilege Escalation | T1078 | Valid Accounts | SQLi used to mint/derive a working administrator session |
| Credential Access | T1552.001 | Unsecured Credentials: Credentials In Files | Post-compromise search for stored DB/cloud credentials and environment variables on the Metabase host |
| Credential Access | T1552.005 | Unsecured Credentials: Cloud Instance Metadata API | Host process querying 169.254.169.254 to escalate to cloud IAM credentials |
| Persistence | T1505.003 | Server Software Component: Web Shell | Backdoor script/binary dropped by the Metabase process |
| Persistence | T1053 | Scheduled Task/Job | Scheduled task or cron entry added on the compromised host |
| Command and Control | T1071 | Application Layer Protocol | Outbound connections from the Metabase host to attacker infrastructure |
| Command and Control | T1572 | Protocol Tunneling | Unexpected listening port opened for a reverse/bind channel |
| Exfiltration | T1567 | Exfiltration Over Web Service | Connected-database data exported via Metabase's own query/export features |
| Impact | T1565 | Data Manipulation (n/a to this pack) | Not observed in any reviewed source; listed for completeness of the admin-takeover blast radius |
Native Audit-Log Hunts (Non-CQL)
This is the single most important section of the pack. The vendor-published detection signature is an HTTP request/response pattern that CrowdStrike Falcon cannot see — it must be hunted in Metabase's own application log, a reverse proxy, a load balancer, or a WAF.
1. Primary exploitation signature (Metabase app log / reverse proxy / WAF / load-balancer access log)
Hunt for: POST /api/session/reset_password returning HTTP 400, followed within a short window by GET /api/user/current returning HTTP 200, from the same client IP or the same short-lived session. This is the pattern Metabase's own CEO called out as the operative compromise indicator. If request logging is not currently enabled on your Metabase deployment, enable it and forward it to your SIEM before doing anything else — without it, this entire attack class is invisible.
2. Metabase application audit log ("Admin > Audit log" / activity history)
Review for: new API key creation, new admin accounts, permission-group changes, and connected-database configuration edits in the days surrounding your earliest possible exposure date (treat the earliest of your patch date or 2026-08-01 as the start of the review window, since exploitation predates public disclosure).
3. core_session table review (Metabase application database)
Before purging core_session per the vendor remediation steps, export it for forensic review: look for session records with anomalous creation timestamps, unfamiliar source IPs, or sessions tied to admin accounts that were not actively used by legitimate staff.
4. Connected data-warehouse / database query logs
Review query logs for the Metabase service account for unusual export-style queries (large row counts, SELECT * against sensitive tables, queries outside normal business hours) in the exposure window.
5. Linux cron / systemd-timer persistence (Falcon coverage gap — supplement here)
Falcon's LogScale event model has no dedicated cron-file-write event (see Q6 and the Coverage Map for the equivalent host-based hunt and its limits). Supplement with a native auditd watch rule on /etc/cron.d/, /etc/cron.daily/, /var/spool/cron/, and /etc/systemd/system/*.timer, or a periodic file-integrity check against those paths.
CrowdStrike LogScale CQL Hunt Queries
All seven queries below hunt host and network telemetry around the Metabase server, not the SQL injection itself. Scope every query to your Metabase host group (by aid/ComputerName or a Falcon host group) before running — several are written broadly for portability and will be noisy run fleet-wide.
Looks for: a shell, scripting interpreter, or common recon/transfer tool spawned as a direct child of the Metabase JVM — the highest-fidelity Falcon-visible signal that a Metabase instance has been used for command execution post-compromise. FP: some deployments run health-check wrappers, backup agents, or configuration-management tools that legitimately spawn a shell alongside a co-located java process; scope to your actual Metabase host group.
// HUNT: Unexpected child process of the Metabase Java process // MITRE: T1190, T1059 // CONF: high // FP: medium // COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 on the Metabase host(s) // FALSE POSITIVES: health-check wrapper scripts, backup jobs, or config-management agents co-located on the same host // TUNING: exclude known deployment/orchestration parent-child chains for your Metabase image (e.g. container entrypoint scripts) after a benign baseline period; scope to your Metabase host group with aid/ComputerName before promoting to IOA // LOOKBACK: 7d (set via console time picker) #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^java(\.exe)?$/i | FileName=/^(sh|bash|dash|zsh|cmd|powershell|pwsh|python[0-9.]*|perl|curl|wget|nc|ncat|socat)(\.exe)?$/i | table([aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, timestamp])
Looks for: outbound connections from the Metabase java process to any destination outside common internal/private ranges — a broad net for data staging/exfil or C2 following compromise. FP: Metabase legitimately connects outward to every connected data warehouse, SMTP relays, Slack/webhook integrations, and its own license/update checks, so this is high-noise on its own.
// HUNT: Metabase host outbound connection to a non-internal destination // MITRE: T1041, T1071 // CONF: medium // FP: high // COST: medium // REQUIRES: NetworkConnectIP4 on the Metabase host(s) // FALSE POSITIVES: connections to legitimate connected data warehouses, SMTP relays, Slack/webhook integrations, and Metabase's own update/license checks // TUNING: build an allowlist of expected outbound destinations (connected DB hosts, SMTP relay, integration endpoints) with in()/cidr() exclusions before alerting on this; best used as a pivot after Q1 or Q4 fires, not run standalone // LOOKBACK: 7d (set via console time picker) #event_simpleName=/NetworkConnectIP4/ | ContextBaseFileName=/^java(\.exe)?$/i | !cidr(RemoteAddressIP4, subnet=["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16","127.0.0.0/8","169.254.0.0/16","100.64.0.0/10"]) | table([aid, ComputerName, ContextBaseFileName, RemoteAddressIP4, RemotePort, LocalPort, timestamp])
Looks for: the Metabase java process reaching the cloud instance metadata endpoint (169.254.169.254) — a realistic escalation path from stolen application-DB credentials to the underlying cloud IAM role/service account. FP: some JDBC drivers (e.g. IAM-authenticated RDS/Cloud SQL connectors) legitimately call IMDS to resolve credentials, so a driver baseline is required before promoting to IOA.
// HUNT: Metabase process calling the cloud instance metadata service // MITRE: T1552.005 // CONF: medium // FP: medium // COST: low // REQUIRES: NetworkConnectIP4 on the Metabase host(s), cloud-hosted deployment // FALSE POSITIVES: JDBC drivers or SDKs that legitimately resolve cloud-IAM database credentials via IMDS (e.g. IAM-authenticated RDS/Cloud SQL connectors) // TUNING: if a specific connected-database driver legitimately calls IMDS, baseline and exclude that driver's known process/command-line signature rather than excluding the whole host // LOOKBACK: 7d (set via console time picker) #event_simpleName=/NetworkConnectIP4/ | ContextBaseFileName=/^java(\.exe)?$/i | RemoteAddressIP4="169.254.169.254" | table([aid, ComputerName, ContextBaseFileName, RemoteAddressIP4, RemotePort, timestamp])
Looks for: a new PE, Linux ELF binary, or executable script written to disk by the Metabase java process — consistent with a dropped web shell or backdoor used to persist beyond patching. FP: low; the JVM occasionally writes temp files or downloads plugin driver JARs during normal driver installation, which is why the write event type list below intentionally does not include archive/document writes.
// HUNT: New executable/script written by the Metabase process // MITRE: T1505.003, T1105 // CONF: high // FP: low // COST: low // REQUIRES: PeFileWritten, NewExecutableWritten, ELFFileWritten on the Metabase host(s) // FALSE POSITIVES: legitimate JDBC/plugin driver JARs downloaded during normal Metabase driver installation #event_simpleName=/PeFileWritten|NewExecutableWritten|ELFFileWritten/ | ContextBaseFileName=/^java(\.exe)?$/i | table([aid, ComputerName, ContextBaseFileName, TargetFileName, SHA256HashData, timestamp])
Looks for: the Metabase java process opening a listening port outside the expected Metabase/reverse-proxy set — a possible bind-shell or backdoor listener. FP: JVM debug (5005) or JMX/management ports intentionally opened by ops tooling will trip this if not excluded.
// HUNT: Unexpected listening port on the Metabase host // MITRE: T1071, T1572 // CONF: medium // FP: medium // COST: low // REQUIRES: NetworkListenIP4 on the Metabase host(s) // FALSE POSITIVES: JVM remote-debug (5005) or JMX/management ports intentionally opened by operations tooling // TUNING: add your environment's actual Metabase listen port (default 3000, or 80/443/8080 if reverse-proxy fronted) plus any intentionally-open JVM debug/JMX ports to the exclusion list before promoting to IOA // LOOKBACK: 7d (set via console time picker) #event_simpleName=/NetworkListenIP4/ | ContextBaseFileName=/^java(\.exe)?$/i | !in(LocalPort, values=["3000","8080","443","80"]) | table([aid, ComputerName, ContextBaseFileName, LocalPort, LocalAddressIP4, timestamp])
Looks for: a new scheduled task or service registered on the specific host(s) running Metabase, following the vendor's own remediation reminder to audit for persistence after this class of admin takeover. FP: routine patch/maintenance scheduled tasks and container-orchestrator health-check tasks will appear here. Coverage note: this covers Windows-hosted Metabase well; Falcon's LogScale event model has no dedicated cron-file-write event, so Linux cron/systemd-timer persistence is a gap — see the native auditd hunt in Section 7.
// HUNT: Scheduled task / service persistence on the Metabase host // MITRE: T1053 // CONF: low // FP: medium // COST: low // REQUIRES: ScheduledTaskRegistered, CreateService; host-scoped by ComputerName // FALSE POSITIVES: routine patch/maintenance scheduled tasks, container-orchestrator health-check tasks // TUNING: replace REPLACE_WITH_METABASE_HOSTNAME with your actual Metabase server hostname(s); this query has no Linux-cron equivalent in the Falcon event model -- pair it with the auditd hunt in Section 7 for full coverage // LOOKBACK: 14d (set via console time picker) #event_simpleName=/ScheduledTaskRegistered|CreateService/ | in(ComputerName, values=["REPLACE_WITH_METABASE_HOSTNAME"]) | table([aid, ComputerName, UserName, CommandLine, timestamp])
Looks for: shell commands spawned from the Metabase process tree that reference credential material, environment dumps, or the Metabase application's own session/config store — consistent with an attacker harvesting connected-database credentials after admin takeover. FP: legitimate ops/debugging sessions on the same host will trigger some of these terms.
// HUNT: Credential/environment recon spawned from the Metabase process // MITRE: T1552.001, T1518 // CONF: medium // FP: medium // COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 on the Metabase host(s) // FALSE POSITIVES: legitimate ops/debugging sessions on the same host reviewing environment or credential configuration // TUNING: exclude known admin/SRE tooling that legitimately reads environment variables on this host (e.g. a config-management agent's command-line signature) // LOOKBACK: 7d (set via console time picker) #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ParentBaseFileName=/^(sh|bash|dash|zsh|java)(\.exe)?$/i | CommandLine=/(credentials|printenv|environ|GOOGLE_APPLICATION_CREDENTIALS|core_session|metabase\.db)/i | table([aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, timestamp])
CrowdStrike Custom IOA Recommendations
Three queries are strong Custom IOA candidates once tuned against your own Metabase host baseline. The remaining four should stay Investigate-only given their FP profile.
| Query | IOA Name | Pattern | Exclusions Needed | Deployment Path |
|---|---|---|---|---|
| Q1 | Metabase Process — Unexpected Shell Child | Shell/interpreter/transfer-tool spawned as a direct child of the Metabase JVM | Deployment/orchestration parent-child chains for your specific Metabase image | Falcon console → Custom IOA rule groups, scoped to a "Metabase Servers" host group |
| Q3 | Metabase Process — IMDS Access | Metabase JVM connecting to 169.254.169.254 | Any driver/SDK on the host with a legitimate, baselined need to call IMDS | Same host group; low volume, safe to run near-real-time |
| Q4 | Metabase Process — New Executable/Script Write | PE/ELF/script write events with the Metabase JVM as the writing process | None expected once your plugin/driver install baseline is captured | Same host group; highest-confidence IOA in the pack |
Q2, Q5, Q6, and Q7 remain Investigate-only: Q2 and Q5 have high/medium FP that needs an environment-specific allowlist before alerting, and Q6/Q7 are best run as periodic hunts rather than always-on IOAs.
Machine-Readable IOC Appendix
No attacker-attributed atomic indicators (hashes, C2 domains, source IPs) have been published for this campaign as of 2026-08-11. The CSV block below ships only placeholder rows for your own investigation findings; nothing in it is a real indicator. This pack's actual detection value is the behavioral signatures in the second block.
# No attacker-attributed file hashes, C2 domains, or IPs have been publicly # disclosed for GHSA-vwf4-m7j8-wcjf / CVE-2026-72898 as of 2026-08-11. # The rows below are placeholders for YOUR OWN incident-response findings -- # populate them from your Falcon/WAF/Metabase log investigation, do not # invent values. type,value,action,severity,expiration,description,tags sha256,REPLACE_WITH_SHA256,prevent,critical,2027-02-11,Metabase host post-exploitation artifact (webshell/backdoor),campaign:Metabase-GHSA-vwf4 domain,REPLACE_WITH_C2_DOMAIN,detect,high,2026-11-11,Suspected exfil/C2 destination observed from a compromised Metabase host,campaign:Metabase-GHSA-vwf4 ipv4,REPLACE_WITH_ATTACKER_IP,detect,high,2026-11-11,Suspected attacker source IP identified in Metabase app/WAF logs,campaign:Metabase-GHSA-vwf4
# PRIMARY exploitation signature -- Metabase app log / WAF / reverse-proxy
# access log ONLY. This is NOT visible in Falcon EDR telemetry.
POST /api/session/reset_password -> HTTP 400
immediately followed by (same client, short window)
GET /api/user/current -> HTTP 200
# Vulnerable version fingerprint -- query GET /api/session/properties
Vulnerable: 1.58.0-1.58.23, 1.59.0-1.59.20, 1.60.0-1.60.16,
1.61.0-1.61.10, 1.62.0-1.62.8, 1.63.0-1.63.3
Patched: 1.58.24, 1.59.21, 1.60.17, 1.61.11, 1.62.9, 1.63.5
# Falcon-visible host-layer behaviors (see Q1-Q7 in Section 8)
- Shell/interpreter spawned as a direct child of the Metabase JVM
- Metabase JVM process reaching 169.254.169.254 (cloud instance metadata)
- New PE/ELF/script write events attributed to the Metabase JVM
- Unexpected listening port opened by the Metabase JVM
- New scheduled task/service on the Metabase host
GHSA: GHSA-vwf4-m7j8-wcjf
CVE: CVE-2026-72898
CVSS: 10.0 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
Vulnerable ep: POST /api/session/reset_password
Root cause: unvalidated "user-id" JSON key reaches HoneySQL as a
{:raw ...} raw-SQL directive, bypassing parameter binding
Vendor advisory: github.com/metabase/metabase/security/advisories/GHSA-vwf4-m7j8-wcjf
Vendor blog: metabase.com/blog/security-update
[ ] Confirm current version via GET /api/session/properties
[ ] Upgrade to the fixed release for your branch
(1.58.24 / 1.59.21 / 1.60.17 / 1.61.11 / 1.62.9 / 1.63.5)
[ ] Block POST /api/session/reset_password at the proxy/WAF until patched
[ ] Delete all rows in the core_session application-database table
[ ] Review and revoke unrecognized Metabase API keys
[ ] Audit administrator accounts for unauthorized creation/changes
[ ] Rotate every credential Metabase held for connected databases
[ ] Review connected data-warehouse access/query logs for the exposure window
[ ] Review Metabase activity history / audit log for anomalies
[ ] Run Q1, Q3, Q4 (Section 8) against the Metabase host for host-level compromise indicators
Detection Validation Gates
| Gate | Status | Notes |
|---|---|---|
| Telemetry ready | Verify | Confirm ProcessRollup2/SyntheticProcessRollup2, NetworkConnectIP4, NetworkListenIP4, and file-write events are actively collected from every host running Metabase, including container-runtime sensor coverage if Metabase runs in Docker/Kubernetes |
| Benign baseline | Required before promotion | Run Q1, Q2, and Q5 in Investigate mode for 7–14 days to capture your environment's legitimate child-process, egress, and listening-port behavior before promoting any of them to an IOA |
| Positive test | Recommended | In a lab Metabase instance, validate Q4 fires by writing a benign test file from a child process of a mock java process; validate Q1 fires on a deliberately spawned benign shell child |
| Promotion | Q1 / Q3 / Q4 ready | Q1, Q3, and Q4 are promotable to Custom IOA once host-specific exclusions are tuned (Section 9); Q2, Q5, Q6, Q7 remain hunt-only pending baseline/coverage work |
Hardening — Tiered
1. Patch to the fixed release for your branch (1.58.24 / 1.59.21 / 1.60.17 / 1.61.11 / 1.62.9 / 1.63.5). MITRE M1051 (Update Software). Verify via GET /api/session/properties returning a patched version string.
2. Block POST /api/session/reset_password at the reverse proxy/WAF until patched, per vendor guidance. MITRE M1037 (Filter Network Traffic). ⚠ best-practice, no formal CIS benchmark entry — this is a vendor-recommended emergency control, not a benchmark item. Verify by confirming the endpoint returns 403/404 from outside the proxy.
3. Rotate every connected-database credential Metabase held, revoke/regenerate all API keys, and purge core_session to invalidate any attacker-held session. Vendor guidance (Metabase Security Update advisory). Verify via a diff of active API keys and admin accounts against your last known-good baseline.
1. Remove direct internet exposure of the Metabase admin/API surface: front it with SSO, a VPN, or an IP allowlist at the reverse proxy. MITRE M1030 (Network Segmentation); align with your reverse proxy's own CIS benchmark (e.g. CIS Nginx or Apache HTTP Server Benchmark) for the proxy configuration itself. Verify via an external port scan confirming the API is unreachable without the proxy/VPN path.
2. Enforce IMDSv2 with a hop limit of 1 on the cloud instance(s) hosting Metabase, and restrict the instance's IAM role/service account to least privilege. MITRE M1042 (Disable or Remove Feature or Program); CIS AWS Foundations Benchmark (IMDSv2 control) or the equivalent CIS Azure/GCP Foundations control. Verify via your cloud CLI's instance-metadata-options query.
3. If containerized, apply the CIS Docker Benchmark baseline: run as a non-root UID, read-only root filesystem, drop unnecessary Linux capabilities, restrict egress via a network policy. MITRE M1038 (Execution Prevention) / M1030 (Network Segmentation); CIS Docker Benchmark sections 4 and 5. Verify via docker inspect or kubectl get pod -o yaml capability/user checks.
1. Move connected-database credentials to short-lived, dynamically issued secrets via a secrets manager (Vault, AWS Secrets Manager, GCP Secret Manager) instead of static stored credentials in Metabase. MITRE M1027 (Password Policies) applied architecturally. ⚠ best-practice, no single formal benchmark covers this architecture. Verify via absence of long-lived static secrets in the Metabase application database.
2. Build a durable app-layer detection pipeline: ship Metabase/WAF/proxy access logs to your SIEM so the reset_password(400)→user/current(200) signature and future app-layer exploitation attempts are hunted continuously. This directly closes the Falcon telemetry gap documented throughout this pack. Verify via a synthetic test alert firing on a benign simulated 400/200 sequence in a lab instance.
Deployable Playbooks
Playbook A — Emergency WAF/reverse-proxy block (nginx example)
location = /api/session/reset_password {
deny all;
return 403;
}
Prerequisites: a reverse proxy (nginx or equivalent) sits in front of Metabase; ability to reload its configuration.
Reboot required: no — nginx -s reload applies it live.
Rollback: remove the location block and reload; only do this after confirming the instance is patched to a fixed version.
Playbook B — Enforce IMDSv2 (AWS CLI example)
aws ec2 modify-instance-metadata-options \ --instance-id REPLACE_WITH_INSTANCE_ID \ --http-tokens required \ --http-put-response-hop-limit 1 \ --http-endpoint enabled
Prerequisites: AWS CLI configured with ec2:ModifyInstanceMetadataOptions permission; confirm no application code on the instance still calls IMDSv1 without a session token.
Reboot required: no.
Rollback: aws ec2 modify-instance-metadata-options --instance-id REPLACE_WITH_INSTANCE_ID --http-tokens optional restores IMDSv1 compatibility if a legacy integration breaks.
Playbook C — Session purge (Metabase application database)
-- Run against the Metabase APPLICATION database only -- (never a connected data-source database). DELETE FROM core_session;
Prerequisites: direct admin access to the Metabase application database; export the table for forensic review first (Section 7); put Metabase into maintenance mode to avoid races during the delete.
Reboot required: restart the Metabase application process afterward to clear in-memory session caches.
Rollback: none required — this only invalidates existing sessions; legitimate users simply re-authenticate.
Playbook D — Container hardening (docker-compose example)
# docker-compose.yml
services:
metabase:
image: metabase/metabase:REPLACE_WITH_PATCHED_TAG
read_only: true
user: "2000:2000"
cap_drop: ["ALL"]
tmpfs: ["/tmp"]
Prerequisites: confirm the patched Metabase image tolerates a read-only root filesystem (mount a writable tmpfs for its plugins/temp directories); test in staging before production.
Reboot required: container recreate (docker compose up -d).
Rollback: revert to the previous compose file (remove the read_only/user/cap_drop lines) and recreate the container.
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| 1 · Isolate | Restrict network access to the Metabase host/API to trusted sources only, or take it offline; block /api/session/reset_password at the proxy immediately (Playbook A) | IR lead / Network team | Firewall/WAF change log with timestamp of isolation |
| 2 · Eradicate | Patch to the fixed version; purge core_session (Playbook C); revoke/regenerate all API keys; audit and remove unauthorized admin accounts; run Q1/Q3/Q4 against the host and remove any dropped artifacts found | App/Platform team + IR | Patch version confirmation, admin-account diff, Falcon detection review |
| 3 · Recover | Rotate every connected-database credential Metabase held; restore Metabase from a known-clean image/backup if host integrity is in doubt; re-enable access only behind the hardened proxy/VPN | DBA + Platform team | Credential-rotation log, clean image tag/hash |
| 4 · Post-Incident | Review connected data-warehouse query/export logs for the compromise window; determine customer PII exposure scope and trigger breach-notification process if applicable; convert the reset_password/user-current signature into a permanent SIEM/WAF rule | IR + Legal/Privacy + SOC | Data-warehouse audit report, notification records, new detection rule ID |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1190 (the SQLi itself) | reset_password 400 → user/current 200 | None — Falcon has no HTTP request/response visibility into the Metabase JVM | N/A | GAP — hunt in app/WAF/proxy logs (Section 7), not Falcon |
| T1078 / post-exploitation execution | Unexpected child process of the Metabase JVM | Q1 | Candidate | Good |
| T1552.005 cloud credential theft | Metabase JVM calling 169.254.169.254 | Q3 | Candidate | Good |
| T1505.003 web shell / backdoor | New executable/script written by the JVM | Q4 | Candidate | Good |
| T1041/T1071 exfil / C2 | Outbound connection to non-internal destination | Q2 | Investigate-only | Partial — high FP, needs environment allowlist |
| T1572 tunneling / backdoor listener | Unexpected listening port | Q5 | Investigate-only | Partial |
| T1053 scheduled task/cron persistence | New scheduled task/service; Linux cron unmapped | Q6 | Investigate-only | Partial — Windows covered, Linux cron is a Falcon event-model gap (see Section 7 auditd hunt) |
| T1552.001 credential/env recon | Env/credential-referencing commands from the JVM's process tree | Q7 | Investigate-only | Partial |
| T1567 exfil via connected data warehouse | Anomalous export-style queries under the Metabase service account | None — lives in the data warehouse's own audit log | N/A | GAP — hunt natively in the connected database's audit/query log |
Validation gate status (full detail in Section 11): telemetry readiness must be confirmed per host, Q1/Q2/Q5 require a benign baseline before promotion, and Q1/Q3/Q4 are the only queries currently recommended for Custom IOA promotion.
Hunt Summary Ticket
TITLE: Metabase Unauthenticated SQLi -> Admin Takeover (GHSA-vwf4-m7j8-wcjf / CVE-2026-72898)
SEVERITY: Critical (CVSS 10.0) -- confirmed exploited in the wild, multiple victim breaches disclosed
SCOPE: Any self-hosted Metabase instance on 1.58.0 through the 1.63.x branch reachable by
an untrusted network path to /api/session/reset_password
HYPOTHESIS: An unauthenticated attacker used the reset_password SQLi to obtain admin access,
then pivoted from stolen connected-database credentials and/or host access toward
recon, persistence, or exfiltration on/around the Metabase host.
QUERIES: Q1 unexpected shell child of Metabase JVM | Q2 outbound to non-internal destination
| Q3 IMDS access from Metabase JVM | Q4 new exe/script written by Metabase JVM
| Q5 unexpected listening port | Q6 scheduled task/service on host
| Q7 credential/env recon from process tree
DO FIRST: 1) Confirm version via GET /api/session/properties 2) Patch to the fixed release
3) Block reset_password at the proxy/WAF if not yet patched 4) Purge core_session
and rotate every connected-database credential
FINDINGS: [populate during investigation]
GAPS: The primary exploitation signature (reset_password 400 -> user/current 200) is not
visible to Falcon and must be hunted in Metabase/WAF/proxy logs. Linux cron
persistence has no dedicated Falcon event -- supplement with auditd. No
attacker-attributed atomic IOCs (hashes/domains/IPs) are publicly available as of
2026-08-11.
ACTIONS: Patch -> rotate credentials -> purge sessions -> run Q1/Q3/Q4 against the host ->
review connected data-warehouse logs -> assess PII exposure / notification duty
OWNER: [assign IR lead]
VERSION: v0.1 -- 2026-08-11
Changelog
References
| Tier | Source | Used For | Access Date |
|---|---|---|---|
| 1 | The Hacker News — Metabase Zero-Day Exploited in Wild | Primary disclosure, CEO-published detection signature, named victims | 2026-08-11 |
| 1 | GitHub Security Advisory GHSA-vwf4-m7j8-wcjf | CVSS vector, version ranges, CVE-2026-72898, vendor remediation checklist | 2026-08-11 |
| 1 | Metabase — Security Update | Vendor incident narrative and remediation steps | 2026-08-11 |
| 1 | n8n Blog — Metabase security incident update | Self-disclosed victim breach detail (136 records) | 2026-08-11 |
| 1 | Kilo (Anaconda) Blog — Metabase incident | Self-disclosed victim breach detail (Slack token exposure) | 2026-08-11 |
| 2 | Wiz Blog — Inside the Metabase SQLi | Technical root-cause analysis (HoneySQL/Clojure merge) | 2026-08-11 |
| 2 | Resecurity — Metabase Zero-Day analysis | Corroborating technical analysis | 2026-08-11 |
| 2 | BleepingComputer — Framework, Tally disclose Metabase attacks | Independent confirmation of Framework/Tally breaches | 2026-08-11 |
Verbatim extracted-text snapshots of all eight sources are saved alongside this pack in Metabase-GHSA-vwf4-SQLi-Hunt-sources/ for provenance verification.