BigRedes

Guía introductoria a la Seguridad para el Desarrollo de Aplicaciones WEB

El Comité Asesor para el Desarrollo e Implementación de Aplicaciones Seguras, creado por la Dirección Nacional de Ciberseguridad de la Secretaría de Innovación Pública, elaboró una guía de buenas prácticas para el desarrollo de aplicaciones web a través de la Disposición 8/2021. La misma será utilizada en los organismos del Sector Público Nacional para mejorar la protección de datos.

Contenido

Presentación de la Guía

La programación segura es la práctica de escribir código agotando todos los esfuerzos para que no sea vulnerable. En la actualidad, muchos de los ataques aprovechan las vulnerabilidades presentes en el software. Por eso debe prestarse especial atención al desarrollo seguro de aplicaciones, especialmente aquellas que corren sobre la web y sobre las cuales descansan muchos de los servicios y trámites que los ciudadanos realizan con organismos públicos.

Por lo tanto, es importante incorporar los principios y buenas prácticas de seguridad en todas las etapas del ciclo de vida del desarrollo del software, incluyendo en las etapas iniciales. Esto alcanza también a los nuevos enfoques del desarrollo de aplicaciones, como DevSecOps.

Implementar un esquema de seguridad durante todo el ciclo de vida del desarrollo de software redundará en una menor demanda de recursos, ya que cualquier modificación o cambio debido a vulnerabilidades o fallas de seguridad en etapas posteriores, implicará necesariamente una reingeniería del desarrollo y por tanto más tiempo y mayores costos. En consiguiente, se deben identificar las buenas prácticas y los controles de seguridad en cada una de las etapas e incorporarlas oportunamente.

Atendiendo esta problemática, esta guía fue elaborada con el objetivo de contribuir al desarrollo seguro de aplicaciones en organismos que conforman el Sector Público Nacional. Su texto se basa en un documento redactado por personal técnico1 perteneciente a lo que es actualmente la DIRECCIÓN NACIONAL DE CIBERSEGURIDAD de la SUBSECRETARÍA DE TECNOLOGÍAS DE LA INFORMACIÓN de la SECRETARÍA DE INNOVACIÓN PÚBLICA DE LA JEFATURA DE GABINETE DE MINISTROS, parte del cual continúa desempeñándose en el área. Se encuentra también publicado en la plataforma GITHUB2.

Su texto fue enriquecido por los comentarios y opiniones de especialistas en la materia, a quienes se agradece su contribución.

Adicionalmente, como Anexos 1 y 2 se agrega un mayor detalle de OWASP TOP 10 y BSIMM para quienes quieran profundizar sus conocimientos del tema.

Argentina.gob.ar


1.     Introducción

El software de calidad responde a un proceso de desarrollo seguro. Integrar actividades de seguridad al ciclo de vida de desarrollo de software, si bien puede incidir inicialmente sobre los plazos y el presupuesto de un proyecto, contribuye a una operación con menor porcentaje de fallas y especialmente, a una menor exposición a actividad maliciosa de la información que procesa la aplicación. Tarde o temprano, no hacerlo demandará mayores recursos y tendrá un mayor impacto negativo en los usuarios y en el organismo.

Las aplicaciones seguras asisten en la protección de la propiedad intelectual y la reputación de una organización, ayudan a sostener el funcionamiento de sus procesos y al cumplimiento de la Ley 25.326 de Protección de Datos Personales.

Este documento está dirigido a quienes llevan adelante funciones de desarrollo de software, así como a responsables de áreas de Sistemas, Tecnología y Seguridad de la Información del Sector Público Nacional. Busca difundir buenas prácticas de aplicación a todo el Ciclo de Desarrollo de Software.

2.     Modelo Simplificado de Ciclo de Desarrollo

Existen varios modelos de ciclo de vida de desarrollo seguro, cada uno con su enfoque particular (regulatorio, aplicaciones Web, desarrollo para Windows, etc). Se puede seguir alguno de estos modelos, si correspondiere, o se puede tomar el modelo simplificado que sugerimos a continuación. En la sección 3 se ofrece una comparativa de los distintos modelos.

2.1   Inicio del Proyecto

Se identifica la oportunidad de mejorar un proceso y nace la idea de implementar una solución tecnológica basada en un desarrollo interno o tercerizado. Los responsables de seguridad de la información deben intervenir desde el inicio del proyecto, considerando los riesgos involucrados y el posible impacto sobre la información que gestiona el organismo y sobre los procesos involucrados.

Algunas de las actividades de Seguridad a desarrollar en esta etapa son la asignación de recursos, el análisis del contexto, la definición de responsabilidades y la revisión de Marco Normativo aplicable.

2.2   Análisis de Requerimientos.

Se definen las funcionalidades a cubrir con la aplicación sobre la base de los procesos y reglas del organismo y se establecen prioridades.

Es la etapa en la que más se influye sobre el resultado final del proyecto, siendo también indispensable la participación de los responsables de seguridad y privacidad para definir requerimientos específicos. En esta etapa se deben tener en cuenta los requerimientos de cumplimiento establecidos en el marco normativo.

Algunas de las actividades de Seguridad incluyen el análisis de riesgos y establecimiento de los requerimientos de seguridad.

2.3   Diseño del Sistema.

Se determinan los elementos que establecen cómo cumplirá el sistema los requerimientos identificados durante el análisis de requerimientos.

Se podrían incorporar vulnerabilidades al sistema al tomar decisiones incorrectas sobre la arquitectura de diseño del sistema. Las actividades de seguridad durante la etapa de diseño minimizan la necesidad de modificar código en etapas posteriores.

Algunas de las actividades de Seguridad incluyen la definición de los principios de Diseño Seguro, las revisiones de Diseño, y el modelado de Amenazas.

2.4   Etapa de Implementación.

