Software y Seguridad
El software es un conjunto de instrucciones de ordenador que tiene como objetivo auxiliar un proceso cualquiera humano. En la mayoría de las veces auxilia un proceso que ya existe manualmente. Eso quiere decir que no existe un software separado del mundo, es parte de un proceso.
El software no existe en el vacío. Es una herramienta al servicio de un proceso, ejecutado por personas.
- Existe un conjunto de actividades antes de que el software sea usado.
- Otro durante el uso del software.
- Y un proceso al final del uso del software.
Un software de nómina, por ejemplo, no crea el proceso de pagar a empleados. Automatiza y auxilia un proceso que ya existía (cálculos manuales, emisión de cheques, etc.). Las actividades de recoger las horas trabajadas (antes), operar el software (durante) y distribuir las nóminas y hacer los pagos (después) continúan existiendo. El software es solo la pieza central que optimiza el "durante".
No existe seguridad de software desacoplado de los procesos a su alrededor. Es un error pensar que la seguridad se resume solamente al software.
Este es el pilar de la seguridad de la información moderna. Un software puede ser técnicamente perfecto, sin ninguna vulnerabilidad, pero aún así ser comprometido por fallos en los procesos a su alrededor.
Vamos a ejemplificar esto.
- Un sistema bancario puede tener la criptografía más fuerte del mundo, pero si el proceso permite que un empleado anote la contraseña del cliente en un post-it, la seguridad fue rota por el proceso, no por el software.
- Un servidor en la nube puede ser extremadamente seguro, pero si el proceso de configuración es mal ejecutado y un administrador deja un puerto de acceso abierto para toda internet, el sistema se vuelve vulnerable. El fallo no fue del software del servidor, sino del proceso humano a su alrededor.
Todo software es un cambio de cultura, antes hacían de una manera, ahora harán de otra. La implantación de un software exige cambio incluso en los procesos manuales a su alrededor.
Podemos poner como ejemplo una empresa que usaba hojas de cálculo para control de clientes e implanta un sistema de CRM (Customer Relationship Management). Muchos vendedores pueden resistirse, encontrando el sistema nuevo "complicado" o "lento", y continuarán usando sus hojas de cálculo antiguas "por seguridad", creando una inconsistencia de datos y un riesgo de seguridad (datos de clientes en archivos sueltos).
- El ser humano tiene como hábito continuar intentando hacer algo de la manera que lo hacía antes.
- El usuario piensa que el sistema es más inseguro que la manera anterior.
Esto es una cuestión de percepción y confianza. El proceso manual, por ser familiar y tangible (una carpeta de papel en un armario), puede parecer más seguro para el usuario que un sistema digital "abstracto" en la nube, aunque el armario pudiera ser forzado fácilmente y el sistema en la nube tenga múltiples capas de cifrado y control de acceso. La falta de comprensión genera desconfianza.
El usuario es frecuentemente llamado "la última línea de defensa" o, si no está entrenado, el "eslabón más débil" de la seguridad.
¿Cuándo se Considera Seguro un Software?
Por más pruebas que hayan sido ejecutadas, el software es un mecanismo complejo y casi con certeza algún fallo no fue previsto, y a lo largo del tiempo van siendo corregidos.
¿Por qué un sistema entra en producción incluso con fallos? Porque es muy barato corregir un fallo, al contrario de una empresa que produce coches donde el sistema de recall sería extremadamente dañino financieramente pudiendo llevar a una empresa a la quiebra.
Claro que en algunas circunstancias existen errores de software que son extremadamente caros, como por ejemplo un software de un avión que deja de funcionar llevando a la caída y la muerte de muchas personas.
La idea es desarrollar software donde los fallos no generen perjuicios catastróficos.
Procesos de Desarrollo de Software
Es necesario primero entender sobre cómo funciona el proceso de desarrollo de software para que tenga sentido el estudio sobre seguridad en software. Si ya conoces todo el proceso, ¡excelente! Voy a intentar hacer un resumen de años en pocas líneas.
Básicamente estas son las etapas de un desarrollo de software, pero es necesario tener en consideración que la metodología usada puede cambiar la forma con que cada etapa es ejecutada.
- Levantamiento Inicial
- Especificación
- Análisis y proyecto
- Codificación
- Pruebas
- Implantación
- Mantenimiento
Antiguamente teníamos algunas metodologías (abajo) que hoy son consideradas desfasadas después de lo que llamamos Manifiesto Ágil. No vamos a entrar en detalles sobre ellas, si es de tu interés basta investigar.
- Cascada
- Espiral Iterativo
- Prototipado evolutivo
- Codificación y corrección
Manifiesto Ágil
Las metodologías arriba generalmente no entregaban el software que el cliente pedía, pues el cliente no sabe lo que quiere de verdad o no pensó en todos los aspectos. Muchas veces el mercado cambiaba antes incluso de que el software estuviera listo. Era necesaria una metodología que incluyera al cliente en el proceso y que fuera flexible y esta fue la base para lo que llamamos Manifiesto Ágil.
- Individuos e interacciones sobre procesos y herramientas
- Esto enfoca al colaborador en el proyecto en vez de las burocracias involucradas.
- Herramientas y procesos son importantes, pero deben servir a las personas, y no al contrario.
- Software funcional sobre documentación extensa
- El software está en constante evolución. Perder mucho tiempo documentando no tiene sentido si esto cambiará tan rápido. Eso no quiere decir que no se deba tener una documentación mínima viable.
- Colaboración del cliente sobre negociación contractual
- El cliente debe formar parte del equipo y ver lo que está pasando y lo que está siendo desarrollado. Esto evita contratos cerrados con tiempo determinado, mantiene al cliente siempre informado y hace que errores de especificación o entendimiento sean encontrados rápido.
- Respuesta al cambio sobre la planificación
- Comienza a producir y responde al cambio como necesidad.
Es muy importante observar que la arquitectura del software en desarrollo precisa ser pensada para responder a los cambios. Un software completamente acoplado en sus funciones compromete este factor y demanda más tiempo para el cambio.
Las metodologías ágiles más usadas hoy son:
-
Scrum
- Basado en sprints de trabajo cortos y estructurados
- Los equipos de Scrum se comprometen a concluir un incremento de trabajo, que puede ser enviado, por medio de intervalos definidos, llamados sprints. El objetivo es crear ciclos de aprendizaje para reunir e integrar con rapidez el feedback de los clientes. Los equipos Scrum adoptan papeles específicos, crean artefactos especiales y realizan ceremonias regulares para mantener el avance de las cosas. El Scrum se define mejor en la Guía Scrum.
-
Kanban
- Hace el proceso más fluido
- Tiene que ver con visualizar el trabajo, limitar el trabajo en curso y maximizar la eficiencia (o flujo). Los equipos Kanban tienen como foco la reducción del tiempo que lleva para el proyecto (o historia de usuario) ir del inicio al fin. Para alcanzar ese objetivo, usan el tablero Kanban y mejoran siempre el flujo de trabajo.
Scrum | Kanban | |
---|---|---|
Origen | Desarrollo de software | Fabricación lean |
Ideología | Aprende por medio de experiencia, autoorganización y priorización y reflexiona sobre las ganancias y las pérdidas para siempre mejorar. | Usa recursos visuales para mejorar el trabajo en curso |
Ritmo | Sprints regulares, de duración fija (ej.: dos semanas) | Flujo continuo |
Prácticas | Planificación de sprint, sprint, scrum diario, revisión de sprint, retrospectiva del sprint | Visualiza el flujo del trabajo, limita el trabajo en curso, gestiona el flujo e incorpora loops de feedback |
Funciones | Propietario del producto, maestro scrum, equipo de desarrollo | Sin funciones obligatorias |
Vale un estudio profundizado sobre estas metodologías para trabajar con software hoy en día, principalmente el Scrum. Generalmente las empresas adaptan el scrum a sus necesidades disminuyendo algunas ceremonias. Existe incluso un mix entre Scrum y Kanban llamado Scrumban.
Existen muchas herramientas que ayudan en la aplicación de las metodologías ágiles.
Software Heredado
Un software heredado es un sistema, tecnología o aplicación que, aunque aún esté en uso y muchas veces sea crítico para las operaciones, es considerado obsoleto. Permanece activo principalmente por dos razones: soporta procesos de negocio vitales ("aún funciona") y el coste o el riesgo de sustituirlo o modernizarlo es considerado prohibitivo por la organización.
- Documentación inexistente o desactualizada haciendo cualquier modificación un proceso lento y arriesgado.
- Escrito en lenguajes obsoletos que poseen pocos desarrolladores disponibles en el mercado.
- Posee alto coste de mantenimiento
- Fue desarrollado sin seguir los estándares modernos de ingeniería de software, resultando en un código problemático.
Representa un gran riesgo para la seguridad de la información, pues no recibe actualizaciones y muchas veces posee vulnerabilidades conocidas y no corregidas.
Lenguajes de programación
El procesador solo entiende binario 0 y 1 y los seres humanos tienen dificultad de programar directamente así.
Para eso son definidos lenguajes de alto nivel que crean un algoritmo (flujo lógico) que consigue ser leído fácilmente por seres humanos.
El compilador (otro software) lee este lenguaje de alto nivel y transcribe para binario.
Los lenguajes pueden ser:
-
Compilados (C, C++, Delphi, Python, Rust, etc)
- Toma el código fuente de alto nivel y genera el ejecutable que ya está en lenguaje de máquina (0 y 1)
- Es necesario recompilar en cada cambio del código fuente
- Es necesario compilar para la arquitectura correcta del procesador
- Suele ser lenguajes más rápidos por ya estar todo listo.
-
Código Intermedio (Java, C#)
- Genera un código intermedio para ejecutar sobre una máquina virtual que está preparada para leer ese precompilado y compilar correctamente para la arquitectura del procesador que la máquina virtual está ejecutando, haciendo los ajustes necesarios e incluso mejoras.
- Suele optimizar el código para la compilación final de acuerdo con el procesador siendo una ventaja sobre el código interpretado.
- El lenguaje se preocupa en generar máquinas virtuales para cada arquitectura de procesador.
- Mayor flexibilidad
- Es más fácil hacer la ingeniería inversa con el código precompilado generando un problema de seguridad.
-
Interpretado (PHP, JavaScript, Beanshell, etc)
- Lee el código fuente en tiempo de ejecución y genera el código de máquina en tiempo real.
- No necesita generar ejecutables preparados para cada arquitectura
- Menos eficiente
Desarrollo de Aplicaciones Móviles
El desarrollo de aplicaciones móviles frecuentemente utiliza un código intermedio. Este código, a su vez, pasa por un proceso de compilación final que lo optimiza para la arquitectura específica de los procesadores móviles, buscando maximizar el rendimiento y, principalmente, la eficiencia energética para preservar la vida útil de la batería.
Para garantizar la autenticidad y la integridad de la aplicación, protegiéndola contra adulteraciones y falsificaciones, el código final es firmado digitalmente con un certificado digital.
Tanto Android como iOS realizan rigurosamente esta validación. Caso el código de la aplicación sea modificado de cualquier forma, la firma digital se vuelve inválida, y el sistema operativo rechaza la instalación o la actualización de la app, protegiendo al usuario.
La filosofía de Apple es más restrictiva: además de la firma del desarrollador, la propia Apple revisa y "notariza" cada aplicación, centralizando la distribución en la App Store (con excepciones recientes para tiendas alternativas en la Unión Europea). Ya Android permite la instalación de apps de fuentes externas (proceso conocido como sideloading), desde que la aplicación posea una firma digital válida.
Desde el punto de vista de la seguridad para el usuario común, este enfoque centralizado hace que el ecosistema del iPhone sea ampliamente considerado más seguro, pues elimina el principal vector de malwares: la instalación de apps de fuentes no confiables.
El riesgo en Android reside en el hecho de que, aunque no se pueda actualizar una app con una firma diferente, un invasor puede adulterar una aplicación legítima y distribuirla como una nueva app, firmada con su propio certificado. Por esa razón, la recomendación de seguridad fundamental para usuarios de Android es instalar aplicaciones exclusivamente a partir de la tienda oficial, la Play Store.
Es importante resaltar que toda esta estructura de seguridad es válida para aparatos en su estado original (iPhone sin jailbreak y Android no rooteado). Realizar estas modificaciones rompe las barreras de protección del sistema, permitiendo la instalación de cualquier software, inclusive los maliciosos.
Este principio de verificación no es exclusivo de los sistemas móviles. El Windows, a través del SmartScreen, alerta sobre aplicaciones no firmadas, y los repositorios de Linux utilizan claves criptográficas para validar la autenticidad y la integridad de los paquetes, garantizando que la fuente es confiable.
Arquitectura de sistema (Visión General)
Toda aplicación de software, en su esencia, puede ser dividida en tres componentes lógicos fundamentales:
- Interfaz: La capa con la cual el usuario interactúa.
- Lógica: Donde las reglas, procesamientos y cálculos son ejecutados.
- Datos: La capa responsable del almacenamiento y recuperación de las informaciones.
La forma en que estos componentes son organizados y se comunican define la arquitectura del sistema.
Mainframe
En este modelo totalmente centralizado, todos los tres componentes (presentación, lógica y datos) residen y son procesados en un único servidor de gran porte, el Mainframe. Los usuarios interactúan con el sistema a través de "terminales tontos" (dumb terminals), que sirven solo para exhibir informaciones y enviar comandos, sin capacidad de procesamiento local.
Stand Alone
Es la arquitectura clásica de los softwares de escritorio. Aquí, todos los componentes son instalados y ejecutados en la máquina del propio usuario. No hay, por defecto, una comunicación en red para acceder a una capa de datos o lógica externa. Ejemplos incluyen editores de texto u hojas de cálculo en su modo offline.
Cliente Servidor
En este modelo, la capa de Datos está centralizada en un servidor de base de datos. Sin embargo, las capas de Presentación y Lógica de Negocio son ejecutadas en la máquina del cliente.
Esta arquitectura está en gran parte obsoleta debido a un fallo de seguridad fundamental: la aplicación cliente precisa conectarse directamente a la base de datos por la red, lo que significa que las credenciales de acceso quedan almacenadas en la máquina del usuario. Un atacante podría fácilmente usar un sniffer de red para capturar esos datos de autenticación o, teniendo acceso a la máquina, extraer las credenciales y manipular la base de datos directamente.
Arquitecturas Modernas y Patrones Comunes
Arquitectura en 3 Capas y N Capas
La arquitectura de 3 Capas es la base para la mayoría de los sistemas modernos. Separa físicamente los tres componentes lógicos:
- Capa de Presentación: Responsable de la interfaz del usuario (ej: un navegador web, una app móvil).
- Capa de Aplicación/Lógica: Un servidor donde las reglas de negocio son procesadas.
- Capa de Datos: Un servidor de base de datos que almacena las informaciones.
La arquitectura en N Capas es una evolución de este modelo, permitiendo la creación de capas intermediarias adicionales para funciones especializadas, como caching, colas de mensajes o gateways de seguridad.
-
N Capas
-
Móvil
- WebApp que en verdad es una app que por debajo se ejecuta en el navegador. Es una cáscara solamente. La mayor parte es este tipo de app.
- Nativos son las apps reales.
- Híbridos, siendo que algunas funciones son tratadas de forma web
-
3 Capas
Arquitectura Web
La arquitectura web es la implementación más común del modelo de 3 capas. El flujo funciona de la siguiente forma:
- El navegador (Presentación) envía una petición vía protocolo HTTP/HTTPS.
- El Servidor de Aplicación (Lógica), ejecutando tecnologías como Java, C#, Python, Node.js, etc., recibe la petición, procesa las reglas de negocio e interactúa con la base de datos.
- El servidor entonces envía una respuesta de vuelta para el navegador, que la renderiza para el usuario.
Este modelo de comunicación es síncrono y conocido como Request-Response. Estilos arquitecturales como el REST son ampliamente utilizados para estructurar esta comunicación de forma estandarizada.
Arquitectura Móvil
- Nativo: Aplicaciones desarrolladas específicamente para un sistema operativo (iOS o Android), utilizando sus lenguajes y herramientas nativas. Ofrecen el mejor rendimiento y acceso total a los recursos del dispositivo.
- Web App: En la práctica, es un sitio web diseñado para parecer y comportarse como una aplicación, ejecutándose dentro del navegador del móvil.
- Híbrido: Una combinación de los dos mundos. Utiliza una "cáscara" nativa (WebView) para ejecutar tecnologías web (HTML, CSS, JavaScript), pero consigue acceder a algunas funcionalidades nativas del aparato a través de puentes (bridges).
Comunicación Asíncrona: Publish-Subscribe (Pub/Sub)
En contraste con el modelo síncrono, el patrón Pub/Sub utiliza un intermediario, como una cola de mensajes (message broker), para la comunicación.
- Un servicio ("Publisher") publica un mensaje en un tópico, sin saber quién lo recibirá.
- Otros servicios ("Subscribers"), que tienen interés en ese tópico, reciben el mensaje y lo procesan en su propio tiempo.
- Este modelo es asíncrono, desacoplando los servicios y siendo ideal para tareas que no exigen una respuesta inmediata.
Microservicios
La arquitectura de Microservicios estructura una aplicación como una colección de pequeños servicios independientes, cada uno responsable de un área de negocio específica. La comunicación entre esos servicios es un punto crucial, y utilizan una combinación de patrones:
Comunicación Síncrona (ej: APIs REST): Para comandos directos que necesitan una respuesta inmediata.
Comunicación Asíncrona (ej: Pub/Sub): Para notificar a otros servicios sobre eventos, garantizando desacoplamiento y resiliencia.