Seguridad de aplicaciones JavaScript: top 10 vulnerabilidades para principiantes
\n\nEl desarrollo en JavaScript, especialmente en el entorno Node.js, abre amplias posibilidades para crear aplicaciones web modernas. Sin embargo, con el poder viene la responsabilidad. Ignorar los problemas de seguridad puede provocar fugas de datos, pérdidas financieras y daños a la reputación. Para los desarrolladores principiantes, comprender las amenazas básicas es el primer paso para crear código seguro. En este artículo, analizaremos las 10 principales vulnerabilidades de JavaScript (Node.js) basadas en la lista de OWASP, con ejemplos de código y consejos prácticos de protección.
\n\n1. Secuencias de comandos entre sitios (XSS)
\nXSS es uno de los ataques más comunes. El atacante inyecta un script malicioso en una página web que se ejecuta en el navegador de la víctima. En Node.js, esto suele ocurrir a través de la salida de datos sin escapar.
\n\nEjemplo de código vulnerable (Express):
\napp.get('/user/:name', (req, res) => {\n res.send('<h1>Hola, ' + req.params.name + '</h1>');\n});\n\n\nCómo protegerse: Utilice motores de plantillas con escape automático (por ejemplo, Handlebars, EJS) o bibliotecas como helmet. Nunca inserte entrada de usuario directamente en HTML.
app.get('/user/:name', (req, res) => {\n const safeName = encodeURIComponent(req.params.name);\n res.send(`<h1>Hola, ${safeName}</h1>`);\n});\n\n\n2. Inyecciones SQL
\nSi su aplicación utiliza una base de datos SQL (por ejemplo, PostgreSQL o MySQL), el manejo incorrecto de las consultas puede provocar la ejecución de código SQL arbitrario.
\n\nCódigo vulnerable:
\nconst query = `SELECT * FROM users WHERE email = '${userInput}'`;\ndb.query(query, callback);\n\n\nSolución: Utilice siempre consultas parametrizadas o un ORM (por ejemplo, Sequelize, Prisma).
\n\nconst query = 'SELECT * FROM users WHERE email = $1';\ndb.query(query, [userInput], callback);\n\n\n3. Falsificación de peticiones entre sitios (CSRF)
\nEl ataque CSRF obliga al usuario a realizar una acción no deseada en un sitio donde está autenticado. Por ejemplo, transferir dinero o cambiar la contraseña.
\n\nProtección: Utilice tokens CSRF. En Express, la biblioteca popular csurf (obsoleta, pero reemplazada por csrf-csrf o soluciones integradas de frameworks).
const csrf = require('csrf-csrf');\nconst { generateToken } = csrf();\n\napp.post('/transfer', (req, res) => {\n const token = req.body._csrf;\n if (!validateToken(token)) {\n return res.status(403).send('Ataque CSRF');\n }\n // Ejecutar la transferencia\n});\n\n\n4. Dependencias no seguras
\nLas aplicaciones Node.js utilizan miles de paquetes de npm. Las dependencias obsoletas o vulnerables son una causa común de ataques.
\n\nRecomendaciones:
\n- \n
- Ejecute regularmente
npm auditpara verificar vulnerabilidades. \n - Utilice
snykoDependabotpara actualizaciones automáticas. \n - Elimine los paquetes no utilizados. \n
5. Autenticación y gestión de sesiones inseguras
\nContraseñas débiles, falta de límite en intentos de inicio de sesión, almacenamiento incorrecto de tokens de sesión: todo esto conduce al compromiso de cuentas.
\n\nMejores prácticas:
\n- \n
- Almacene las contraseñas con hash (bcrypt, argon2). \n
- Utilice JWT con vida útil corta y tokens de actualización. \n
- Establezca un límite en los intentos de inicio de sesión (rate limiting). \n
const bcrypt = require('bcrypt');\nconst saltRounds = 10;\n\n// Registro\nconst hash = await bcrypt.hash(password, saltRounds);\n\n// Inicio de sesión\nconst match = await bcrypt.compare(inputPassword, hash);\n\n\n6. Deficiencias en el control de acceso
\nUsu