Se escribe el código y se integran componentes construidos previamente en función del diseño establecido. Integrar las actividades de seguridad a esta etapa minimiza la cantidad de errores o fallos a repararse en etapas posteriores.

Algunas de las actividades de Seguridad incluyen Técnicas de programación defensiva, Análisis estático, Revisiones del código.

2.5   Etapa de Pruebas.

Comparando el resultado de la implementación con los requerimientos preestablecidos, pueden detectarse errores o fallas de diseño o codificación, por lo que deben realizarse correcciones y ajustes. Nunca se deben relegar las consideraciones de seguridad para su atención en esta etapa. Las pruebas deben servir como punto de verificación y control adicional para aquellas cuestiones vinculadas a la protección de los datos.

Algunas de las actividades de Seguridad incluyen Pruebas de caja negra y caja blanca y auditorías de código a cargo de terceros.

2.6   Despliegue.

Se prepara la infraestructura sobre la que se ejecutará la aplicación, se instala y configura el software. Una correcta preparación de todo el conjunto de tecnologías puede prevenir vulnerabilidades graves.

Algunas de las actividades de Seguridad incluyen: hardenizado de Sistemas Operativos, así como correcta instalación y configuración de Servicios.

2.7   Mantenimiento.

Se realiza un monitoreo de registros de seguridad y comportamiento de usuarios. Se reciben reportes de incidentes y fallos. Se corrigen errores e implementan actualizaciones.

Algunas de las actividades de Seguridad incluyen Monitoreo de Registros,  Respuesta a Incidentes, Desarrollo y Aplicación de Parches.

3.     Comparativa: Actividades en Modelos de SDLC Seguro.

Comparativa de conjuntos de actividades de seguridad para las etapas del SDLC sugeridas en documentos de distintas organizaciones.

  Etapa/ModeloOWASP(ISC)2 CSSLPMicrosoft SDLNIST SP800-64Sugerido
 Definir alcance ProyectoPolíticas de Privacidad.Entrenamiento de seg.Iniciar Plan deEvaluar impacto sobre
 Definir responsablesRegulaciones,Fundamental.Seguridadla organización y la
 Comunicar a losPrivacidad y Categorizarprivacidad de datos.
 participantes de la iniciativaCumplimiento. Información 
  Inicio del Proyectode seguridad.  Evaluar Impacto a la organización. 
    Evaluar Impacto 
    Privacidad. 
    Asegurar uso SDLC 
    Seguro. 
 Evaluar prácticas vigentes.Fuentes deRequerimientos deEvaluar riesgos alRequerimientos de
 DeterminarRequerimientos dePrivacidad y Seguridad.sistema.seguridad.
 Madurez (SAMM)Seguridad.Calidad y nivel de fallaElegir y documentarAnálisis de riesgos.
RequerimientosDefinir objetivos e impacto. Revisión Requerimientos de Seguridad Riesgo usuarios y arquitecturaCasos de abuso. Matriz RTM.aceptables. Análisis de Riesgos Privacidad/Seguridadcontroles de seguridad. 
 Revisión Diseño Seguro.Evaluación de SuperficieRequerimientos DiseñoDiseñar arquitecturaPrincipios del diseño
 Revisión seguridad externa.de Ataque.Reducción de la superficie de ataqueSeguridadSeguro.
DiseñoAnálisis Riesgos Diseño.Modelados de Amenaza.  Modelado de AmenazasIngeniería Seguridad y ControlesModelado de Amenazas.
    Documentación de 
    Seguridad 
 Análisis estático de códigoVulnerabilidadesHerramientasIntegrar seguridad aPrácticas desarrollo
 Entrenamiento a Desarrollocomunes.Aprobadas.ambientesseguro.
 Estándares de CódigoProgramaciónDeprecar Funcionesestablecidos.Análisis estático de
Implementación Defensiva.Inseguras código.
  Procesos seguros.Análisis Estático. Revisión código entre
     pares.
    PruebasMétricas de Seguridad Revisión de Pruebas. Pruebas de PenetraciónPruebas QA Pruebas de Seguridad Gestión ResultadoAnálisis Dinámico. Fuzz Testing. Revisión Superficie de Ataque.Evaluar seguridad del sistema Autorizar sistema de información.Análisis dinámico de código. Prueba de penetración.
 Gestión Riesgos Pre-DeployHardenizadoPlan RespuestaVer PreparaciónHardenizado de
 Gestión de Infraestructura.Configuración.Incidentesoperativa.sistema operativo y
  DesplieguePruebas de Penetración.Publicación Vers.Revisión Final de Seguridad Certificación de VersiónGestión de configuración.servicios.
   y archivado  
 Gestión de respuesta a incidentes. Parches de seguridad.Monitoreo. Respuesta a incidentes.Ejecutar plan de respuesta a incidentes.Monitoreo continuoRespuesta a incidentes.
MantenimientoRevisiones de permisos.Backups y Recuperación  Monitoreo de Seguridad Aplicación de
     parches.

4.     Consideraciones al Iniciar un Proyecto

Incorporar un enfoque de seguridad desde el inicio del proyecto reduce los esfuerzos de desarrollo y la cantidad de vulnerabilidades antes de llegar a poner la aplicación operativa o en producción. También ayuda a acortar los plazos para la puesta en producción y aumentar los niveles de seguridad de la aplicación.

4.1   Van a Atacar la aplicación

Se debe operar bajo la premisa de que la aplicación va a recibir ataques variados periódicamente. Dependiendo de su criticidad y de los datos a los que da tratamiento, puede aumentar la intensidad y sofisticación de los ataques.

4.2   Algún ataque va a funcionar

Se debe partir de la premisa de que algunos ataques van a funcionar, ya sea por errores de diseño o fallos en la implementación o por vulnerabilidades en la infraestructura en la que se ejecuta la aplicación.

