INTRODUCCIÓN

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Por qué las puertas de acceso a una vivienda tienen las bisagras hacia adentro?

Bisagras
Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Qué notáis de raro en esta imagen?

Bisagras
Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Por qué las puertas de acceso a una vivienda tienen las bisagras hacia adentro?

Desarrollo de Aplicaciones Seguras — Curso 2025/26
  • El pestillo asociado al pomo de una puerta es una medida de seguridad
  • Las bisagras no son una medida de seguridad, pero están implicadas en la seguridad
Desarrollo de Aplicaciones Seguras — Curso 2025/26

medidas de seguridad medidas seguras

Desarrollo de Aplicaciones Seguras — Curso 2025/26

En el software, este tipo de medidas no se tiene siempre en cuenta...

Ejemplo: extracto de la documentación de BEA WebLogic (2004):

Since most security for Web applications can be implemented by a system administrator, application developers need not pay attention to the details of securing the application unless there are special considerations that must be addressed in the code. For programming custom security into an application, WebLogic Server application developers can take advantage of BEA-supplied Application Programming Interfaces (APIs) for obtaining information about subjects and principals (identifying information for users) that are used by WebLogic Server. The APIs are found in the weblogic.security package.

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Muchos sistemas de software no se construyen con la seguridad en mente.

Las tecnologías reactivas como los cortafuegos pueden aliviar algunos ataques a los servidores, pero no abordan el problema principal: software mal hecho

Para poner en práctica la seguridad del software hay que:

  • Adoptar prácticas de ingeniería
  • Considerar la seguridad como parte del Software Development Lifecycle (SDL)
Desarrollo de Aplicaciones Seguras — Curso 2025/26

Software security points in the SDL

¿Cuáles son los puntos más importantes de cara a la seguridad?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Esta asignatura trata sobre la seguridad en los siguientes puntos...

  • Arquitectura y diseño
  • Construcción (no sólo implementación/código)
  • Operaciones
Desarrollo de Aplicaciones Seguras — Curso 2025/26

CÓDIGO Y DISEÑO

Ejemplo: Entrada no validada

Vulnerabilidad provocada por no validar la entrada del usuario:

Implementación en Python:

def greet_user(name):
    print(f"Hola {name}!")

# Supongamos que la entrada proviene de un parámetro web
user_input = "<script>alert('XSS')</script>"
greet_user(user_input)
Desarrollo de Aplicaciones Seguras — Curso 2025/26

Solución más segura:

import html

def greet_user(name):
    safe_name = html.escape(name)
    print(f"Hola {safe_name}!")
Desarrollo de Aplicaciones Seguras — Curso 2025/26

Ejemplo: Buffer overflow

Provocado por ofrecer a los atacantes la posibilidad de escribir arbitrariamente en memoria.

Implementación en C:

void trouble() {
  int a = 32; /* integer */
  char line[128]; /* character array */
  gets(line); /* read a line from stdin */
}
Desarrollo de Aplicaciones Seguras — Curso 2025/26

Ejemplo: Buffer overflow

Solución más segura:

void trouble() {
  int a = 32; /* integer */
  char line[128]; /* character array */
  fgets(line, sizeof(line), stdin);  /* read a line from stdin */
}
Desarrollo de Aplicaciones Seguras — Curso 2025/26

Estructura en memoria:

  • 0xNN es la dirección de comienzo de la pila (stack)
  • Marco de pila tras la llamada a trouble()...

Marco de pila antes de la ejecución:

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Marco de pila después de ejecución normal:

Marco de pila tras un ataque por buffer overflow:

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Implementation bugs

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿A qué se debe este buffer overflow?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Buffer overflow provocado por el (mal) uso de APIs vulnerables:
gets(), strcpy(), etc.

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Cómo evitar el mal uso de APIs vulnerables?

Desarrollo de Aplicaciones Seguras — Curso 2025/26
  • Code review (manual)
  • Análisis estático (automatizado):
    • Static Application Security Testing (SAST)
  • Análisis de dependencias (integrado en el SDLC):
    • Software Composition Analysis (SCA)
  • Análisis dinámico
    • Dynamic Application Security Testing (DAST)
Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Todos los problemas de seguridad se pueden resolver
con análisis de código?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Menos del 50%
— según Chest & West: Secure Programming with Static Analysis, 2007 —

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Qué otras actividades relacionadas con el desarrollo tienen implicaciones en la seguridad?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Arquitectura y diseño

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Ejemplo: Arquitectura insegura

Un servicio web que ejecuta consultas SQL directamente desde parámetros HTTP:

Implementación en Python:

@app.route('/user')
def user_info():
    name = request.args['name']
    query = f"SELECT * FROM users WHERE name='{name}'"
    return db.execute(query)
Desarrollo de Aplicaciones Seguras — Curso 2025/26

