
Доказательство концепции для CVE-2026-75855, обхода пути в командах создания/удаления базы данных ArcadeDB, позволяющего произвольную запись и удаление файлов за пределами настроенного каталога.
Path Traversal в командах сервера "create database" / "drop database" позволяет произвольную запись и удаление файлов за пределами настроенной директории базы данных
Команды create database и drop database конечной точки POST /api/v1/server используют имя базы данных, переданное вызывающей стороной, для построения пути в файловой системе без какой-либо санитизации, нормализации или проверки на ограничение пути. Пользователь, аутентифицированный как root-аккаунт сервера ArcadeDB, может указать имя, содержащее последовательности ../, чтобы заставить сервер создать (а затем удалить) целую базу данных — произвольные файлы и директории — по любому абсолютному пути в файловой системе, доступному для записи процессу сервера, полностью за пределами настроенной arcadedb.server.databaseDirectory.
Это было проверено вживую, дважды независимо с чистого состояния: специально сформированная команда create database записала реальные файлы базы данных в /tmp/ и, в отдельном тесте, в ; соответствующая команда с той же строкой обхода затем рекурсивно удалила директорию.
/etc/drop databaseserver/src/main/java/com/arcadedb/server/http/handler/PostServerCommandHandler.java:
private void createDatabase(final String databaseName) {
if (databaseName.isEmpty())
throw new IllegalArgumentException("Database name empty");
checkServerIsLeaderIfInHA();
final ArcadeDBServer server = httpServer.getServer();
final ServerDatabase db = server.createDatabase(databaseName, ComponentFile.MODE.READ_WRITE);
...
}
Единственная проверка — это проверка на непустоту. databaseName передаётся без изменений в ArcadeDBServer.createDatabase() (server/src/main/java/com/arcadedb/server/ArcadeDBServer.java:572):
final DatabaseFactory factory = new DatabaseFactory(
configuration.getValueAsString(GlobalConfiguration.SERVER_DATABASE_DIRECTORY) + File.separator
+ databaseName).setAutoTransaction(true);
Это простая конкатенация строк, а не Path.resolve() с проверкой на ограничение пути. DatabaseFactory (engine/src/main/java/com/arcadedb/database/DatabaseFactory.java) никогда не вызывает .normalize() и не проверяет, что разрешённый путь остаётся в пределах целевой базовой директории, до того как create()/open() запишут файлы на диск.
dropDatabase() имеет такое же отсутствие проверки, и поскольку сервер отслеживает базу данных под буквальным (содержащим обход) именем, указанным вызывающей стороной, последующая команда drop database рекурсивно удаляет любую директорию, в которую записала команда create database.
checkRootUser(user) применяется перед обеими командами, поэтому это требует root-аккаунта сервера — но root здесь — это собственный суперпользователь уровня приложения ArcadeDB, что не обязательно означает тот же уровень доверия, что и доступ к ОС/оболочке хоста. Нарушение ограничения databaseDirectory позволяет этой учётной записи уровня приложения записывать и удалять произвольные файлы в любом месте, где процесс JVM имеет разрешения ОС.
Окружение: ArcadeData/arcadedb @ коммит 545e703, собран из исходников (./mvnw -pl engine,server -am install -DskipTests), запущен автономно с установленным arcadedb.server.rootPassword и arcadedb.server.databaseDirectory=/databases.
Убедитесь, что целевая директория базы данных пуста.
Отправьте команду create database с payload обхода:
curl -u root: -X POST http://127.0.0.1:2480/api/v1/server \
-H "Content-Type: application/json" \
-d '{"command":"create database ../../../../../../tmp/arcadedb-traversal-poc"}'
→ {"result":"ok"} HTTP 200
ls -la /tmp/arcadedb-traversal-poc/
→ configuration.json, schema.json, dictionary..dict, txlog_.wal — полноценная, реальная база данных ArcadeDB. Предназначенная директория databases/ остаётся пустой на протяжении всего процесса.
list databases возвращает буквальную строку обхода как зарегистрированное имя, что подтверждает нулевую нормализацию:{"result":["../../../../../../tmp/arcadedb-traversal-poc"]}
Повторено с более глубоким обходом в /etc/arcadedb-poc2 — успешно аналогичным образом, что демонстрирует, что запись не ограничена /tmp или какой-либо конкретной областью файловой системы, а только тем, куда процесс может записывать. Также воспроизведено с минимальным одноуровневым обходом ../, что подтверждает реальный выход за пределы пути, а не случайный результат.
drop database с той же строкой обхода рекурсивно удаляет директорию:
curl -u root: -X POST http://127.0.0.1:2480/api/v1/server \
-H "Content-Type: application/json" \
-d '{"command":"drop database ../../../../../../tmp/arcadedb-traversal-poc"}'
→ {"result":"ok"}; директория подтверждённо удалена после этого.
create database) и произвольное рекурсивное удаление (через drop database) по любому абсолютному пути, доступному для записи процессу сервера, полностью за пределами песочницы настроенной databaseDirectory.Отклонять имена баз данных, содержащие разделители пути (/, \) или сегменты .. outright (простое регулярное выражение с allow-list, например ^[A-Za-z0-9_-]+$, является стандартным для этого класса идентификаторов), и защитно разрешать конечный путь с помощью Path.resolve(name).normalize() и проверять, что он всё ещё начинается с настроенной базовой директории перед любой файловой операцией, как в createDatabase, так и в dropDatabase.
Автор: Pervin Zahidli (@ech0void )