Siempre debe considerarse la posibilidad real de que un atacante evada los controles de seguridad establecidos. En este contexto, se deben aplicar principios de desarrollo seguro para minimizar el impacto de los ataques exitosos. La postura debe ser que cuando un atacante obtenga acceso al sistema, se debe minimizar el impacto contra la organización y los datos que son objeto de procesamiento electrónico.

4.3   Privacidad de los Usuarios

La información personal de sus usuarios, una vez filtrada no volverá a ser privada. Además, una filtración de datos puede afectar los procesos y la reputación de la organización. Una vez tomada la decisión de procesar y almacenar datos personales debe asumirse la responsabilidad de proteger su confidencialidad e integridad mediante controles de seguridad y técnicas de desarrollo seguro.

4.4   Considerar la seguridad en cada decisión

Cada cambio sobre la aplicación implica nuevos riesgos. Al tomar decisiones sobre la arquitectura del sistema, debe hacerse un análisis de los riesgos implicados. Los riesgos generados con los cambios pueden ser difíciles de detectar. Las decisiones importantes requieren la intervención de los miembros más experimentados del equipo y de los responsables de seguridad.

4.5   Intervención del Personal de seguridad

La participación del equipo de seguridad puede ofrecer una visión especializada sobre los riesgos del desarrollo y ayudar a prevenir fallas, haciendo seguro el diseño de la aplicación. La ventaja de incorporar la visión de seguridad antes de la implementación es que se ahorra el esfuerzo en recursos y tiempo de modificar código para corregir vulnerabilidades.

Los responsables de seguridad deben brindar entrenamiento sobre las buenas prácticas de desarrollo seguro al resto de los miembros del equipo. Todas las partes con algún tipo de responsabilidad en el

proyecto  de desarrollo  pueden beneficiarse recibiendo  entrenamiento los riesgos inherentes a producir nuevas aplicaciones.

5.     Durante el Análisis de Requerimientos

A continuación, se listan actividades de seguridad que se pueden integrar a una etapa de análisis de requerimientos.

5.1   Clasificación de Activos.

¿Qué se está defendiendo? La actividad de clasificación de activos consiste en identificar los elementos de la aplicación que ameritan defenderse y estimar su valor para la organización. Ejemplos de activos son: información sensible, componentes de software y servicios.

5.2   Casos de Abuso

Algún atacante intentará vulnerar los controles de seguridad establecidos o la política de uso aceptable. Los casos de abuso enumeran situaciones en las que un atacante intenta vulnerar la seguridad de la aplicación. Esta práctica se realiza en paralelo al estudio de casos de uso.

5.3   Requerimientos de Seguridad

¿Qué no debe hacer la aplicación ante un ataque? Los requerimientos de seguridad definen restricciones sobre la funcionalidad de la aplicación, en base a las reglas de la organización, los activos a defenderse y las posibles amenazas. Se recomienda formular los requerimientos de seguridad en forma explícita, precisa, completa y no conflictiva y usando afirmaciones positivas para validar su cumplimiento.

5.4   Requerimientos de Privacidad

Algunos requerimientos de seguridad refieren específicamente a la confidencialidad sobre elementos de la aplicación, como código fuente o datos privados. Se debe optar por minimizar los datos privados almacenados en sistemas informáticos y justificar explícitamente su almacenamiento.

5.5   Requerimientos Arbitrarios

Refieren al tipo de requerimientos que pueden disminuir la seguridad de la aplicación. Generalmente son incorporados por intervención de personal no especializado. Si bien las aplicaciones desarrolladas deben adaptarse a los procesos de la organización, los expertos deberán decidir sobre la inclusión de requerimientos y su impacto sobre la aplicación a producirse.

5.6   Análisis de Riesgos.

Consiste en estimar la probabilidad de que ocurran ciertos eventos, y evaluar cuál sería el impacto de los mismos para la organización. Permite administrar la asignación de recursos limitados para protegerse de un abanico ilimitado de amenazas posibles. Ofrece planes de acción racionales ante un futuro incierto.

5.7   Priorización de Requerimientos

Es necesario establecer prioridades relativas entre los requerimientos enumerados, para decidir en qué orden se los incorpora al diseño y cuales son descartados.

6.     Principios para un Diseño Seguro.

Algunas vulnerabilidades pueden incorporarse a la aplicación a partir de decisiones de diseño incorrectas. Aplicar principios de diseño seguro ayuda a prevenir este tipo de fallos.

6.1   Minimizar la Superficie de Ataque.

Cada línea de código es un bug en potencia. Cada bug puede implicar en una vulnerabilidad y ser explotada. Se debe reducir la cantidad de componentes y librerías de las que se dependerá. Esta práctica afecta la cantidad final de errores en el código.

6.2   Diseñar para ser Mantenido

Indefectiblemente, habrá que corregir errores o fallos. Sin embargo, la arquitectura de la aplicación puede perjudicar o ayudar en su mantenimiento. Será más viable corregir vulnerabilidades de seguridad en un sistema con arquitectura simple y mantenimiento sencillo.

Factores como la complejidad de módulos y arquitectura afectan a la seguridad de la aplicación por el efecto que tienen sobre su mantenibilidad. La rapidez con la que se corrigen los errores afecta la “ventana de vulnerabilidad”, siendo ésta el plazo durante el cual se desconoce la existencia de una falla de seguridad en el sistema.

6.3   El eslabón más débil.

Generalmente, los atacantes utilizarán inicialmente las vulnerabilidades más fáciles de explotar. La arquitectura de seguridad de su aplicación será tan resistente como lo sea el componente con la mínima seguridad.

Es una buena práctica identificar los puntos débiles de la seguridad de la aplicación mediante revisiones de diseño y una vez detectados, fortalecerlos ajustando el diseño o implementando controles de seguridad.

