Tabla de contenidos
Las buenas prácticas para un desarrollo seguro evitan vulnerabilidades y previenen ataques. En este post hacemos un repaso a las buenas prácticas de codificación segura establecidas por OWASP (Open Web Application Security Project), una entidad internacional sin ánimo de lucro que trabaja para mejorar la seguridad del software.
Los puntos débiles de cualquier aplicación en términos de seguridad tienen que ver con la forma en que se ha escrito su código. Así que, durante todo el proceso de desarrollo, desde que se comienza el proyecto hasta que se entrega la app al cliente, los programadores deben seguir determinadas pautas para garantizar la máxima seguridad del código.
Cuando los desarrolladores empiezan a construir una nueva aplicación, deben tener en cuenta los requisitos del cliente y deben hacer un código eficiente y seguro. En este artículo del blog explicamos por qué la seguridad del código debe ser una prioridad absoluta y analizamos las buenas prácticas de seguridad
¿Qué es un desarrollo seguro?
El desarrollo seguro es la práctica de escribir código, en cualquier lenguaje de programación, para prevenir problemas de seguridad en la app o sitio web. El objetivo es minimizar vulnerabilidades.
Cualquier tarea de programación se puede llevar a cabo de diferentes maneras, con distintos niveles de complejidad. Algunas soluciones son más seguras que otras. Los estándares o buenas prácticas de código seguro guían a los desarrolladores para que elijan el camino más seguro, aunque no sea el camino más rápido o eficiente.
Un ejemplo sencillo de entender es la recomendada denegación por defecto a la hora de permitir accesos. Los desarrolladores que utilizan técnicas de desarrollo seguro crean código que impide el acceso a recursos sensibles, a menos que el usuario pueda demostrar que tiene autorización. El trabajo extra de dar privilegios a los usuarios de forma personalizada —por ejemplo, según si eres usuario registrado o no, o según el estatus dentro de la organización— es necesario. Solo así garantizamos que la persona que accede a un dato tiene permiso para hacerlo en razón de su responsabilidad en la empresa.
Según OWASP, el objetivo del desarrollo seguro es «mantener la confidencialidad, integridad y disponibilidad de los recursos de información con el fin de facilitar el éxito de las operaciones de las empresas»
¿Por qué son importantes las buenas prácticas para un código seguro?
Los incidentes de seguridad pueden tener graves consecuencias para negocios y personas. Un código creado sin seguir buenas prácticas de seguridad puede provocar daños económicos y robos de identidad, entre otros perjuicios. En sectores específicos, como finanzas, salud, energía y transporte, los efectos negativos pueden ser mayores.
En los últimos años hemos visto que incluso grandes organizaciones sufren graves filtraciones de datos, a pesar de haber podido dedicar recursos para minimizar las vulnerabilidades.
Las compañías que se relacionan con sus clientes a través de webs y aplicaciones móviles pueden perder la confianza de estos por problemas de seguridad. Una de las peores cosas que pueden pasar es poner en peligro a los clientes. Por este motivo, consolidar buenas prácticas de desarrollo es una prioridad.
Desde un punto de vista tecnológico, el daño que se causa a una web o app puede afectar a otros sistemas, como por ejemplo la base de datos del backend o el sistema del usuario.
Seguridad desde el inicio del desarrollo
Las buenas prácticas de seguridad se deben seguir durante todo el proceso de creación de código, desde las primeras líneas de código hasta la finalización del proyecto. Además, hay que utilizar herramientas automatizadas para ir evaluando la calidad del código y detectar fallos tan pronto se produzcan. Lo que nunca podemos hacer es ponernos a pensar en los aspectos de seguridad a mitad del proyecto de desarrollo.
Dar prioridad a un código seguro sale siempre a cuenta. Es cierto que el desarrollo puede perder velocidad y ganar complejidad. Sin embargo, no hay mayor tranquilidad que saber que la aplicación difícilmente va a sufrir problemas de seguridad en el futuro que puedan tener un impacto negativo en el negocio. ¿Qué costes podría tener que asumir la empresa si un ciberataque explotase una vulnerabilidad con éxito y hubiese una filtración de información sensible de usuarios?
Poner en práctica unas normas de desarrollo seguro desde las primeras etapas del ciclo de desarrollo es más fácil y más económico que corregir problemas detectados a través del testing en fases más avanzadas o cuando la aplicación ya está en producción, es decir, cuando es utilizada por usuarios reales.
Además de seguir buenas prácticas de desarrollo seguro, hay que mantener el diseño tan simple y mínimo como sea posible. Un diseño muy complejo es una desventaja, ya que aumenta la probabilidad de errores de todo tipo, también de seguridad.
Buenas prácticas para la seguridad del código según OWASP
Cuando se trata de hacer desarrollos, no se puede reinventar la rueda. Así, los expertos han alcanzado consensos sobre qué prácticas garantizan un desarrollo seguro.
Una de las guías más seguidas es OWASP Secure Coding Practices. Se trata de un documento muy práctico, con buenas prácticas descritas a modo de checklist en un total de 14 áreas con impacto en el ciclo de desarrollo.
Los 14 ámbitos de seguridad analizados por OWASP son:
- Validación de entradas
- Codificación de salidas
- Gestión de autenticación y contraseñas
- Administración de sesiones
- Control de acceso
- Prácticas criptográficas
- Gestión de errores y logs
- Protección de datos
- Seguridad en las comunicaciones
- Configuración del sistema
- Seguridad de base de datos
- Gestión de archivos
- Gestión de memoria
- Prácticas generales para el desarrollo de código
Validación de entradas y codificación de salidas
Una buena práctica destacada en este ámbito es la necesidad de identificar todas las fuentes de datos, y de clasificarlas según si son de confianza o no son de confianza. Todos los datos que vengan de fuentes que no son de confianza (bases de datos, secuencias de archivo, etc), habría que validarlos. Cualquier error en la validación debe llevar al rechazo del dato de entrada.
Una adecuada validación de inputs puede eliminar una gran mayoría de vulnerabilidades de software. Cuatro de las 10 principales vulnerabilidades, según la lista de OWASP, vienen de confiar de forma errónea en datos que entran en el sistema.
En relación a la codificación de salidas, entre otras buenas prácticas hay que utilizar rutinas estándar testadas para cada tipo.
Gestión de autenticación y contraseñas
Las contraseñas son un punto débil en muchos sistemas, razón que explica la generalización de la autenticación multifactor. Ahora bien, las contraseñas son necesarias. De hecho, hoy son la acreditación más común para garantizar la seguridad.
Como regla general, hay que pedir autenticación para todos los recursos y páginas, excepto para aquellas que se han clasificado como públicas.
OWASP propone muchas buenas prácticas para reducir los riesgos. Entre estos consejos, podemos destacar los siguientes:
- Almacenar en la aplicación solo los hashes criptográficos con sal (del inglés salted) de las contraseñas, y no las contraseñas tal cual (en texto claro). La otra recomendación importante es que la tabla/fichero que guarda contraseñas y claves solo puede ser escrita por la aplicación. En la protección a través de contraseña, salt es una cadena de datos aleatoria que se utiliza para modificar un hash de contraseña. Servicios online de todo tipo que usamos cada día no almacenan la contraseña que el usuario ha introducido, sino un valor hash para esa contraseña.
- Obligar al usuario a poner contraseñas lo suficientemente largas y complejas para resistir los ataques más comunes.
- Deshabilitar la entrada de la contraseña después de varios intentos de inicio de sesión incorrectos.
- Reautenticar el usuario justo antes de la realización de operaciones críticas.
Las contraseñas son omnipresentes, pero podrían acabar siendo obsoletas con la tecnología passkey, un login sin password que ofrece más seguridad y más comodidad al usuario.
Con los passkeys, la autenticación requiere una autenticación biométrica —como una huella dactilar— o un PIN o un patrón para dispositivos Android.
Administración de sesiones
La duración de las sesiones debe ser lo más breve posible, buscando un equilibro entre las necesidades de seguridad del sistema y las necesidades del usuario/cliente.
Habría que utilizar tokens para reforzar la gestión de sesiones para operaciones delicadas del lado del servidor, como por ejemplo la gestión de cuentas de usuario. Los tokens previenen los ataques de Cross Site Request Forgery.
Control de acceso
Las decisiones de acceso deben basarse en permisos, y no en exclusiones. En otras palabras, la idea es que el acceso se deniegue por defecto, y que el sistema identifique las condiciones bajo las cuales se permite un acceso. Por tanto, a los usuarios que no pueden demostrar autorización, se les debe denegar el acceso.
El principio del menor privilegio que propugna OWASP dice que un usuario no debe tener más permisos de los que le hacen falta
Prácticas criptográficas
En caso de filtración de datos, es fundamental la encriptación de datos con algoritmos criptográficos y seguir buenas prácticas de gestión segura de claves.
Hay muchas librerías disponibles para ayudar a implementar la encriptación. Ahora bien, es importante usar solo algoritmos y librerías estándar.
Gestión de errores y logs
Los errores de código pueden apuntar muchas veces a vulnerabilidades, así que la gestión y el registro de errores (logs) son dos técnicas muy útiles.
- La gestión de errores intenta detectar errores en el código antes de que haya un fallo catastrófico.
- El logging o registro de logs permite documentar los errores, para que así los desarrolladores puedan diagnosticar la causa y solucionar el problema.
Incluso los mejores desarrollos pueden tener errores. Lo que de verdad marca la diferencia es que, cuando haya un error, sea identificado y se trate lo antes posible para mitigar su impacto.
Protección de datos
Muchos ciberataques buscan acceder a datos sensibles. De ahí que sean cruciales las buenas prácticas de codificación en protección de datos. Por ejemplo:
- Implementar el mínimo privilegio. Es decir, restringir el acceso de los usuarios solo a la funcionalidad, datos y sistemas de información que necesitan para hacer sus tareas.
- Proteger el caché con datos sensibles y eliminarlo tan pronto deje de hacer falta.
- Como ya hemos dicho, no almacenar contraseñas u otra información sensible en texto claro o sin encriptación criptográfica.
Seguridad en las comunicaciones
Una de las buenas prácticas destacadas es implementar la encriptación para todas las transmisiones de información sensible. Esto debería incluir TLS para proteger la conexión. Además, se puede recurrir a una encriptación discreta de archivos sensibles o conexiones no basadas en HTTP.
Configuración del sistema
La guía de OWASP para un desarrollo seguro también describe buenas prácticas para la seguridad de los sistemas con los que se escribe el código. La idea principal es tenerlo todo actualizado y trabajar solo con las funcionalidades y archivos estrictamente necesarios. Otro consejo obvio, pero que no está de más recordar, es llevar un sistema de control de cambios y versiones.
Seguridad de base de datos
Una recomendación de seguridad destacada es el empleo de consultas parametrizadas, para evitar inyecciones SQL. Los datos de entrada en el sistema son interpretados como parámetros y no contienen código ejecutable.
Gestión de archivos y de memoria
Una gestión de archivos segura exige autenticación antes de transferir los archivos al servidor. También hay que hacer una validación de los tipos de archivo, a partir de los file headers (datos contenidos en el archivo con información que lo identifica), no a partir de las extensiones.
La gestión de memoria segura requiere controles en la entrada y salida de información que no es de confianza. Otras buenas prácticas se refieren, por ejemplo, al tamaño de los buffers.
Prácticas generales para el desarrollo de código
La guía para el desarrollo seguro de OWASP concluye con una larga lista de prácticas de tipo general, como por ejemplo usar código testado y verificado en vez de crear nuevo código para las tareas habituales.
Omatech crea proyectos digitales de código seguro
Buenas prácticas para un desarrollo seguro: un proceso continuo
Un vez el código ya está listo, se le debe hacer un mantenimiento que permite mantener el listón de la seguridad tan alto como sea posible.
- Mínimo privilegio. Hay que seguir fieles al principio según el cual los usuarios necesitan los permisos estrictamente necesarios.
- Defensa en profundidad. El riesgo se debe gestionar con múltiples estrategias de defensa. De esta manera, si una capa de protección no funciona, otra capa sí que puede evitar que una falla de seguridad sea una vulnerabilidad que alguien con malas ideas pueda aprovechar. Además, también se trata de limitar las consecuencias negativas de un exploit con éxito.
- Técnicas para asegurar la calidad. Gracias al test PEN o test de penetración, las auditorías de código o el scanning de aplicaciones, podemos identificar y eliminar vulnerabilidades. Hay que hacer scanning de aplicaciones cada vez que grandes cambios o revisiones vayan a producción.