Skip to main content

Cómo resolver problemas de seguridad en mi aplicación Spring MVC

Escrito por
Blog Header Spring MVC

15 de marzo de 2021

0 minutos de lectura

El framework Spring MVC es muy conocido para crear aplicaciones web interactivas en Java. Implementa el patrón de arquitectura Modelo-Vista-Controlador para separar los distintos aspectos de tu aplicación. Separar los elementos lógicos, como la lógica de presentación, de entrada y de negocio, suele considerarse una buena práctica de arquitectura. Si se implementa correctamente, esta separación de responsabilidades te ofrece, por ejemplo, menos código duplicado y varias vistas para el mismo modelo.

Spring MVC forma parte del framework Spring y se enfoca en crear aplicaciones web en Java. Puede ser una aplicación independiente que use un servidor web separado, como Tomcat, o una aplicación Spring Boot.

Para este artículo, creé una aplicación Spring MVC con páginas web JSP (JavaServer Pages) que se ejecuta en un servidor Tomcat. El código que escribí es muy básico y directo. Aunque funciona perfectamente, cometí algunos errores relacionados con la seguridad. Veamos cómo podemos detectar estos errores en mi aplicación Spring MVC mediante análisis estático de código Java y cómo corregirlos.

Mi aplicación Java Spring MVC

La aplicación Java Spring MVC que creé es muy sencilla. Está basada en Java 11 y usa una versión muy reciente de spring-web-mvc. La implementación respeta el patrón modelo-vista-controlador e interactúa con el usuario mediante páginas JSP sencillas. Puedes encontrar esta aplicación de ejemplo en GitHub y ejecutarla con mvn tomcat7:run.

Las funciones básicas de la aplicación son:

  • Subir un archivo a una carpeta

  • Subir y descomprimir un archivo

  • Mostrar los archivos subidos

  • Escribir un mensaje en el tablero de mensajes

  • Mostrar todos los mensajes

  • Buscar un mensaje específico.

Limité las dependencias a lo mínimo indispensable. Aunque podría usar algunas bibliotecas conocidas para facilitar el trabajo, escribí toda la lógica de negocio por mi cuenta. Además de springweb-mvc, uso:

  • commons-fileupload para subir archivos

  • jstl para la lógica de mis archivos JSP

  • h2, una base de datos en memoria para los mensajes.

Sé que esta aplicación tiene algunos errores de seguridad en el código. Probemos el nuevo Snyk Code y veamos qué tan eficaz es el análisis estático de código Java para encontrar las vulnerabilidades que introduje.

Snyk Code: herramienta de análisis estático de código Java

Snyk Code es un nuevo producto de Snyk que se enfoca en encontrar patrones de código vulnerables en varios lenguajes, incluido Java. El análisis de código Java de Snyk Code también es compatible con los principales frameworks, como Spring MVC, que uso actualmente. Snyk Code es una herramienta de pruebas de seguridad de aplicaciones estáticas (SAST). Aunque SAST es un término que se usa principalmente en el mundo de la seguridad de la información, describe exactamente lo que hace: analiza estáticamente tu código Java para detectar posibles vulnerabilidades. Snyk Code aprovecha el aprendizaje automático para ofrecer una forma muy rápida y fácil de usar para desarrolladores de encontrar vulnerabilidades en el código. Para esta publicación del blog, usaremos la integración de GitHub con Snyk para aprovechar Snyk Code.

Nota: Actualmente estoy usando una versión de acceso anticipado de Snyk Code. Lo más probable es que esté disponible de forma general en abril.

Analizar mi aplicación Java Spring MVC con Snyk Code

Activé Snyk Code en la configuración de mi cuenta de Snyk. Una vez completada la activación, ten en cuenta que Snyk Code analizará todos los repositorios que importes a partir de ese momento. Esto también significa que autorizo a Snyk a inspeccionar mi código. No necesitamos hacerlo cuando solo usamos Snyk Open Source y analizamos dependencias vulnerables. En ese caso, solo necesitamos leer el archivo de manifiesto, como pom.xml o build.gradle.

Página de configuración de Snyk con Snyk Code seleccionado y habilitado mediante un interruptor, y un botón para guardar los cambios

Después de importar el repositorio de GitHub que contiene mi aplicación Java Spring MVC, enseguida veo que Snyk Code ya hizo su trabajo y que el análisis de código Java encontró problemas de seguridad.

Encontró un par de problemas de recorrido de rutas relacionados con la lógica para subir archivos. Snyk Code también detectó varias vulnerabilidades de inyección SQL, un par de problemas con cookies y credenciales codificadas directamente. Veamos rápidamente algunos de ellos.

Vulnerabilidad de recorrido de rutas al subir archivos