6.4   Seguridad por Defecto.

Los usuarios usualmente tienden a no configurar los parámetros de seguridad por lo que este tipo de controles deben ser configurados de la forma más segura posible. Eventualmente se puede ofrecer la posibilidad de deshabilitar algunos de ellos. Como principio general, se recomienda desalentar configuraciones inseguras.

6.5   Mantener la Usabilidad.

El buen software es transparente para el usuario. Es esencial negociar un equilibrio entre controles de seguridad y la usabilidad del sistema. Este principio también se conoce como “Aceptabilidad psicológica”. Deberá evitarse generar experiencias de usuario que puedan confundir a los usuarios y llevarlos a tomar malas decisiones de seguridad.

6.6   Autorización para Todo por Defecto.

Por defecto, debe requerirse autorización para acceder a los recursos de la aplicación. En caso de que se

decidiera publicar ciertos recursos, debe fundamentarse tal decisión en base a reglas de la organización. Adicionalmente, debería hacerse un análisis de los riesgos asociados a la decisión que se adopte.

6.7   Principio de Mínimo Privilegio

Establece que se debe asignar a un componente o usuario solo los permisos necesarios y suficientes para realizar una acción específica. Estos permisos deben asignarse lo más tardíamente posible es decir, lo más cercano en tiempo al momento en que debe ejecutarse la acción y se deben revocar en cuanto no son necesarios.

6.8   Separación de responsabilidades y roles.

Cuando un componente falle, que no afecte el resto del sistema. Este principio consiste en aislar los privilegios de los componentes para evitar que interfieran entre sí en caso de que alguno sea vulnerable.

6.9   Defensa en profundidad.

Consiste en establecer controles de seguridad consecutivos que seguirán en pie independientemente de que falle alguno de ellos. Este principio de diseño aumenta notablemente la resistencia del sistema, ofrece defensa contra ataques que encadenan múltiples técnicas de explotación.

6.10        Los controles en el Cliente no son suficientes.

Sin control sobre el dispositivo en que se ejecuta el código es inviable controlar su comportamiento. Cualquier control implementado en un equipo que le pertenece a terceros puede ser modificado o deshabilitado. Nunca se debe confiar en datos validados en un equipo cliente, un atacante podría manipularlos arbitrariamente.

6.11   Ayudar a los Administradores.

El software no puede defenderse a sí mismo de atacantes. La aplicación debe ofrecer herramientas útiles a los administradores para analizar el comportamiento de los usuarios y detectar casos de abuso. También debe permitir conceder, analizar y revocar permisos de acceso a usuarios.

Debe ofrecerse un registro de eventos de seguridad, preferiblemente con reducción de falsos positivos y ruido. Nunca mostrar información personal de los usuarios a los administradores. Se debe proteger especialmente interfaces de acceso administrativo, y considerar implementar autenticación multifactor.

6.12   Diseño sin secretos.

La buena seguridad no requiere secretos. Se debe diseñar el sistema bajo la premisa de que eventualmente el público conocerá los detalles de su funcionamiento interno. Seguridad mediante oscuridad es el error de confiar en secretos como controles válidos. Existen técnicas de testeo a ciegas e ingeniería inversa para obtener información sobre el funcionamiento de sistemas teóricamente secretos. No se debe confiar en el secreto de los mecanismos como medida válida de seguridad.

6.13   Modelado de amenazas.

Ofrece herramientas para estudiar y mejorar los diseños propuestos para la aplicación. Ayuda a identificar puntos débiles y fortalece la seguridad total del sistema. Ayuda a prevenir vulnerabilidades a nivel arquitectura de diseño.

  • Se estudia el diseño tentativo del sistema, reduciéndolo a sus componentes principales.
  • Se grafican la estructura y las relaciones de confianza que existen entre los componentes.
  • Se producen diagramas de flujos de datos.
  • Se definen posibles amenazas para las relaciones entre componentes.
  • Se clasifican las amenazas utilizando criterios STRIDE, DREAD, OCTAVE, etc., en todos los casos priorizando por criticidad.

El modelado de amenazas es una práctica que ofrece un excelente valor agregado sobre el diseño de la aplicación. Puede ayudar a prevenir múltiples tipos de vulnerabilidades graves, producto de relaciones entre componentes. Ayuda a incorporar el principio de defensa en profundidad al diseño de seguridad.

7.     Seguridad en procesos de implementación

Las siguientes consideraciones están orientadas a incrementar la seguridad en el proceso de implementación.

7.1   Seguridad de Herramientas

Se deberá consultar la documentación de buenas prácticas de seguridad específicas para los lenguajes de programación, frameworks y librerías a utilizarse.

Considerar las recomendaciones para la herramienta publicadas por el fabricante y otras autoridades afines sobre: Configuraciones de seguridad y reporte de errores, Módulos de seguridad específicos, Patrones de implementación seguros y Existencia de vulnerabilidades conocidas.

7.2   Mantenibilidad y Seguridad

La facilidad para mantener el código incide sobre el tiempo y precisión de la corrección de vulnerabilidades. Además, minimiza significativamente la cantidad de vulnerabilidades que podrían afectar a sistemas productivos.

Una documentación del diseño de arquitectura y las funcionalidades críticas de la aplicación asiste en el mantenimiento del sistema, especialmente en caso de incorporar nuevos miembros al equipo.

Se recomienda establecer guías de estilo y estructura de código. Y es muy preferible documentarlas o utilizar guías ya publicadas por el fabricante de la herramienta.

7.3   Sistemas de Control de Versiones

Herramientas de control de versiones como Git, Subversion, Mercurial y CVS; ofrecen un excelente valor agregado al equipo en materia de organización de código y auditoría de cambios. Con la desventaja de requerir cierto entrenamiento inicial para utilizarse correctamente.

