Desde los sitios web HTML en los años 80 hasta las aplicaciones web progresivas en 2024, el desarrollo web ha avanzado enormemente. Y a medida que han mejorado las capacidades del lado cliente, también lo ha hecho la importancia de la seguridad. Puede que antes no fuera tan relevante tener una buena seguridad en una página HTML estática, pero los sitios web modernos almacenan cookies, contraseñas, información de tarjetas de crédito y otros datos. Por lo tanto, la seguridad del lado cliente es ahora más crucial que nunca.
Este artículo ofrece un resumen general sobre la seguridad del lado cliente y cubre los siguientes temas:
Cada sección incluye una descripción y algunas técnicas que puedes implementar. También se ofrecen algunos fragmentos de código en JavaScript para demostración. Finalmente, espero que disfrutes leyendo este artículo tanto como yo disfruté escribiéndolo.
La validación de entradas es el proceso de filtrar lo que los usuarios introducen en una aplicación. Es esencial para la seguridad del lado cliente y se necesita, aunque no es suficiente por sí sola.
Considera el siguiente escenario: alguien quiere atacar tu sitio web con un virus. Para hacerlo, accede al formulario de "Contáctanos" e ingresa caracteres que el navegador interpretará como código y ejecutará. Ahora tu sitio está ejecutando código que no diseñaste, lo que puede llevar a comportamientos extraños e incluso al robo de datos de los usuarios.
Puedes evitar todo esto asegurándote de que no entre información maliciosa en tu sitio web. Puedes usar una técnica de "lista blanca", lo que significa que tienes una lista de caracteres permitidos. Cualquier otro será rechazado. También puedes usar una técnica de "lista negra", que contiene una lista de caracteres que NO están permitidos. En general, las listas blancas son más seguras que las listas negras, ya que estas últimas son más susceptibles a evasiones de filtros.
Cualquier buena técnica de validación de entradas debe garantizar la validez tanto de la sintaxis como de la semántica. La validez sintáctica asegura que una entrada esté en la forma o tipo correctos. Por ejemplo, el código CVV de una tarjeta de crédito debe ser siempre de tres dígitos. La validez semántica asegura que los datos ingresados sigan el contexto correcto. Por ejemplo, la fecha de caducidad de una tarjeta de débito siempre debe ser una fecha futura.
Ahora que entiendes lo básico sobre la validación de entradas, revisemos algunas técnicas comunes.
required
, pattern
, type
, min-length
, max-length
, entre otros. Lee más aquí
<!-- Requiriendo un campo -->
<input type="text" name="username" required>
<!-- Estableciendo un patrón para la entrada -->
<input type="text" name="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
<!-- Limitando la longitud de la entrada -->
<input type="text" name="zipcode" minlength="5" maxlength="9">
// Código para eliminar etiquetas HTML de la entrada
function sanitizeInput(input) {
return input.replace(/</g, '<').replace(/>/g, '>');
}
// Código para eliminar espacios en blanco y limitar a caracteres alfanuméricos
function sanitizeUsername(username) {
return username.trim().replace(/[^a-zA-Z0-9]/g, '');
}
// Validación de contraseña (al menos 8 caracteres, 1 mayúscula, 1 número)
const passwordPattern = /^(?=.*[A-Z])(?=.*\d).{8,}$/;
function validatePassword(password) {
return passwordPattern.test(password);
}
La autenticación de usuarios es el proceso de verificar la identidad de un usuario antes de darle acceso a su cuenta y todo lo que esté asociado con ella. La autenticación es útil para la experiencia del usuario, pero lo más importante es que es una medida de seguridad que asegura que los datos sensibles solo sean accedidos por las partes autorizadas.
La autenticación de usuarios es fundamental para la seguridad web. Sin ella, las cuentas de los usuarios son vulnerables a ataques cibernéticos. Considera un sitio web sin autenticación de dos factores. Es fácil hackear la cuenta de un usuario en un sitio así. Todo lo que un atacante tiene que hacer es adivinar la contraseña del usuario. Por eso es importante utilizar el factor de conocimiento, el factor de posesión y el factor inherente.
El factor de conocimiento se basa en algo que solo el usuario sabe, como preguntas de seguridad o contraseñas. El factor de posesión, en cambio, se refiere a la autenticación que requiere dispositivos físicos propiedad del usuario, como una billetera física de criptomonedas. Finalmente, el factor inherente para la autenticación tiene que ver con la biometría, como huellas dactilares o reconocimiento facial.
// Autenticación básica con contraseña
function authenticateUser(username, password) {
const user = database.findUser(username);
if (user && user.password === password) {
return true; // Autenticación exitosa
}
return false; // Autenticación fallida
}
La autorización de usuarios es la emisión condicional de permisos a los diferentes tipos de usuarios en un sitio web. En resumen, la autorización determina qué privilegios tienen los distintos clientes.
// Control de acceso basado en roles
function authorize(user, resource, action) {
const role = user.role;
const permissions = roles[role];
const isAllowed = permissions.some(p =>
p.resource === resource && p.actions.includes(action)
);
return isAllowed;
}
La protección de datos es fundamental para la seguridad del lado cliente. Las aplicaciones web modernas son complejas y manejan mucha información sensible. Es importante proteger los datos para evitar fugas, cumplir con las normativas y mitigar los riesgos de seguridad.
La comunicación segura es crucial para proteger la integridad, confidencialidad y autenticidad de los datos transmitidos entre los clientes y servidores.
La seguridad del lado cliente es esencial para proteger los datos de los usuarios y defenderse de ciberataques. Aquí tienes un resumen de lo que cubrimos:
La validación de entradas protege tu sitio de inyecciones de SQL y otras entradas maliciosas. La autenticación y autorización de usuarios son medidas que garantizan el acceso correcto a recursos. Por último, la protección de datos y la comunicación segura son cruciales para asegurar los datos en el lado cliente y
durante la transmisión entre el cliente y el servidor.
Jorge García
Fullstack developer