Metabase Cloud: H2 INIT sanitizer bypass gives RCE and cross-tenant secret exposure via EKS node credentials
Researchers at Hacktron disclosed a chain in Metabase Cloud that began with a bypass of the sanitization Metabase applies to H2 connection strings and ended in exposure of secrets belonging to other tenants. Metabase strips or rejects INIT= in the H2 URL, but the INIT value could be supplied in a separate details field that was never sanitized. This yielded remote code execution inside the researchers' own tenant pod. From there, misconfigurations (reachable instance metadata, node IAM credentials, Kubernetes node authorizer permissions) allowed reading the environment variables of 24 tenant pods on the same node. Metabase patched the connection logic and hardened its cloud infrastructure before any known malicious exploitation.
Technical Details
- The H2 driver's
connection-details->specruns the sanitizer only on the:dbURL. Thespecfunction forwards every other field (dissoc opts :db) to the connection, includingINIT. - H2 connections are disabled by default, and
POST /api/databasecallscan-connect? :h2, which rejects them. The EE serialization import endpoint builds Database records from uploaded YAML without callingcan-connect?, so the malicious H2 record was persisted. - A database sync then sets
*allow-testing-h2-connections*to true on its own and opens the connection, which runs theINITstatements. - Stage one:
CALL CSVWRITE('/tmp/evil.clj', ...)writes Clojure code to disk. Stage two:CREATE ALIAS LOADCLJ FOR "clojure.lang.Compiler.loadFile"followed byCALL LOADCLJ('/tmp/evil.clj')executes it inside the Metabase process. - From the pod, the EC2 Instance Metadata Service was reachable and returned credentials for the node IAM role
eks-cluster-prod-metabase-1-nodes. These allowed EC2, ECR, S3 and EKS describe calls. - The researchers minted an EKS bearer token and authenticated to the cluster API as
system:node:ip-10-241-27-69.ec2.internal. They then listed pods withGET /api/v1/pods?fieldSelector=spec.nodeName=.... The node authorizer exposed the environment variables of 24 tenant pods on that node, including site URLs andMB_API_KEY. - The researchers state that
MB_API_KEYdid not grant instance access, contrary to their initial assumption. Database credentials in the environment variables were present but untested, and per Metabase they would not have enabled further access. - The approach could scale across further nodes in the prod-metabase-1 cluster. The activity triggered logging alerts at Metabase.
Remediation
- Metabase patched the underlying connection logic and hardened its cloud infrastructure boundaries; no customer action is stated in the article.
- Lessons the article draws: sanitize all connection fields rather than only the URL, block pod access to the instance metadata service, and apply defense in depth for multi-tenant clusters.
Linha do tempo
-
Metabase Cloud: H2 INIT sanitizer bypass gives RCE and cross-tenant secret exposure via EKS node credentials
ler a análise desta fonte ocultar
Researchers at Hacktron disclosed a chain in Metabase Cloud that began with a bypass of the sanitization Metabase applies to H2 connection strings and ended in exposure of secrets belonging to other tenants. Metabase strips or rejects
INIT=in the H2 URL, but theINITvalue could be supplied in a separate details field that was never sanitized. This yielded remote code execution inside the researchers' own tenant pod. From there, misconfigurations (reachable instance metadata, node IAM credentials, Kubernetes node authorizer permissions) allowed reading the environment variables of 24 tenant pods on the same node. Metabase patched the connection logic and hardened its cloud infrastructure before any known malicious exploitation.Technical Details
- The H2 driver's
connection-details->specruns the sanitizer only on the:dbURL. Thespecfunction forwards every other field (dissoc opts :db) to the connection, includingINIT. - H2 connections are disabled by default, and
POST /api/databasecallscan-connect? :h2, which rejects them. The EE serialization import endpoint builds Database records from uploaded YAML without callingcan-connect?, so the malicious H2 record was persisted. - A database sync then sets
*allow-testing-h2-connections*to true on its own and opens the connection, which runs theINITstatements. - Stage one:
CALL CSVWRITE('/tmp/evil.clj', ...)writes Clojure code to disk. Stage two:CREATE ALIAS LOADCLJ FOR "clojure.lang.Compiler.loadFile"followed byCALL LOADCLJ('/tmp/evil.clj')executes it inside the Metabase process. - From the pod, the EC2 Instance Metadata Service was reachable and returned credentials for the node IAM role
eks-cluster-prod-metabase-1-nodes. These allowed EC2, ECR, S3 and EKS describe calls. - The researchers minted an EKS bearer token and authenticated to the cluster API as
system:node:ip-10-241-27-69.ec2.internal. They then listed pods withGET /api/v1/pods?fieldSelector=spec.nodeName=.... The node authorizer exposed the environment variables of 24 tenant pods on that node, including site URLs andMB_API_KEY. - The researchers state that
MB_API_KEYdid not grant instance access, contrary to their initial assumption. Database credentials in the environment variables were present but untested, and per Metabase they would not have enabled further access. - The approach could scale across further nodes in the prod-metabase-1 cluster. The activity triggered logging alerts at Metabase.
Remediation
- Metabase patched the underlying connection logic and hardened its cloud infrastructure boundaries; no customer action is stated in the article.
- Lessons the article draws: sanitize all connection fields rather than only the URL, block pod access to the instance metadata service, and apply defense in depth for multi-tenant clusters.
- The H2 driver's