Ayudan a establecer responsabilidades sobre cambios en el código y a generar un feed-back de mejora de las habilidades de programación individuales y del equipo.

7.4   Seguimiento de errores y fallos

Se recomienda establecer un criterio de rango de errores y fallos, en función de su prioridad y la severidad del defecto que generan. También puede estimarse la complejidad para repararlos para ayudar a decidir prioridades.

Los principales sistemas de control de versiones ofrecen módulos o compatibilidad con herramientas de seguimiento de fallos. Siempre se debe verificar una corrección válida y que no se hayan producido nuevos fallos.

7.5   Prudencia al confiar en terceros.

Cada componente puede fallar. Se debe minimizar la confianza y responsabilidad que se deposita en componentes desarrollados por terceros. Se recomienda especial selectividad al incorporar módulos y librerías, revisar las especificaciones y documentación del fabricante.

7.6   Arquitectura de red

Si bien las cuestiones vinculadas a la seguridad en la implementación y configuración de la infraestructura tecnológica en la que se publicará la aplicación web, se encuentran fuera del alcance del presente documento, se consideró importante dada su relevancia, agregar un apartado al respecto.

El diseño de redes seguras es el proceso de diseñarlas considerando las posibles amenazas a las que se verían expuestas y las contramedidas a adoptar. Se debe considerar la implementación de estas medidas sea escalable y sostenible por lo que requerirá un diseño acorde, considerando los riesgos y los principios de seguridad a aplicar.

Se recomienda estandarizar implementaciones, mantener diseños simples pero seguros, identificar eventos a monitorear, documentar su diseño, arquitectura final y configuraciones. Para su diseño se debe considerar aspectos tales como: aislamiento, separación y compartimentación de la red; políticas de acceso; gestión de las identidades; monitoreo de la red y eventos; correlación de eventos y Resiliencia de la red.

En entornos donde se utilice virtualización por hardware o contenedores, se deberá considerar a su vez, las configuraciones de seguridad de dichas implementaciones.

8.     Programación Segura

Criterios de seguridad para incrementar la seguridad del código producido. Capítulo basado en el documento

OWASP: Secure Coding Cheat Sheet, publicado por Owasp Foundation.

8.1   Validar Todas las Entradas.

Implementar correctamente un módulo de validación de entradas es un desafío complejo. Se recomienda utilizar librerías de validación de código abierto, reconocidas y con mantenimiento activo para el lenguaje elegido.

Debe ejecutarse una validación sobre todas las entradas que lea la aplicación, en un equipo confiable y configurado en forma segura. Nunca debe confiarse en un control ejecutado en un equipo del usuario. Siempre se debe realizar la validación antes de procesar los datos de entrada.

Es preferible realizar la validación utilizando un criterio de “lista blanca”: prohibir todo y permitir deliberadamente casos aceptables. Cuando una validación falla, debe rechazarse los datos de entrada. Es una buena práctica centralizar las rutinas de validación para facilitar su mantenimiento.

entrada_1_sucia = parametro_get()
query_base_datos(entrada_1_sucia)
// NUNCA procesar entradas sin antes validarlas.
entrada_1_sucia = parametro_get()
entrada_1_limpia = validar(entrada_1_sucia)
query_base_datos(entrada_1_limpia)

Esta recomendación resuelve los problemas vinculados a ataques de inyección, XSS (Cross Site Scripting).

8.2   Codificar apropiadamente todas las salidas.

En ocasiones se usan entradas controladas externamente para generar contenido dinámico. Se debe controlar estrictamente el formato y los posibles valores de los resultados de módulos hacia componentes externos.

nombre_usuario_sucio = parametro_get()
generar_html(nombre_usuario_sucio)
// Permite atacar el navegador de los usuarios.
nombre_usuario_sucio = parametro_get()
nombre_usuario_limpio = codificar(nombre_usuario_sucio)
generar_html(nombre_usuario_limpio)

Esta recomendación resuelve los problemas vinculados a ataques XSS: phishing, robo de sesiones, robo de             información privada, distribución de malware.

8.3   Centralizar las Rutinas de Control.

Esta práctica facilita el mantenimiento de los módulos de control. Minimiza las probabilidades de cometer errores en cada instancia del control. Previene la formación de puntos débiles. Facilita la reutilización de código.

entrada_1_sucia = parametro_get()
entrada_2_sucia = parametro_post()
entrada_1_sucia = quitar_puntoycoma(entrada_1_sucia)
entrada_1_sucia = quitar _guiones(entrada_1_sucia)
entrada_1_limpia = quitar _arrobas(entrada_1_sucia)
entrada_2_sucia = quitar _comillas(entrada_2_sucia)
entrada_2_limpia = quitar _puntoycoma(entrada_2_sucia)
// Complica la corrección de controles.
entrada_1_sucia = parametro_get()
entrada_2_sucia = parametro_post()
entrada_1_limpia = validar(entrada_1_sucia, tipo_de_validacion_1)
entrada_2_limpia = validar(entrada_2_sucia, tipo_de_validacion_2)
// Las rutinas centralizadas son más mantenibles.

Esta recomendación resuelve los problemas vinculados a un bajo nivel de mantenimiento del Código.

8.4   Autenticación, contraseñas y sesiones

Se recomienda usar librerías o servicios de autenticación estándares y bien comprobados. Se debería requerir autenticación para todas las páginas y recursos, a menos que justifique que sean públicos. Los controles de autenticación deben ejecutarse en el servidor. Se debería requerir autenticación para operaciones críticas sobre una cuenta de usuario, como modificaciones o acceso a información privada y trámites sensibles.

Se recomienda utilizar librerías o frameworks de gestión de contraseñas estándar y bien comprobadas. Las contraseñas nunca deben transmitirse ni almacenarse en texto plano. Se recomienda deshabilitar la opción de autocomplete para formularios de credenciales en el frontend.

