Seguridad de aplicaciones Java: top 10 vulnerabilidades en la práctica
La seguridad de las aplicaciones Java no es solo una casilla en una lista de verificación, sino un aspecto crítico del desarrollo. Según OWASP, más del 70% de las aplicaciones web modernas contienen al menos una vulnerabilidad crítica. En este artículo analizaremos las 10 amenazas más comunes con ejemplos reales de código y formas de solucionarlas. El material será útil tanto para desarrolladores Java principiantes como experimentados.
1. Inyecciones SQL (Injection)
La inyección SQL sigue siendo la principal vulnerabilidad. Un atacante puede inyectar código SQL malicioso a través de la entrada del usuario.
Código vulnerable:
String query = "SELECT * FROM users WHERE username = '" + username + "'";Statement stmt = connection.createStatement();ResultSet rs = stmt.executeQuery(query);Código corregido (uso de PreparedStatement):
String query = "SELECT * FROM users WHERE username = ?";PreparedStatement pstmt = connection.prepareStatement(query);pstmt.setString(1, username);ResultSet rs = pstmt.executeQuery();2. XSS (Cross-Site Scripting)
Los ataques XSS permiten inyectar scripts del lado del cliente en páginas web. La protección principal es el escape de la salida.
Código vulnerable (JSP):
<%= request.getParameter("comment") %>Código corregido:
<%= Encode.forHtml(request.getParameter("comment")) %>Utilice la biblioteca OWASP Java Encoder para un escape confiable:
import org.owasp.encoder.Encode;String safeOutput = Encode.forHtml(userInput);3. Deserialización insegura
La deserialización de Java puede provocar la ejecución remota de código (RCE).
Código vulnerable:
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());Object obj = ois.readObject(); // ¡Peligro!Recomendaciones de protección:
- No deserialice datos de fuentes no confiables
- Utilice una lista blanca de clases al deserializar
- Use JSON o XML en lugar de la serialización de Java
// Enfoque seguro con verificación de claseObjectInputStream ois = new ObjectInputStream(inputStream) { @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (!allowedClasses.contains(desc.getName())) { throw new InvalidClassException(desc.getName(), "Deserialización no autorizada"); } return super.resolveClass(desc); }};4. CSRF (Cross-Site Request Forgery)
Los ataques CSRF obligan al usuario a realizar acciones no deseadas en un sitio donde está autenticado.
Protección con tokens (Spring Security):
@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); }}Agregar token al formulario:
<form action="/transfer" method="POST"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <input type="text" name="amount"/> <button type="submit">Transferir</button></form>5. Fuga de información a través de excepciones
Los mensajes de error detallados pueden revelar la estructura interna de la aplicación.
Código vulnerable:
try { // lógica de negocio} catch (SQLException e) { response.getWriter().println("Error: " + e.getMessage()); // ¡Fuga!}<