Cada lenguaje de programación viene con su propio conjunto de vulnerabilidades de seguridad, y JavaScript no es una excepción. Explotar las vulnerabilidades de JavaScript puede llevar a la manipulación de datos, secuestro de sesiones, acceso no autorizado a datos y más. Aunque comúnmente asociado con la funcionalidad del lado del cliente, los riesgos de seguridad de JavaScript también pueden representar amenazas significativas en entornos del lado del servidor.
Para cualquier aplicación, la confianza del cliente es muy importante. Mantener esta confianza requiere proteger los datos del cliente y garantizar la seguridad de las aplicaciones. Afortunadamente, implementar salvaguardias adecuadas puede mitigar estos riesgos y mejorar la seguridad de su aplicación.
En este artículo, exploraremos algunas de las amenazas de seguridad de JavaScript más comunes y discutiremos herramientas y estrategias efectivas para proteger su aplicación de posibles ataques.
Scripting entre sitios
El scripting entre sitios (XSS) es una vulnerabilidad de seguridad que permite a un atacante inyectar código malicioso del lado del cliente en un sitio web. Según el Proyecto de Seguridad de Aplicaciones Web Abiertas (OWASP) Las 10 principales vulnerabilidades de seguridad en 2021, XSS se clasifica como el tercer vector de ataque más común.
Cómo mitigar XSS
Validación de entrada
Asegúrese de que la entrada del usuario se adhiera a los tipos de datos, formatos y rangos esperados. Elimine o escape los caracteres potencialmente dañinos para evitar la inyección.
function validateInput(input) {
return input.replace(/[^a-zA-Z0-9]/g, ''); // Allow only alphanumeric characters
}
Codificación de salida
Convertir los caracteres especiales en la salida a sus equivalentes de entidad HTML para neutralizar posibles scripts maliciosos antes de renderizar.
function encodeHTML(input) {
return input.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Clickjacking
Clickjacking es un ataque engañoso que engaña a los usuarios para que hagan clic en un elemento con el que no pretenden interactuar. Esta técnica implica incrustar un sitio web legítimo dentro de uno malicioso, a menudo utilizando un <iframe>
HTML invisible o engañosamente posicionado, para secuestrar las acciones del usuario. Como resultado, los atacantes pueden robar credenciales de inicio de sesión, obtener permisos no autorizados o incluso engañar a los usuarios para que instalen malware sin saberlo.
Una forma común de lograr esto es usar CSS para agregar un botón superpuesto con opacity
configurado en casi 0. Esto engaña al usuario para que haga clic en un botón o enlace no deseado.
Cómo prevenir el Clickjacking
La directiva X-Frame-Options indica al navegador si el sitio puede ser incrustado dentro de un iframe. Tiene tres opciones:
- DENY – Impide que la página se muestre en un iframe por completo
- SAMEORIGIN – Permite que la página se incruste solo si la solicitud proviene del mismo dominio
- ALLOW-FROM – Permite que la página se incruste solo por un dominio específico y de confianza
En Node.js puedes usar helmet
para establecer estas opciones como se muestra a continuación:
const helmet = require("helmet");
const app = express();
app.use(
helmet({
xFrameOptions: { action: "sameorigin" },
}),
);
Una defensa efectiva contra el clickjacking es implementar el encabezado de Política de Seguridad de Contenido (CSP). CSP proporciona un control detallado sobre cómo y dónde se puede incrustar el contenido, evitando el enmarcado no autorizado.
Para mitigar los riesgos de clickjacking, incluya la directiva frame-ancestors
en su encabezado CSP. Por ejemplo:
Content-Security-Policy: frame-ancestors 'self' https://www.example.org;
Esta política asegura que el documento protegido solo pueda ser incrustado por su propia origen ('self'
) y dominios explícitamente permitidos, como example.org
. Bloquea todos los intentos no autorizados de enmarcar el contenido, protegiendo a los usuarios de ataques de clickjacking.
Nota: Si tanto frame-ancestors como X-Frame-Options están configurados, entonces los navegadores que admiten frame-ancestors ignorarán X-Frame-Options.
Falsificación de solicitudes entre sitios (CSRF)
CSRF (a veces también llamado XSRF) explota la confianza que un sitio web tiene en el navegador de un usuario al realizar solicitudes no autorizadas en nombre del usuario. Los atacantes engañan a los usuarios para que ejecuten acciones sin su conocimiento, lo que podría provocar filtraciones de datos o transacciones no deseadas. Algunos ejemplos son actualizar los detalles personales de la víctima, iniciar una transferencia de fondos desde la cuenta bancaria de la víctima o incluso redirigir una entrega de paquete a una dirección diferente.
Veamos un ejemplo específico de esto. Estás visitando el sitio web de tu banco y has iniciado sesión. Supongamos que recibes un correo electrónico de un sorteo que finge ser tu banco. El enlace te lleva a una página web aparentemente inofensiva. Detrás de escena, se activa una solicitud POST y se envía a la aplicación legítima del banco.
curl --location --request POST 'https://acmebank.com/transfer?routing=852363&fromAccountNumber=123456789&toAccountNo=987654321' \
--header 'Cookie: session=acmebanksessionvalue'
En el lado de la aplicación acmebank.com, la etiqueta “script” envía el formulario tan pronto como el usuario carga la página, sin ninguna validación del usuario o sin que el usuario se dé cuenta de lo que está sucediendo, como se muestra a continuación.
<html>
<body>
<form action="https://acmebank.com/transfer" method="POST">
<input type="hidden" routing="852363" fromAccountNo="123456789" toAccountNo="987654321" amount="5000" />
</form>
<script>
window.addEventListener("DOMContentLoaded", () => {
document.querySelector("form").submit();
});
</script>
</body>
</html>
El formulario anterior crea la siguiente solicitud a la aplicación real, acmebank. La solicitud contiene la cookie de sesión del usuario legítimo, ¡pero contiene nuestro número de cuenta bancaria! Debido a que tu sesión con tu banco sigue activa, la transferencia por el monto se procesará si no hay otra validación en su lugar.
Cómo Defenderse Contra CSRF
Establece el atributo SameSite configurado en Estricto. Esto controla si se envía o no una cookie con solicitudes entre sitios.
- Estas cookies de sesión deberían tener una vida útil corta. Requiere re-autenticación para acciones sensibles para mitigar riesgos.
Utilice tokens CSRF únicos por sesión. Este token luego puede incluirse dentro de un formulario que es enviado por el navegador. Para cada solicitud, el servidor compara el token enviado por el cliente con su valor almacenado para la sesión. Utilice la biblioteca csrf-csrf para configurar tokens únicos.
Robo de Datos de Sesión
El secuestro de sesiones ocurre cuando un atacante roba el token de sesión de un usuario, lo que le permite suplantar al usuario y obtener acceso no autorizado a su cuenta.
Cómo Prevenir el Secuestro de Sesiones
Utilice Cookies Seguras
Establezca las banderas Secure
y HttpOnly
en las cookies de sesión para prevenir el acceso no autorizado. Establecer el atributo Secure evita que la cookie de sesión se transmita en texto claro y solo permite que se transmita a través de conexiones HTTPS. Establecer el atributo Http-Only
hace que el navegador no permita el acceso a la cookie desde el DOM lo que previene que los ataques basados en scripts del lado del cliente accedan a los datos sensibles almacenados en esas cookies.
Active la Autenticación Multifactor (MFA)
Agregue una capa adicional de seguridad para verificar a los usuarios. Este es un método muy común que encontrará en la mayoría de las aplicaciones seguras. Las integraciones fáciles están disponibles a través de proveedores como Okta y Duo.
Implementar Caducidad de Sesión
Expirar automáticamente sesiones inactivas para reducir las ventanas de ataque.
Prácticas y Herramientas de Codificación para una Seguridad de Alto Nivel
Escaneo de Vulnerabilidades
Un escáner de vulnerabilidades mantiene la seguridad de tu aplicación. Escanear tus bibliotecas, red, aplicaciones y dispositivos ayuda a descubrir debilidades que los atacantes podrían explotar. Herramientas como Snyk y Sonarqube pueden integrarse fácilmente en bases de código JavaScript. Estas herramientas funcionan en paralelo con listas conocidas de vulnerabilidades mantenidas por OWASP. Con una integración fluida como parte del proceso de desarrollo, estos escáneres brindan a los desarrolladores y equipos de seguridad una visibilidad en tiempo real y precisa sobre las vulnerabilidades del código y soluciones para corregirlas.
Pruebas de Penetración y Evaluaciones
Los desarrolladores pueden adoptar prácticas de pruebas de penetración para investigar y explotar activamente posibles vulnerabilidades dentro de una aplicación. Los hackers éticos simulan ataques del mundo real para evaluar la postura de seguridad de las aplicaciones web manipulando el código JavaScript y las interacciones de los usuarios.
Para lograr esto, los desarrolladores pueden escribir código JS personalizado para simular los escenarios, o pueden utilizar herramientas especializadas de pruebas de penetración que aprovechan JavaScript para automatizar el proceso de escaneo en busca de vulnerabilidades comunes como XSS, utilizando OWASP ZAP. Más información sobre pruebas de penetración está disponible en la guía oficial de OWASP.
Firewall de Aplicaciones Web (WAF)
Conforme las aplicaciones crecen, también lo hace el tráfico web, aumentando la exposición a ataques. Implementar un Firewall de Aplicaciones Web (WAF) ayuda a proteger contra tráfico malicioso filtrando y monitoreando las solicitudes HTTP. Esto implica la integración con proveedores de WAF de terceros como Cloudflare o AWS WAF. Con WAF, puedes definir reglas como:
- País o ubicación geográfica de donde provienen las solicitudes.
- Dirección IP, rango CIDR y nombres de dominio de donde provienen las solicitudes.
- Limitar la longitud de las solicitudes y los parámetros de consulta para prevenir ataques de inyección.
- Código SQL que probablemente sea malicioso. Los atacantes intentan extraer datos de tu base de datos insertando código SQL malicioso en una solicitud web. Esto se conoce como inyección SQL.
- Detectar y bloquear scripts incrustados que puedan ser parte de ataques XSS.
Un WAF también puede ayudar a mitigar Denegación de Servicio Distribuida (DDoS), asegurando la disponibilidad de la aplicación.
Proteger la Integridad de los Datos
Implementar medidas robustas de integridad de datos es esencial al almacenar o acceder a información segura. Las mejores prácticas incluyen:
- Imponer políticas de contraseñas fuertes y fomentar el uso de gestores de contraseñas. Además, anime a sus usuarios a utilizar un gestor de contraseñas para que puedan usar contraseñas más complejas y no tengan que preocuparse por recordarlas (utilice LastPass o 1Password).
- Protegerse contra ataques de fuerza bruta en las páginas de inicio de sesión con limitación de tasa, bloqueos de cuenta después de un cierto número de intentos fallidos, y desafíos CAPTCHA.
- Utilizando cabeceras HTTP como:
- HTTP Access-Control-Allow-Origin para controlar qué orígenes pueden acceder a recursos.
- HTTP X-Content-Type-Options para prevenir riesgos de seguridad de tipos MIME.
- Integridad de subrecursos (SRI) para asegurar que los recursos de CDNs no han sido alterados.
Conclusión
La seguridad de JavaScript es un proceso continuo que requiere un enfoque proactivo para proteger las aplicaciones de las amenazas en constante evolución. La implementación de las mejores prácticas, como la validación de entradas, los encabezados CSP, la gestión segura de sesiones y la exploración de vulnerabilidades, puede reducir significativamente el riesgo de ataques como XSS, CSRF y secuestro de sesiones.
Además, el uso de herramientas de seguridad como WAFs, pruebas de penetración y MFA fortalece la resistencia de la aplicación. Dar prioridad a la seguridad en cada etapa del desarrollo permitirá a los desarrolladores construir aplicaciones sólidas y dignas de confianza de los usuarios que permanezcan protegidas contra las amenazas cibernéticas modernas.
Source:
https://dzone.com/articles/enhancing-security-in-javascript