Se recomienda utilizar los controles de gestión de sesión del servicio o frameworks, antes de intentar implementar los propios. Siempre ofrecer una funcionalidad de cierre de sesión y un tiempo de terminación automática.

Esta recomendación resuelve los problemas vinculados al bypass de autenticación, robo de sesiones, robo y destrucción de datos personales.

8.5   Control de Accesos.

Se deben unificar los controles de acceso para todo el sitio. La verificación de controles de acceso debe ejecutarse en el servidor. Además, se debe limitar la cantidad de acciones permitidas por usuario, dentro de una ventana de tiempo. La aplicación solo debe tener permisos de acceso a los archivos que resulten estrictamente necesarios.

Esta recomendación resuelve los problemas vinculados al acceso a datos privados por referencia directa a objetos, manipulación de interfaces  administrativas.

8.6   Excepciones y Errores Seguros.

Es necesario prever errores y excepciones que puedan ocurrir durante la ejecución del código. En caso de producirse una condición de error, no se debe revelar a usuarios información del funcionamiento interno del sistema.

Se deberá deshabilitar mensajes de debugging y stack-traces del lenguaje, librerías, frameworks y servicios en entornos productivos.

Esta recomendación resuelve los problemas vinculados a la revelación de información sobre la arquitectura interna de la aplicación.

8.7   Carga de Archivos

Esta funcionalidad es de alto riesgo, debe limitarse estrictamente los tipos de archivos que se permite cargar al servidor y correr un análisis de malware sobre su contenido. Deben almacenarse en ambientes aislados o al menos particiones de disco separadas.

Esta recomendación resuelve los problemas vinculados a ataques de ejecución de código, carga de malware y defacements, entre otros.

8.8   Existencia de backdoors administrativas

Las backdoors administrativas son relativamente inofensivas en entornos de desarrollo que no contienen bases de datos productivas. Pero pueden comprometer información privada o la disponibilidad del servicio en caso de llegar a sistemas productivos.

Si son detectadas en sistemas productivos, pueden resultar en robo y modificaciones de datos, perjudicando la reputación de la organización. En el peor de los casos, un atacante puede descubrirlas y utilizarlas. Las auditorías y revisiones de código entre pares ayudan a detectarlas. Debe documentarse su existencia y garantizarse su eliminación de entornos productivos.

if( parámetro_get() == “admin1234” )
conceder_privilegios_administrador()
// Pone en peligro la seguridad de sistemas productivos.

Esta recomendación resuelve los problemas vinculados a casos de abuso con privilegios elevados.

8.9   Recomendaciones generales

Se debería estudiar en detalle la documentación de seguridad específica publicada por el fabricante y referentes del lenguaje de programación, librerías, frameworks, servicios y sistema operativo.

Se recomienda utilizar componentes preexistentes ya comprobados en vez de crear código nuevo para tareas comunes. Validar la seguridad de los componentes elegidos mediante revisiones de código y alertas de seguridad publicadas.

Utilizar controles de integridad sobre el código, librerías, ejecutables y archivos de configuración.

9.     Ataques comunes: OWASP Top 10

Conocer los tipos de ataques más prevalentes puede ayudar a prevenirlos y aumentar los niveles de seguridad.

