From bfa246053f8b05b310a456af10254739eef3bac4 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Tue, 25 Aug 2026 18:43:16 +0000 Subject: [PATCH] Add content from: CVE-2026-72898: Critical Metabase Unauthenticated SQL Inject... --- src/pentesting-web/sql-injection/README.md | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/pentesting-web/sql-injection/README.md b/src/pentesting-web/sql-injection/README.md index 40147817893..7fc779585ab 100644 --- a/src/pentesting-web/sql-injection/README.md +++ b/src/pentesting-web/sql-injection/README.md @@ -669,6 +669,32 @@ Payload (URL-encoded): `%27%20OR%20%271%27%3D%271` → decoded: `' OR '1'='1` JSON_VALUE(metadata, '$.department') = '' OR '1'='1' ``` +### Structured query-builder / raw-expression injection + +Parameterized values do not help when attacker input is interpreted as part of a **query-builder AST**. If an API field expected to be a scalar reaches the builder without strict type and shape validation, a JSON object or array can select a builder directive instead of becoming bound data. For example, HoneySQL's `:raw` expression renders its argument as literal SQL, while `:lift` is intended to keep a sequence or map as a parameter value.[[14]](#references)[[16]](#references) + +During testing, focus on the **data-to-query-syntax boundary**, not only quote characters. Replace scalar identifiers with objects/arrays, add undocumented keys, repeat the test across JSON and form encodings, and compare errors, timing, row counts, and generated-SQL traces. Classic string payloads may miss this class because the attacker injects a valid AST node rather than escaping from a quoted literal.[[14]](#references)[[16]](#references) + +CVE-2026-72898 is an example: affected Metabase password-reset handling accepted an unexpected structured `user-id` value that became a HoneySQL raw expression. The following is only the request shape—the exact SQL expression and generated query are adapter/version-specific:[[13]](#references)[[16]](#references) + +```http +POST /api/session/reset_password HTTP/1.1 +Host: metabase.example:3000 +Content-Type: application/json + +{ + "token": "", + "user-id": {"raw": ""}, + "password": "" +} +``` + +When the sink is the application's own database, prioritize authentication state such as user IDs, password hashes/reset tokens, role or superuser flags, sessions, and API keys. Turning database write capability into an application administrator session can then expose legitimate query/export features and stored connection secrets; access to connected data sources inherits the privileges of the application's configured service accounts.[[13]](#references)[[15]](#references)[[16]](#references) + +For Metabase incident triage, the vendor identifies `POST /api/session/reset_password` returning `400` followed shortly by `GET /api/user/current` returning `200` as a likely-compromise sequence. Correlate it with object-valued `user-id` bodies, unexplained administrator or `core_user.is_superuser` changes, new API keys, session activity, and subsequent queries against connected databases.[[15]](#references)[[16]](#references) + +Hardening must happen before query construction: reject unknown fields and non-primitive identifier values, rebuild permitted query nodes server-side from an allow-list, and never deserialize a request object directly into a builder DSL. Keep `:raw` expressions limited to static trusted application code; use bound values (or HoneySQL `:lift` when a map/sequence is genuinely database data) for attacker-influenced values.[[14]](#references)[[16]](#references) + ### ORDER BY / identifier-based SQLi (PDO limitation) Prepared statements **cannot bind identifiers** (column or table names). A common unsafe pattern is to take a user-controlled `sort` parameter and build `ORDER BY` using string concatenation, sometimes wrapping the input in backticks to “sanitize” it. This still enables SQLi because the identifier context is attacker-controlled.[[12]](#references) @@ -721,5 +747,9 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt - [10] [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/) - [11] [CVE-2026-22730: SQL Injection in Spring AI's MariaDB Vector Store](https://blog.securelayer7.net/cve-2026-22730-sql-injection-spring-ai-mariadb/) - [12] [HTB: Gavel](https://0xdf.gitlab.io/2026/03/14/htb-gavel.html) +- [13] [Metabase advisory GHSA-vwf4-m7j8-wcjf](https://github.com/metabase/metabase/security/advisories/GHSA-vwf4-m7j8-wcjf) +- [14] [HoneySQL special syntax: `raw` and `lift`](https://github.com/seancorfield/honeysql/blob/develop/doc/special-syntax.md) +- [15] [Metabase security update and attack pattern](https://www.metabase.com/blog/security-update) +- [16] [CVE-2026-72898: Critical Metabase Unauthenticated SQL Injection Vulnerability](https://offsec.com/blog/cve-2026-72898-2) {{#include ../../banners/hacktricks-training.md}}