
Технический анализ уязвимости и proof-of-concept для CVE-2026-47630: произвольный dlopen через TRITON_BATCH_STRATEGY_PATH в NVIDIA Triton Inference Server, обеспечивающий выполнение нативного кода, с рекомендациями по обнаружению и устранению.
dlopen через TRITON_BATCH_STRATEGY_PATHОбход каталога с использованием абсолютного пути (absolute path traversal) в загрузчике пользовательских стратегий батчинга из triton-inference-server/core. Параметр конфигурации модели передаётся без проверки в dlopen(RTLD_NOW | RTLD_LOCAL), поэтому любой, кто может влиять на config.pbtxt модели, получает возможность выполнять нативный код внутри процесса сервера Triton в момент загрузки модели.
Подтверждение NVIDIA в бюллетене 5865 дословно гласит: CVE-2026-47630: s1ko.
Triton принимает параметр TRITON_BATCH_STRATEGY_PATH из config.pbtxt модели. Вплоть до версии 26.05 значение обрабатывалось как произвольный путь файловой системы и передавалось в dlopen без изменений. Не было ни проверки на выход за пределы каталога, ни списка разрешённых путей, ни проверки подписи или хеша. Принимались и абсолютные пути, и последовательности обхода каталогов, и символические ссылки.
RTLD_NOW немедленно разрешает все символы и выполняет процедуры __attribute__((constructor)) / .init_array объекта до возврата из dlopen. Следовательно, выполнение не зависит от успешности загрузки — для запуска полезной нагрузки не требуется наличие ни одной из точек входа TRITONBACKEND_ModelBatch*, и она выполняется с привилегиями процесса Triton (часто root в NGC-контейнерах).
src/backend_model.cc — ввод атакующего достигает batch_libpath и проверяется только на существование:
if (model_config.parameters().contains("TRITON_BATCH_STRATEGY_PATH")) {
batch_libpath = model_config.parameters()
.at("TRITON_BATCH_STRATEGY_PATH")
.string_value();
bool exists = false;
RETURN_IF_ERROR(FileExists(batch_libpath, &exists));
if (!exists) {
return Status(
triton::common::Error::Code::NOT_FOUND,
("Batching library path not found: " + batch_libpath).c_str());
}
}
Примечательно отсутствие какого-либо вызова IsChildPathEscapingParentPath, который Triton уже применял к путям меток (label paths) и путям библиотек бэкендов в других местах того же файла.
src/backend_model.cc — SetBatchingStrategy передаёт его дальше:
Status TritonModel::SetBatchingStrategy(const std::string& batch_libpath)
{
std::unique_ptr<SharedLibrary> slib;
RETURN_IF_ERROR(SharedLibrary::Acquire(&slib));
RETURN_IF_ERROR(slib->OpenLibraryHandle(batch_libpath, &batch_dlhandle_));
src/shared_library.cc — sink (точка выполнения):
*handle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
Три практических пути к контролю над model_config.parameters():
config.pbtxt своей модели, размещает .so в собственном каталоге и указывает параметр на него. Полезная нагрузка выполняется с привилегиями сервера, что даёт доступ к весам, секретам и GPU всех остальных арендаторов.TRITONSERVER_ServerLoadModelWithParameters вместе с документированным префиксом параметра file:<rel-path> позволяет вызывающей стороне с правами на загрузку моделей передать config.pbtxt и .so в одном запросе и немедленно запустить загрузку. Доступ к файловой системе вне API не требуется.dlopen по требованию.poc/ содержит примитив, урезанный до того, что делает OpenLibraryHandle. Только исходный код — соберите его самостоятельно:
$ cd poc && ./build.sh
$ gcc -O0 -o test_dlopen test_dlopen.c -ldl
$ ./test_dlopen ./evil.so
dlopen OK, handle=0x55d1779652c0
$ cat /tmp/triton_dlopen_rce_proof.log
[triton-dlopen-rce] constructor fired @ Fri May 1 09:56:56 2026
pid=240157 uid=1000 euid=1000 cwd=/opt/poc
Полезная нагрузка инертна: она дописывает одну строку с pid, uid, euid и cwd. Проверено на Debian 13, GCC 14.2, x86_64.
Для триггера на стороне Triton поместите собранный evil.so рядом с poc/config.pbtxt в хранилище моделей и загрузите модель — автозагрузкой, через --load-model или POST /v2/repository/models/evil_model/load. На затронутой версии конструктор срабатывает во время SetBatchingStrategy, до любого поиска символов бэкенда.
Загрузка логируется самим Triton на уровне INFO:
Loading custom batching strategy library <path> for model <name>
На исправленной сборке отклонённая попытка проявляется как Batching library path escapes model repository.
Любое значение TRITON_BATCH_STRATEGY_PATH, которое является абсолютным, содержит .. или разрешается за пределы каталога модели, заслуживает алерта независимо от версии. Sigma-правило, покрывающее и строку лога, и параметр конфигурации, находится в detection/.
Дополнительные сигналы:
config.pbtxt, вообще содержащие параметр TRITON_BATCH_STRATEGY_PATH, — на практике эта функция редка, поэтому одно лишь наличие уже является полезным фильтром.openat/mmap файла .so за пределами корня модели процессом tritonserver (auditd, eBPF или Falco).Обновитесь до Triton Inference Server 26.06 или новее. Исправление добавляет проверку на выход за пределы каталога, которой не хватало загрузчику:
bool escapes{true};
RETURN_IF_ERROR(IsChildPathEscapingParentPath(
batch_libpath, localized_model_dir->Path(), &escapes));
if (escapes) {
return Status(
Status::Code::INVALID_ARG,
"Batching library path escapes model repository.");
}
Если обновление невозможно сразу, компенсирующие меры контроля:
TRITON_BATCH_STRATEGY_PATH из каждого config.pbtxt, прежде чем он попадёт в хранилище моделей.--model-control-mode в значении, отличном от explicit, либо авторизацию на конечных точках репозитория), если он не требуется.tritonserver от непривилегированного пользователя с хранилищем моделей, смонтированным в режиме только для чтения, чтобы успешная загрузка имела минимально возможный радиус поражения.Соответствие: MITRE ATT&CK T1574.006 Hijack Execution Flow: Dynamic Linker Hijacking и T1129 Shared Modules; NIST SP 800-53r5 SI-7, CM-5, SC-18; CIS Controls v8 §2, §4.
triton-inference-server/core — https://github.com/triton-inference-server/coreMIT — см. LICENSE.
| CVE | CVE-2026-47630 |
| Бюллетень NVIDIA | 5865 (2026-08-18) |
| CWE | CWE-36 (Absolute Path Traversal); также указано как CWE-114 / CWE-829 |
| CVSS v3.1 (NVIDIA) | 5.5 MEDIUM — AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Затронутые версии | Triton Inference Server 0.0 – 26.05 (Linux) |
| Исправлено в | 26.06 |
| Сообщил | s1ko (github.com/s1ko, [email protected]) |
| Отслеживание у вендора | тикет NVIDIA PSIRT 6139742 |
| Дата | Событие |
|---|
| 2026-04-25 | Первичная находка об обработке путей в Triton сообщена; NVIDIA PSIRT открывает тикет 6128799 |
| 2026-05-01 | Эта вторичная находка подтверждена и сообщена; PSIRT открывает тикет 6139742 |
| 2026-05-28 | Согласован порядок скоординированного раскрытия с PSIRT |
| 2026-06 | Исправление выходит в Triton Inference Server 26.06 |
| 2026-08-18 | NVIDIA публикует бюллетень 5865 с присвоением CVE-2026-47630 и указанием s1ko автором |
| 2026-08-22 | Опубликован данный разбор |