AtaqueDescripciónAmenazaMitigaciones
Ataques de InyecciónLa aplicación envía datos sin validar a un sistema que interpreta instrucciones. Como motores SQL, LDAP, NoSQL, Comandos al Sistema Operativo, XML, XMTP, etc.Robo y corrupción de datos. Ataques de denegación de servicio. Puede resultar en compromiso total del equipo.Utilizar Interfaces parametrizadas. Escapar caracteres peligrosos. Filtrar entradas por “listablanca”.
Autenticación o Control de Sesión IncorrectoComun en módulos de autenticación y sesión desarrollados desde cero. Estos pueden contener múltiples errores de implementación y diseño. (Funciones de Logout, creación de cuentas, cambio contraseñas, olvidó su contraseña, timeouts, recordarme, pregunta secreta).Ataques sobre cuentas de usuario. Las cuentas con privilegios elevados suelen ser atacadas.Utilizar un módulo de autenticación y control de sesión fuerte y sin vulnerabilidades conocidas. Revisar detenidamente el diseño y la implementación de estos controles.
XSS: Cross Site ScriptingOcurre cuando se genera una página incluyendo datos controlados por un atacante que no fueron correctamente filtrados. Los datos pueden ser almacenados en el servidor o reflejados de algún parámetro o Cabeceras HTTP.Ejecución de scripts arbitrarios en el navegador de los usuarios. Posibilitando robo de sesiones, ataques phishing, modificaciones de contenido, descarga malware y “browser hijackers”.Filtrar los datos correctamente, en base al contexto en que serán presentados. Utilizar librerías de sanitización de inputs reconocidas. Medida adicional (pero insuficiente) es la utilización de Content Security Policy.
Mecanismo de Control de Acceso IncorrectoMecanismo de Control de Acceso Incorrecto Las aplicaciones y las APIs muchas veces usan el nombre o código de un objeto para generar páginas. Estos códigos y nombres pueden ser fáciles de adivinar. Las aplicaciones o las APIs no siempre verifican que el usuario esté autorizado para acceder al recurso solicitado.Comprometer la toda la funcionalidad o datos accesibles. Robo de datos y abuso de servicio.Verificar permisos de acceso para cada solicitud. Se puede generar códigos de acceso a recurso individuales para cada sesión de usuario.
Mala Configuración de SeguridadPuede ocurrir en cualquier capa del stack: sistema operativo, plataforma, servicio web, servicio de aplicación, base de datos, frameworks y código personalizado.Acceso no autorizado a algunos datos y funcionalidades del sistema. Puede resultar en compromiso total del sistemaProceso de Hardenizado repetible que garantice cierto aseguramiento del ambiente. Los entornos de Desarrollo, QA y producción deben configurarse en forma idéntica (con contraseñas distintas para cada uno). Proceso de seguimiento e instalación de actualizaciones y parches para TODOS los componentes. Arquitectura de la aplicación segura, segregación de funciones efectiva. Verificación automatizada de config.
AtaqueDescripciónAmenazaMitigaciones
Filtración de Datos SensiblesEl fallo más común es no encriptar los datos sensibles o encriptarlos incorrectamente usando claves débiles, gestión de claves pobre o algoritmos débiles.Compromiso de todos los datos desprotegidos.No almacenar datos sensibles indiscriminadamente. Encriptar todos los datos sensibles almacenados y enviados. Utilizar algoritmos estándar y claves fuertes. Las contraseñas deben almacenarse utilizando algoritmos diseñados específicamente para proteger contraseñas, (bcrypt, PBKDF2, scrypt). Deshabilitar la opción caché y de autocomplete, en páginas y formularios con información sensible
Falta de Protección contra AtaquesLas aplicaciones y APIs son atacadas todo el tiempo, generalmente detectan los inputs inválidos pero solo los rechazan: permitiendo que los atacantes prueben una y otra vez.La mayoría de los ataques comienzan con un sondeo de vulnerabilidades. Permitir este tipo de pruebas incrementa las probabilidades de un ataque exitoso, ayuda a los atacantes.Medidas de detección y respuesta a ataques. Proceso de aplicación de parches críticos (o virtuales).
CSRF: Cross Site Request ForgeryAprovechando el hecho de que los navegadores envían las cookies de sesión automáticamente, un atacante puede generar un link que solicite una acción sobre la aplicación.Los usuarios pueden ser engañados para ejecutar acciones no deseadas en la aplicación, como cambios de información, modificaciones de cuentas o compras.Utilizar tokens únicos para confirmar la validez de una acción. Como medida adicional se puede usar el flag “SameSite=strict” sobre todas las cookies.
Componente con Vulnerabilidades ConocidasOcurren cuando no hay aseguramiento de que se usen componentes y librerías actualizadas. O cuando hay dependencias desconocidas entre componentes.Puede facilitar todo tipo de ataques: de inyección, XSS, controles de acceso rotos, etc. Puede resultar en compromiso total del host y robo de datos.Inventariar continuamente las versiones de los componentes utilizados. Monitorear bases de datos de vulnerabilidades en busca de los componentes utilizados. Analizar componentes instalados y evaluar si son necesarios. Aplicar actualizaciones y parches de seguridad provistos por el fabricante del componente.
API DesprotegidaMuchas aplicaciones modernas se conectan a APIs en el backend, (XML, JSON, RPC o customizadas) que son susceptibles a todo tipo de ataques. Este tipo de vulnerabilidades, generalmente requiere revisiones manuales y suele permanecer sin ser detectado.Todo tipo de ataques: robo, corrupción e incluso modificación de datos. Acceso no autorizado a funciones de la aplicación. Puede resultar en compromiso total del equipo.Asegurar las comunicaciones entre cliente de la aplicación y la API. Esquema de autenticación fuerte. Parser de datos Hardenizado contra ataques. Esquemas de control de accesos. Protección contra ataques de inyección.
Este capítulo se publica bajo la licencia Creative Commons Attribution-ShareAlike 4.0. Autor original: Owasp Foundation

10. Pruebas de Seguridad

Criterios para verificar si el diseño y la implementación de la aplicación cumplen con los requerimientos de seguridad establecidos.

10.1 Comienzo Temprano de la Etapa de Pruebas

Cuanto más temprano se descubran los fallos y errores, más económico será corregirlos, y menor será el impacto sobre la integridad del resto del código. Idealmente, debería comenzarse con las pruebas de seguridad en paralelo a la etapa de desarrollo. A efectos de detectar y corregir tempranamente posibles vulnerabilidades.

10.2 Revisiones de Código entre Pares.

Se realiza en paralelo con las tareas de desarrollo. No se requiere una cobertura total del código. Se recomienda comenzar por los componentes más críticos de la aplicación.

Esta práctica reduce drásticamente la cantidad de errores y fallos que permanecen en el código sin ser detectadas. Aumenta los niveles de comunicación entre miembros del equipo, ayuda a consolidar criterios de buenas prácticas e incrementa las habilidades programáticas individuales.

Es preferible establecer una metodología estándar de corrección y validación de errores para todo el equipo. Se recomienda limitar los bloques de revisión a alrededor de 400 líneas de código y períodos de una hora.

10.3 Herramientas de escaneo estático.

El análisis estático de un IDE, compilador, intérprete o herramienta especializada puede ofrecer una excelente medida para prevenir errores o fallos. Este tipo de herramientas complementa a las revisiones manuales para detectar errores sintácticos o que requieren seguir flujos de ejecución muy largos para ser interpretado por humanos.

Las herramientas tienen la debilidad de ofrecer falsos positivos y falsos negativos. Es posible reconfigurar o ajustar las alertas para prevenir resultados falsos. Esta práctica no sustituye las revisiones manuales de código.

10.4 Pruebas de Penetración

Se evalúa la seguridad del sistema desde la perspectiva de un atacante. Cumple la función de detectar vulnerabilidades que escaparon a todos los otros controles de seguridad anteriores.

Por si sola, este tipo de pruebas no es suficiente para garantizar la seguridad de una aplicación. Corregir fallos detectados mediante pruebas de penetración, suele ser mucho menos económico que prevenirlos en etapas tempranas del ciclo de desarrollo.

10.5 Auditorías Manuales de Código

Algunos fallos son difíciles de detectar con herramientas o pruebas de penetración, pero resultan evidentes al leer el código responsable. Este tipo de pruebas suele llamarse White-box o transparent-box.