Principios de diseño seguro

  1. Defensa en profundidad: varias capas de seguridad.
  2. Mínimo privilegio: cada módulo o usuario solo debe tener los permisos mínimos necesarios.
  3. Separación de responsabilidades: la lógica de negocio no debe ejecutar tareas del sistema.
  4. Fail safe defaults: por defecto, negar acceso o fallar de forma controlada.
Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Por qué el diseño es clave para la seguridad?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

El diseño asegura la mantenibilidad

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Mantenibilidad

  • Hallar code smells o problemas de mantenibilidad
  • Refactoring: cómo cambiar el diseño/implementación sin cambiar la funcionalidad
  • Linting: verificar la calidad y estilo del código
  • Coding standards: Common Weakness Enumeration (CWE), CERT, CVE, NVD, ...

Ann Campbell: For secure code, maintainability matters

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Coding standards

El 60% de las CWE no son exactamente vulnerabilidades...

La vista CWE-699: Software Development contiene debilidades de categorías diversas...

  • Problemas de complejidad
  • Errores numéricos
  • Malas prácticas de codificación

Malas prácticas de codificación

  • CWE-478: Missing default case
  • CWE-581: Object Model Violation: Just One of Equals and Hashcode Defined
Desarrollo de Aplicaciones Seguras — Curso 2025/26

Tendencias 2019-2024

CWE Top 25 Most Dangerous Software Weaknesses

Al alza:

A la baja:

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Qué requisito de seguridad puede verse incumplido
si no se cumple la CWE-581?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Disponibilidad

Desarrollo de Aplicaciones Seguras — Curso 2025/26

ARQUITECTURA

Robert C. Martin: La arquitectura de un sistema software es la forma dada al sistema por aquellos que lo construyen. La forma es la división del sistema en componentes, la disposición de esos componentes y la manera en que se comunican entre sí.

Para un enfoque completo a la seguridad del software hay que combinar revisiones de código y análisis arquitectónico

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Qué tiene que ver la arquitectura en todo esto de la seguridad?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

La arquitectura software decide los componentes que conforman un sistema software y sus interacciones

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Son importantes otras actividades relacionadas con el desarrollo de software?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Mucho, pero no las trataremos aquí

Desarrollo de Aplicaciones Seguras — Curso 2025/26

No nos interesan (tanto)...

  • Técnicas criptográficas avanzadas
  • Gestión de identidades
  • Control de acceso
  • Etc.

nos interesan aquellos aspectos del desarrollo de software que, en principio, no parecen relacionados con la seguridad, pero que la ponen en riesgo si no se hacen bien.

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Así que hay que saber programación y técnicas de desarrollo de software para poder garantizar la seguridad?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿No hay un respiro para quienes no les gusta programar?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Threat modeling

😅 Threat modeling: diagramas y diseño de la arquitectura

  • Identificar requisitos de seguridad
  • Señalar amenazas y vulnerabilidades
  • Cuantificar la criticidad de amenazas y vulnerabilidades
  • Priorizar métodos de reparación

Métodos de threat modeling en arquitectura software:

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Conocéis Windsurf? ¿Github Copilot?

¿Es otro respiro para quienes no les gusta programar?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Ejemplo con Windsurf/Copilot

  1. Abrir código fuente Python con VSCode
    • server-side-request.py
    • temporary-file-creation.py
    • cryptographic-key-generation.py
  2. Comprobar las reglas SounarSource:
    • RSPEC-5144: Server-side requests should not be vulnerable to forging attacks
    • RSPEC-5445: Insecure temporary file creation methods should not be used
    • RSPEC-4426: Cryptographic key generation should be based on strong parameters
  3. Probar Windsurf o Github Copilot...
  4. Probar otros IDE: Cursor, Copilot Agent mode, etc.
Desarrollo de Aplicaciones Seguras — Curso 2025/26

PROGRAMACIÓN DEFENSIVA

Garantizar el comportamiento de todo elemento de una aplicación ante cualquier situación de uso por incorrecta o imprevisible que ésta pueda parecer

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿La programación defensiva garantiza un software seguro?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

No lo garantiza, porque al hablar de seguridad se supone la existencia de un adversario

Desarrollo de Aplicaciones Seguras — Curso 2025/26

La seguridad del software significa crear programas que se comportan correctamente incluso en presencia de un comportamiento malicioso.

Ejemplo en C

void printMsg(FILE* file, char* msg) {
  fprintf(file, msg);
}
Desarrollo de Aplicaciones Seguras — Curso 2025/26
void printMsg(FILE* file, char* msg) {
  fprintf(file, msg);
}

¿Cómo arreglamos el hecho de que algún argumento de la función pueda ser null? Aplicar programación defensiva...

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Aplicando programación defensiva:

void printMsg(FILE* file, char* msg) {
  if (file == NULL) {
    logError("attempt to print message to null file");
  } else if (msg == NULL) {
    logError("attempt to print null message");
  } else {
    fprintf(file, msg);
  }
}

NOTA: Hay alternativas mejores para el tratamiento de null, como los Optionals

Desarrollo de Aplicaciones Seguras — Curso 2025/26