Al subir un archivo en mi aplicación Spring MVC, Snyk Code detectó que no saneo el archivo recibido. Si lo escribimos directamente en el sistema de archivos sin verificarlo, es posible recorrer rutas. Un atacante puede crear una solicitud POST cuyo nombre de archivo se evalúe como ../../../../../dir/file.x. Así, se sale del ámbito inicial y se escribe el archivo fuera de la aplicación. Esto también significa que un atacante podría sobrescribir un archivo existente.

Informe de Path Traversal de Snyk Code que destaca la entrada HTTP sin sanitizar que llega a Files.write en UploadController.java

Vulnerabilidad Zip Slip de recorrido de rutas

Se encuentra un problema similar de recorrido de rutas al subir y descomprimir archivos ZIP en mi aplicación Spring MVC. Creo los archivos en el sistema de archivos usando los nombres incluidos en el ZIP, sin sanearlos. Si tu archivo ZIP se parece al que aparece a continuación, crearás o sobrescribirás archivos fuera del ámbito de la aplicación.

-rw-r--r--  18-Apr-15 23:04 good.txt
-rwxrwxrwx  18-Jun-03 17:06 ../../../../../../../../../../../../dir/file.x

Este tipo específico de recorrido de rutas dentro de un archivo ZIP se conoce como vulnerabilidad zip-slip. En el pasado, muchas bibliotecas para comprimir y descomprimir archivos tenían esta vulnerabilidad de seguridad. Por eso, recuerda analizar tus dependencias con Snyk Open Source para detectar estas bibliotecas vulnerables.

Vista de Snyk Code sobre recorrido de rutas que muestra una explicación de la vulnerabilidad y el flujo de datos resaltado en el código Java UploadController.java

Vulnerabilidad de inyección SQL al buscar mensajes

En el repositorio de mensajes que escribí para esta aplicación Java Spring MVC, creo manualmente la consulta de búsqueda usando el parámetro recibido. Como puedes ver en la captura de pantalla, no uso parámetros en la consulta. Al parametrizar una consulta, separas los parámetros de la cadena de consulta propiamente dicha. Puedes validar y sanear los parámetros vinculándolos, por ejemplo, a un tipo específico. Actualmente, solo concateno el parámetro a la consulta existente y la ejecuto. Esto significa que puedo manipular la consulta SQL.

Prueba el siguiente parámetro de búsqueda: '; UPDATE message SET text = 'EVIL. Salgo de la consulta original y ejecuto una nueva instrucción que actualiza todos los mensajes. Probablemente no sea lo que quieres y, por suerte, Snyk Code nos ayudó a encontrar la vulnerabilidad.

Informe de inyección SQL de Snyk que muestra cómo una entrada HTTP sin sanitizar llega a una llamada executeQuery de Java y resalta el código vulnerable.

Otras vulnerabilidades detectadas por el análisis de código Java

Snyk también encontró otros problemas que podrían representar un riesgo. Por ejemplo, las propiedades de conexión de mi base de datos, incluidos el nombre de usuario y la contraseña, están codificadas directamente en el repositorio. Snyk Code me recomendó no hacerlo, y tiene razón.

El análisis de seguridad detecta credenciales de base de datos codificadas directamente en el código Java y muestra una llamada de conexión con DB_URL, USER y PASS.

Snyk Code también detectó un problema con una cookie que configuro. Como se trata de una aplicación web Spring MVC, guardo el ID de usuario en una cookie práctica en el sistema del cliente. Sin embargo, la vigencia máxima de esta cookie está configurada en un año. Si guardas información confidencial en una cookie, no es buena idea establecer un valor alto para maxAge. Si usas cookies para almacenar datos temporalmente, deben tener una vigencia limitada. Snyk Code me lo señala por un buen motivo.

Hallazgo de seguridad por tiempo de expiración de sesión insuficiente, con un fragmento de código de Spring MVC en CookieUtil.java que muestra una duración máxima de un año para la cookie.

Conclusión

Al crear una aplicación web muy sencilla en Java con Spring MVC, pueden surgir muchos problemas. Ten en cuenta que no analicé todos los problemas que Snyk Code encontró en esta aplicación de demostración. Te dejo el resto como ejercicio.

Si escribes toda la lógica de negocio por tu cuenta, pueden pasar inadvertidos algunos problemas de seguridad. Ten en cuenta que existen bibliotecas bien mantenidas que te ayudan a lograr el mismo objetivo. Un gran ejemplo dentro del framework Spring son las bibliotecas spring-data, que pueden ayudarte a consultar tu base de datos. Cuando uses bibliotecas externas, recuerda analizarlas con Snyk Open Source para evitar incluir una biblioteca vulnerable. Aun así, es fácil introducir problemas de seguridad en tu propio código Java, y puede pasarle a cualquiera. Es difícil detectar estas vulnerabilidades durante una revisión de código. Por suerte, contamos con una excelente herramienta de análisis estático de código Java, como Snyk Code, que te ayuda a hacerlo.

Protege tu código con información de vanguardia

Conoce todas las funcionalidades de SAST de Snyk Code en solo 30 minutos.