10.6 Pruebas Tercerizadas y Confidencialidad

En caso de que las pruebas sean realizadas por personal ajeno a la organización se recomienda documentar las condiciones de las actividades de prueba, definiendo: alcance, objetivos, tipos de pruebas y horarios permitidos.

11. Puesta en producción

Partiendo de una correcta verificación durante la etapa de pruebas, se presentan a continuación buenas prácticas para el despliegue de la aplicación.

11.1 Segregación de ambientes

Se deberá tomar medidas para garantizar una estricta segregación entre los ambientes de desarrollo, pruebas y producción. No se debe conceder acceso irrestricto a entornos productivos. No debe utilizarse datos productivos en entornos de desarrollo y pruebas, se recomienda generar datos ficticios o aleatorios con estructura equivalente a la productiva. Se debe formalizar una serie de controles previo a la puesta en producción de nuevas versiones de la aplicación. Al producirse la migración de código hacia entornos productivos, prestar especial cuidado a la eliminación de todas las “backdoors” administrativas.

11.2 Hardenizado de equipos

Se deben eliminar componentes innecesarios, configurar correctamente los necesarios, activar componentes de seguridad y documentar las configuraciones establecidas para cada componente.

Siempre se debe cambiar las contraseñas preestablecidas por defecto, cumpliendo con la política de contraseñas de la organización.

Deberá prestarse especial atención a una correcta configuración del sistema operativo y los servicios utilizados por la aplicación siguiendo las buenas prácticas de seguridad recomendadas por cada fabricante y comunidad de usuarios expertos.

Se debe separar equipos de servicios web y bases de datos, ubicando el servicio web en la DMZ y el servicio de base de datos en un entorno privado. Se recomienda cifrar las comunicaciones entre ambos servicios.

Las herramientas de virtualización y contenedores ofrecen una capa extra de seguridad generalmente deseable. Sin embargo, requieren mantenimiento adicional y pueden impactar sobre el rendimiento del sistema.

Se recomienda un esquema de particiones que separe el sistema operativo, servicios, los registros de auditoría y archivos cargados por usuarios.

Las cuentas de servicio y administrativas deberán contar con los mínimos privilegios necesarios para realizar las acciones previstas.

Prestar especial consideración a una correcta configuración del servicio de cifrado para datos en tránsito y el cifrado de las unidades de almacenamiento protegiendo: código fuente, bases de datos y datos personales.

Debería correrse pruebas y revisiones de la configuración para todos los componentes. Es preferible lograr una configuración base segura que pueda adaptarse para cada caso de uso.

Se recomienda el uso de herramientas de seguridad específicas para cada capa, que deben seleccionarse cuidadosamente. Red: balanceadores de carga, firewalls, sistemas de detección y prevención de intrusos. Sistema operativo: firewall de host, controles de integridad de archivos, cifrado, scripts de hardenizado, antimalware. Servicios: firewall de aplicaciones, módulos de seguridad, scripts de hardenizado. Aplicación: Correcta       configuración,      componentes      de      seguridad,       generación      registros      de      auditoría.

12. Mantenimiento

Recomendaciones para mantener los niveles de seguridad durante el funcionamiento productivo de la aplicación.

12.1 Protocolo de Backups

Debe implementarse un protocolo de back-up periódico formalizado, con procedimientos para restaurar servicio en caso de fallos, a efectos de garantizar integridad y disponibilidad. Se recomienda definir tipo de backup, periodicidad, pruebas, usuarios y responsables.

12.2 Monitoreos periódicos de seguridad y alertas

Se deberá ofrecer a los administradores herramientas de administración de cuentas, alertas de seguridad, monitoreo de abuso y registros de auditoría.

12.3 Reporte de incidentes y vulnerabilidades

Se recomienda ofrecer un canal de contacto para el reporte de fallos, errores y vulnerabilidades. Se deberá implementar una Base de Conocimientos para facilitar el seguimiento de cada caso.

Será necesario suscribirse a las notificaciones de seguridad del fabricante de cada componente utilizado en la aplicación. En caso de recibir información de terceros sobre vulnerabilidades que afecten a nuestra aplicación, se recomienda recabar la información necesaria para solucionar lo reportado.

12.4 Ventana de vulnerabilidad

Es el plazo de tiempo desde que se toma conocimiento de la existencia de una vulnerabilidad hasta que se produce una nueva versión o parche correctivo. Se debe minimizarla para reducir el riesgo de ataques. Se recomienda establecer procesos especiales para casos que requieran corrección urgente. Algunos dispositivos permiten mitigar temporalmente las vulnerabilidades mediante la aplicación de “parches virtuales”.

12.5 Actualizaciones de seguridad

Se deberá verificar que las actualizaciones reparen efectivamente la vulnerabilidad o fallo. También deberá probarse que los cambios no generan nuevas vulnerabilidades. En caso de que las actualizaciones se instalen manualmente deberá corroborarse que no queden instancias con versiones vulnerables. Es una buena práctica publicar reportes describiendo información técnica y la criticidad de la actualización. Dependiendo del tipo de aplicación, puede ser necesario notificar a los usuarios de los cambios aplicados.

12.6 Descarte de la aplicación

Al llegar al final de la vida útil de un sistema, por obsolescencia o reemplazo, debe considerarse especialmente la privacidad de los datos almacenados. En caso de migración, deben tomarse medidas para evitar que se comprometa la integridad y establecerse mecanismos de custodia para garantizar la confidencialidad.

Si se necesita destruir los datos de la aplicación original, debe validarse la eliminación mediante sobreescritura y adicionalmente destrucción física de los medios de almacenamiento que fueron utilizados.

Al momento de una migración, deben validarse y sanitizarse todos los datos importados.

BigRedes