¿Desde la perspectiva de la seguridad, esta solución que aplica programación defensiva es suficiente?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Desde la perspectiva de la seguridad, esta solución no es suficiente.

Un atacante podría especificar un string en un formato maligo,
pensado para provocar un buffer overflow.

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Recordemos el marco de pila de una llamada a función...

...antes de la ejecución:

...tras un ataque por buffer overflow:

Desarrollo de Aplicaciones Seguras — Curso 2025/26

LA FALACIA DE LA CALIDAD

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Las organizaciones que desarrollan software tienen grupos de ingenieros de calidad - Quality Assurance (QA) dedicados a escribir y ejecutar tests y evaluar sus resultados.

Es casi imposible mejorar la seguridad del software solo mejorando la QA

  • Los tests de funcionalidad sirven para asegurarse de que los usuarios típicos con las necesidades típicas estén contentos, pero no sirven para encontrar defectos de seguridad que no estén relacionados con características específicas de seguridad.

  • La mayor parte de las pruebas software sirven para comparar la implementación con los requisitos, enfoque no adecuado para encontrar problemas de seguridad.

  • Los problemas de seguridad no suelen ser violaciones de los requisitos, sino funcionalidades no deliberadas que hacen que un programa sea inseguro.

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Software fiable vs seguro

El software fiable hace lo que se supone que tiene que hacer.
El software seguro hace lo que se supone que tiene que hacer, y nada más.

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Ejemplo

Implementación con JSP

<c:if test="${param.sayHello}">
  <!-- Let's welcome the user ${param.name} -->
  Hello ${param.name}!
</c:if>
  • Puede que cumpla con requisitos, pero...

¿alguna vulnerabilidad?

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Es vulnerable a ataques de Cross-Site Scripting (XSS)

Desarrollo de Aplicaciones Seguras — Curso 2025/26

Ninguna cantidad de pruebas de caja negra llega a ser suficiente para revelar este problema.

  • Las pruebas de caja negra solo pueden comenzar cuando el sistema está terminado. Tras desplegarlo, los atacantes y los defensores están en situación de igualdad. Los atacantes pueden ahora estudiar el software.

  • La suma de horas de todos los posibles atacantes puede superar con creces la suma de horas de los defensores haciendo pruebas. Los atacantes pueden encontrar más vulnerabilidades.

  • Encontrar una prueba fallida es un signo de problemas, pero pasar una prueba con éxito no significa mucho.

Imagina a un ladrón que quiere entrar en tu casa y que las bisagras de la puerta principal están hacia fuera

Imagina a un ladrón que quiere entrar en tu casa y que las bisagras de la puerta principal están hacia fuera

El pomo en sí es una medida de usabilidad

Un pestillo es una medida de seguridad Una medida mal diseñada o implementada puede comprometer la seguridad Implementar solo medidas de seguridad no garantiza la seguridad real

Muchas de las vulnerabilidades en los sistemas informáticos no son por fallos en las medidas de seguridad, sino en otros aspectos del desarrollo. Por ejemplo, usar una biblioteca vulnerable para manejo de imágenes.

• Requisitos: identificar necesidades de confidencialidad, integridad y disponibilidad. • Arquitectura y diseño: prever amenazas, modelar riesgos (por ejemplo, con STRIDE). • Construcción: escribir código robusto y revisarlo con herramientas (SAST, SCA). • Pruebas: incluir casos de uso maliciosos y pruebas de penetración. • Calidad y mantenimiento: corregir vulnerabilidades, actualizar dependencias.

También configuración y despliegue.

El programa se ejecuta correctamente, pero si se muestra en una página web, ejecutará código arbitrario (XSS).

Los problemas arquitectónicos son muy difíciles (a veces imposibles) de encontrar tan solo mirando al código Por ejemplo, la ausencia de una separación clara entre módulos con diferentes niveles de privilegio puede dar lugar a vulnerabilidades graves que no se detectan en el análisis de código.

Aquí el fallo no es solo de código: el diseño permite inyección SQL. La solución implica modificar la arquitectura (p. ej., usar un ORM o una capa de acceso controlada).

Algunos ataques (v.g. Heartbleed) tardaron en detectarse por el mal formateo del código escrito, que dificultaba su revisión humana

Si no se cumple la invariante if a.equals(b) == true then a.hashCode() == b.hashCode().. puede haber problemas cuando se almacenen objetos de esta clase en una colección. Si los objetos de la clase en cuestión se usan como claves de una Hashtable o si se insertan en un Map o un Set, es crítico que objetos iguales tengan los mismos hashcodes. Si no, puede que un objeto esté, pero no sea encontrado... NO DISPONIBILIDAD

STRIDE (Microsoft): analiza amenazas de Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service y Elevation of Privilege. LINDDUN: centrado en la privacidad Ejemplo: para el diseño de una API web, el modelo STRIDE identificaría amenazas de suplantación (S), inyección (T), denegación de servicio (D) y escalada de privilegios (E).