Cómo SAST aborda las 10 principales vulnerabilidades de OWASP

Análisis de código estático para la seguridad: cómo SAST aborda las 10 principales vulnerabilidades de OWASP.

Las vulnerabilidades de seguridad son más fáciles de prevenir que de corregir. Un fallo de inyección SQL detectado durante una revisión de código se corrige en minutos. El mismo fallo, descubierto tras una brecha de seguridad, requiere semanas de respuesta a incidentes, investigación regulatoria y medidas correctivas, además de los datos que se hayan filtrado durante el proceso. El análisis estático de código consiste en detectar estos problemas antes de que el código se ejecute, examinando la estructura del código fuente, el flujo de datos y los patrones comparándolos con firmas de vulnerabilidades conocidas. Aplicado sistemáticamente, transforma la seguridad, pasando de ser una práctica reactiva a una característica intrínseca del proceso de desarrollo.

El OWASP Top 10 es el catálogo de referencia de los riesgos de seguridad más críticos para aplicaciones web, actualizado por el Open Web Application Security Project con base en datos de vulnerabilidades reales de miles de aplicaciones. Cada elemento de la lista es detectable, en mayor o menor medida, mediante herramientas de análisis estático. Esta guía relaciona cada categoría de OWASP con lo que el análisis estático puede encontrar, muestra el patrón de código vulnerable y su equivalente seguro, y explica qué herramientas aplican cada técnica.

Detecta la inyección antes de que lo hagan los atacantes.

SMART TS XL Rastrea las vulnerabilidades desde las API de JavaScript a través de los servicios Java hasta los sistemas backend de COBOL.

MÁS INFORMACIÓN

¿Qué son las pruebas de seguridad de aplicaciones estáticas (SAST)?

Las pruebas estáticas de seguridad de aplicaciones (SAST) analizan el código fuente, el código de bytes o el binario sin ejecutar el programa. El análisis examina cómo fluyen los datos a través de la aplicación, a qué operaciones sensibles a la seguridad llegan esos datos y si alguna ruta desde una entrada externa (entrada del usuario, parámetros HTTP, contenido de archivos, variables de entorno) conduce a una operación peligrosa (consulta de base de datos, comando del sistema, salida HTML, función criptográfica) sin la validación o sanitización adecuadas.

SAST es una capa dentro de un programa completo de seguridad de aplicaciones. Para comprender dónde encaja, es necesario compararlo con las alternativas:

Nuevo enfoqueCuando funcionaLo que encuentraLo que le falta
SAST (estático)Antes de la ejecución, en el código fuenteVulnerabilidades a nivel de código, patrones de inyección, mal uso de criptografía, secretos codificados.Vulnerabilidades que solo se manifiestan en tiempo de ejecución, problemas de configuración en la implementación.
DAST (Dinámico)Contra una aplicación en ejecuciónComportamiento en tiempo de ejecución, fallos de autenticación, problemas de configuración del servidorLos patrones a nivel de código no se activaron durante las pruebas.
SCA (Análisis de composición de software)En los manifiestos de dependenciaCVE conocidos en bibliotecas de tercerosVulnerabilidades en el código personalizado
IAST (Interactivo)Durante la ejecución de pruebas con instrumentaciónFlujos de datos en tiempo de ejecución con alta precisiónRequiere que la aplicación esté en ejecución, la respuesta será más lenta.

SAST proporciona la retroalimentación más temprana, ya que se ejecuta en código que aún no se ha desplegado, ni en la canalización de CI/CD ni en el IDE, antes de que la vulnerabilidad llegue a un entorno de prueba. Esta precocidad es su principal valor en materia de seguridad.

¿Qué tipos de amenazas puede mitigar el análisis estático de código?

Esta es una de las preguntas más buscadas sobre SAST. La respuesta directa:

El análisis estático de código puede mitigar las amenazas que se manifiestan en patrones de código fuente : vulnerabilidades de inyección (SQL, comandos, XSS), uso indebido de criptografía, credenciales codificadas, implementaciones de autenticación inseguras, control de acceso deficiente en la lógica del código y fallos en la integridad de los datos. No puede mitigar las amenazas que surgen de la configuración en tiempo de ejecución, la topología de red o la configuración de la infraestructura; para ello se requieren pruebas de seguridad de datos (DAST), pruebas de penetración o análisis de seguridad de la infraestructura.

Análisis estático frente a análisis dinámico para la cobertura de OWASP

El análisis dinámico (DAST) y el análisis estático (SAST) detectan diferentes subconjuntos de vulnerabilidades de OWASP. Ninguno lo abarca todo. La Guía de Pruebas de Seguridad Web de OWASP (WSTG) es el marco metodológico para las pruebas dinámicas; las herramientas SAST como CodeQL, Semgrep y SonarQube se centran en la capa de código fuente.

Categoría Top 10 de OWASPCobertura SASTCobertura de DAST
Control de acceso rotoParcial, lagunas en la lógica del códigoBuenas pruebas de comportamiento en tiempo de ejecución
Fallas criptográficasDetección de algoritmos fuertesDébil, difícil de observar desde fuera
InyecciónAnálisis de contaminación fuertePruebas de carga útil fuertes y activas
Diseño inseguroDetección parcial de patronesDébil, requiere conocimientos de diseño
Configuración incorrecta de seguridadParcial, configuración en el códigoPruebas en entornos reales y exigentes
Componentes vulnerablesDébil, SCA es mejorDébil, SCA es mejor
Errores de autenticaciónCredenciales parciales y codificadas, patrones débilesPruebas de seguridad, sesión y autenticación
Fallos en la integridad de los datosPatrones de deserialización parcialesDébil, difícil de detectar externamente.
Fallos de registroRegistros parciales o incompletosAusencia débil y difícil de observar
SSRFFuerte, contamina la llamada HTTPPruebas de solicitud sólidas y activas

Conclusión: SAST y DAST son complementarios. Para obtener la máxima cobertura de OWASP, ejecute ambos. Para equipos con presupuestos limitados que parten de cero, ejecute primero SAST, ya que proporciona la retroalimentación más rápida a los desarrolladores y la mayor cobertura de inyección.

OWASP Top 10: Qué encuentra el análisis estático y cómo

A01, Control de acceso averiado

El control de acceso deficiente es el principal riesgo de OWASP. El análisis estático aborda las manifestaciones a nivel de código: la falta de comprobaciones de autorización en funciones y puntos finales, las referencias a objetos que exponen identificadores internos sin validación y las asignaciones de roles codificadas que eluden las estructuras de permisos previstas.

Lo que detecta el análisis estático: Métodos que manejan operaciones sensibles sin una verificación de autorización correspondiente; referencias directas a objetos donde la ID del objeto proviene de la entrada del usuario sin validación de acceso; patrones de navegación forzada donde se verifica el estado autenticado pero no la propiedad del objeto.

Java

// Vulnerable: no ownership check -- any authenticated user can access any order
@GetMapping("/orders/{orderId}")
public Order getOrder(@PathVariable Long orderId) {
    return orderRepository.findById(orderId).orElseThrow();
}

// Secure: verify the order belongs to the requesting user
@GetMapping("/orders/{orderId}")
public Order getOrder(@PathVariable Long orderId,
                      @AuthenticationPrincipal UserDetails user) {
    Order order = orderRepository.findById(orderId).orElseThrow();
    if (!order.getOwnerId().equals(user.getUserId())) {
        throw new AccessDeniedException("Order does not belong to requesting user");
    }
    return order;
}

Lo que el análisis estático no puede detectar: ​​Fallos en el control de acceso en tiempo de ejecución donde la lógica es correcta, pero los datos utilizados para tomar la decisión están comprometidos. Para estos casos, se requieren pruebas DAST y de penetración.

A02, Fallos criptográficos

La criptografía débil se puede detectar de forma fiable mediante análisis estático porque los patrones vulnerables, MD5, SHA-1, DES, modo ECB, claves codificadas, son identificables léxicamente en el código fuente.

pitón

# Vulnerable: MD5 for password hashing (broken algorithm)
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()

# Vulnerable: hardcoded encryption key
KEY = b"mysecretkey12345"
cipher = AES.new(KEY, AES.MODE_ECB)  # ECB mode also vulnerable

# Secure: bcrypt for passwords, environment-sourced keys
import bcrypt, os
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))

# Secure: AES-GCM with environment-sourced key
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = os.environ["ENCRYPTION_KEY"].encode()
aesgcm = AESGCM(key)

Bandera de reglas de análisis estático: MD5/SHA-1 para fines sensibles a la seguridad, modo DES/3DES/RC4/ECB, claves y secretos criptográficos codificados, HTTP en lugar de HTTPS para la transmisión de datos sensibles y verificación de certificados deshabilitada (verify=False en solicitudes de Python, setHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER) en Java).

A03, Inyección

Inyección, SQL, comandos del sistema operativo, LDAP, XSS, inyección de plantillas: esta es la categoría donde el análisis de contaminación interprocedimental ofrece su valor más directo. La vulnerabilidad requiere rastrear la entrada no confiable desde su origen a través de llamadas a funciones hasta un destino peligroso.

javascript

// Vulnerable: direct string interpolation in SQL (SQL injection)
app.get('/users', async (req, res) => {
    const name = req.query.name;
    const result = await db.query(`SELECT * FROM users WHERE name = '${name}'`);
    res.json(result.rows);
});

// Secure: parameterized query
app.get('/users', async (req, res) => {
    const name = req.query.name;
    const result = await db.query('SELECT * FROM users WHERE name = $1', [name]);
    res.json(result.rows);
});

php

// Vulnerable: unescaped output (XSS)
echo "Welcome, " . $_GET['username'];

// Secure: context-appropriate escaping
echo "Welcome, " . htmlspecialchars($_GET['username'], ENT_QUOTES, 'UTF-8');

CSharp

// Vulnerable: command injection in C#
var process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c " + userInput;
process.Start();

// Secure: avoid shell interpretation, validate and whitelist inputs
var allowedCommands = new HashSet<string> { "report", "export" };
if (!allowedCommands.Contains(userInput))
    throw new ArgumentException("Invalid command");

Herramientas que realizan análisis de contaminación interprocedimental para inyección: CodeQL (la más precisa), Semgrep con modo de contaminación, Snyk Code, SonarQube con reglas de seguridad.

A04, Diseño inseguro

El diseño inseguro es la categoría más difícil de OWASP para el análisis estático porque se refiere a decisiones arquitectónicas más que a patrones de código. El análisis estático puede señalar los siguientes síntomas:

Falta de lógica de limitación de velocidad en los puntos finales de autenticación, ausencia de bloqueo de cuenta tras intentos fallidos, lógica empresarial que omite pasos de validación y funciones que realizan operaciones privilegiadas sin registro de auditoría. Estos problemas se detectan como patrones faltantes, mediante un análisis estático que informa sobre lo que falta en lugar de lo que está presente.

Algunas herramientas SAST admiten reglas personalizadas que pueden codificar los requisitos de diseño de seguridad de la organización: cada método del controlador debe llamar a una función de autorización, cada escritura en la base de datos debe ir precedida de una validación de entrada, cada llamada a una API externa debe usar un tiempo de espera. Estas reglas personalizadas convierten los requisitos de diseño en restricciones de código que se pueden aplicar.

A05, Configuración de seguridad incorrecta

La configuración incorrecta de seguridad en el código incluye: funciones de seguridad deshabilitadas, encabezados CORS permisivos, encabezados de respuesta de seguridad faltantes, modo de depuración habilitado en producción y mensajes de error detallados que exponen rastreos de pila.

pitón

# Vulnerable: Flask debug mode enables interactive debugger in production
app = Flask(__name__)
app.run(debug=True)  # exposes console access if error occurs

# Vulnerable: overly permissive CORS
from flask_cors import CORS
CORS(app, origins="*")  # allows any origin

# Secure: environment-controlled debug, restricted CORS
import os
debug_mode = os.environ.get("FLASK_DEBUG", "false").lower() == "true"
CORS(app, origins=os.environ.get("ALLOWED_ORIGINS", "").split(","))
app.run(debug=debug_mode)

Bandera de reglas de análisis estático: modo de depuración establecido en True en el origen, orígenes CORS comodín, encabezados de seguridad faltantes en las configuraciones de respuesta HTTP, verificación de certificado SSL deshabilitada y credenciales predeterminadas en los archivos de configuración.

A06, Componentes vulnerables y obsoletos

Esta categoría se aborda principalmente mediante el Análisis de Composición de Software (SCA) en lugar del SAST tradicional. Los escaneos SCA package.json, pom.xml, requirements.txty manifestaciones similares contra bases de datos de vulnerabilidades (Base de datos nacional de vulnerabilidades, Base de datos de avisos de GitHub).

SAST contribuye identificando el uso obsoleto de API, las llamadas a funciones de biblioteca que han sido reemplazadas debido a fallos de seguridad o el uso directo de patrones vulnerables que incluso las bibliotecas más recientes ya no recomiendan.

Herramientas específicas para A06: npm audit, pip-audit, snyk test, OWASP Dependency-Check, GitHub Dependabot y Mend (anteriormente WhiteSource).

A07, Fallos de identificación y autenticación

El análisis estático encuentra los antipatrones de autenticación a nivel de código: contraseñas codificadas, validación débil de contraseñas, tokens de sesión generados con aleatoriedad no criptográfica, falta de invalidación de sesión al cerrar sesión e implementaciones de JWT que aceptan none algoritmo.

javascript

// Vulnerable: JWT accepting 'none' algorithm -- allows signature bypass
const decoded = jwt.verify(token, secret, { algorithms: ['HS256', 'none'] });

// Vulnerable: hardcoded admin credentials
if (username === 'admin' && password === 'admin123') {
    grantAccess();
}

// Secure: algorithm whitelist, no hardcoded credentials
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
    algorithms: ['HS256']  // explicit allowlist only
});

CSharp

// Vulnerable: weak random for session token generation in C#
var sessionToken = new Random().Next().ToString();

// Secure: cryptographically secure random
using var rng = RandomNumberGenerator.Create();
var bytes = new byte[32];
rng.GetBytes(bytes);
var sessionToken = Convert.ToBase64String(bytes);

A08, Fallos en la integridad del software y los datos

Esta categoría abarca la deserialización insegura y las actualizaciones de software no verificadas. El análisis estático detecta: Java ObjectInputStream deserialización de datos de fuentes no confiables, Python pickle.loads() en datos externos, PHP unserialize() con entrada controlada por el usuario y analizadores YAML que utilizan cargadores no seguros.

pitón

# Vulnerable: pickle deserialization of untrusted data
import pickle
data = pickle.loads(request.data)  # arbitrary code execution risk

# Vulnerable: unsafe YAML loader
import yaml
config = yaml.load(user_input)  # yaml.load without Loader is unsafe

# Secure: safe alternatives
import json
data = json.loads(request.data)  # JSON cannot execute code

import yaml
config = yaml.safe_load(user_input)  # safe_load disables arbitrary object creation

A09, Fallos en el registro y la monitorización de seguridad

Los fallos de registro se pueden detectar mediante análisis estático como patrones ausentes: operaciones sensibles, eventos de autenticación, decisiones de control de acceso, modificaciones de datos, que se realizan sin instrucciones de registro correspondientes. Las reglas de análisis estático pueden requerir que ciertas llamadas a funciones siempre coincidan con las llamadas al registro de auditoría.

Lo que detecta el análisis estático: el registro de contraseñas o tokens (el registro de datos confidenciales también es una vulnerabilidad), los manejadores de excepciones que ignoran silenciosamente los errores sin registrarlos y los bloques catch que registran el mensaje de excepción sin procesar (que puede contener datos confidenciales).

Java

// Vulnerable: swallowed exception, no logging
try {
    authenticateUser(username, password);
} catch (Exception e) {
    // silent failure -- no log, no audit trail
}

// Vulnerable: logging sensitive data
log.info("User logged in with password: " + password);

// Secure: log the event, not the credential
try {
    authenticateUser(username, password);
    auditLog.info("Authentication success for user: {}", username);
} catch (AuthenticationException e) {
    auditLog.warn("Authentication failure for user: {}", username);
    throw e;  // do not swallow
}

A10, Falsificación de solicitud del lado del servidor (SSRF)

SSRF constituye un caso sólido para el análisis de contaminación interprocedimental. Esta vulnerabilidad requiere el seguimiento de la entrada controlada por el usuario hasta la solicitud HTTP, a menudo mediante múltiples llamadas a funciones. Una herramienta que solo analiza funciones individuales no puede detectar SSRF cuando la construcción de la URL y la llamada HTTP se realizan en funciones diferentes.

pitón

# Vulnerable: user-controlled URL in HTTP request (SSRF)
import requests

def fetch_resource(url):
    return requests.get(url).content  # no validation

def api_endpoint(request):
    target = request.json().get("url")    # attacker controls this
    return fetch_resource(target)          # SSRF across function boundary

# Secure: allowlist validation before making the request
from urllib.parse import urlparse

ALLOWED_HOSTS = {"api.internal.example.com", "cdn.example.com"}

def fetch_resource(url: str) -> bytes:
    parsed = urlparse(url)
    if parsed.hostname not in ALLOWED_HOSTS:
        raise ValueError(f"URL host not allowed: {parsed.hostname}")
    return requests.get(url, timeout=5).content

Herramientas de análisis de código estático para la seguridad de OWASP

La siguiente tabla relaciona las principales herramientas SAST con las categorías de OWASP que abordan con mayor eficacia:

Idiomas primariosFortalezas de OWASPNuevo enfoque
CódigoQLJava, JS/TS, Python, C/C++, Go, RubyA03 Inyección, A10 SSRF (contaminación profunda)Análisis semántico interprocedimental
Semgrep30+ idiomasA03, A02, A07 (basado en patrones + modo de contaminación)Coincidencia de patrones + contaminación superficial
Código SnykJava, JS/TS, Python, C#A03, A07, A08Análisis de contaminación basado en aprendizaje automático
SonarQube30+ idiomasA02, A03, A05, A07, A09Flujo de datos basado en reglas
Checkmarx30+ idiomasCobertura completa de OWASPcontaminación interprocedimental
VeracódigoJava, .NET, JS, PHPCobertura completa de OWASPAnálisis de código de bytes y contaminación
ZAP OWASPAgnóstico del lenguajeA01, A05, A07 (tiempo de ejecución)DAST, pruebas dinámicas
SMART TS XLCOBOL, JCL, Java, Python, RPG, SQLContaminación interlingüística, riesgo de dependenciaEstructural interlingüística + contaminación

Cómo SMART TS XL Aborda la seguridad en las bases de código empresariales.

Los programas de seguridad empresarial se enfrentan a un desafío que las herramientas SAST de un solo lenguaje no pueden resolver: la superficie de ataque abarca varios lenguajes. Una aplicación web puede aceptar la entrada del usuario en JavaScript, procesarla en Java y enviarla a través de una cola de mensajes a un programa COBOL que ejecuta SQL en una base de datos DB2. La vulnerabilidad de inyección existe en cuatro lenguajes diferentes. Ningún escáner de lenguaje individual detecta la ruta completa de la infección.

SMART TS XL, análisis de código estático cubre todos los lenguajes en esta cadena simultáneamente. Cuando la entrada no confiable fluye desde un controlador de API de JavaScript a través de un servicio Java hacia un programa COBOL que construye una consulta SQL dinámica, SMART TS XL rastrea esa ruta a través del gráfico completo de llamadas entre lenguajes, el mismo seguimiento de contaminación interprocedimental que CodeQL aplica dentro de Java, aplicado a Java, COBOL y SQL en conjunto.

La capacidad de mapeo de dependencias de la aplicación proporciona una visión relevante para la seguridad sobre qué componentes del sistema interactúan con entradas externas, cuáles acceden a operaciones privilegiadas y cuál es la superficie de ataque completa del sistema. Esta visión arquitectónica de seguridad es la base para el modelado de amenazas; no se pueden modelar amenazas contra un sistema cuya estructura se desconoce.

La capacidad de análisis de impacto es fundamental para los programas de remediación de seguridad: cuando se detecta una vulnerabilidad en un componente, el análisis de impacto identifica todos los demás componentes que dependen del vulnerable, lo que permite definir con precisión el alcance de la remediación antes de modificar cualquier código. En el caso de grandes bases de código heredadas, donde un programa COBOL con una vulnerabilidad de seguridad está integrado en cientos de otros programas, conocer el alcance completo de la remediación antes de comenzar marca la diferencia entre una solución controlada y un incidente en cascada.

Para organizaciones que gestionan modernización heredada En los programas, el análisis de seguridad del código fuente heredado es un requisito previo, no una consideración posterior. Migrar programas COBOL vulnerables a Java produce programas Java vulnerables. SMART TS XLEl análisis de seguridad garantiza que las vulnerabilidades se identifiquen y se corrijan como parte del proceso de modernización, y no que se descubran en el sistema migrado.

Integración de SAST en el ciclo de vida del desarrollo

El análisis de seguridad estático ofrece su máximo valor cuando se ejecuta en el momento de la decisión, cuando se escribe y revisa el código, y no después de que se haya implementado.

En el IDE: SonarLint, las extensiones de Snyk para el IDE y la extensión de CodeQL para VS Code muestran los hallazgos directamente en el código mientras los desarrolladores lo escriben. Una alerta de inyección SQL que aparece en el momento en que un desarrollador escribe el patrón vulnerable se soluciona en segundos.

En las solicitudes de extracción: SAST, integrado en GitHub Actions, GitLab CI o Jenkins, se ejecuta en cada solicitud de extracción y publica los hallazgos como comentarios de revisión de código en línea. El desarrollador ve el hallazgo en contexto, junto con el código que lo causó.

Como control de calidad: el modelo de control de calidad de SonarQube bloquea las fusiones cuando se introducen nuevos puntos críticos de seguridad. Esto convierte la seguridad no en un paso de revisión opcional, sino en un requisito estructural del proceso de fusión.

De forma programada: el análisis interprocedimental profundo, CodeQL, Checkmarx, conjuntos completos de reglas Semgrep, suele ser demasiado lento para la ejecución por confirmación, pero se ejecuta todas las noches o semanalmente en la rama principal, encontrando vulnerabilidades que requieren un análisis completo del gráfico de llamadas para su detección.

El enfoque por capas, las reglas rápidas basadas en patrones en el IDE y en las confirmaciones, el análisis profundo de contaminación en las solicitudes de extracción y las pruebas nocturnas, proporciona tanto la inmediatez que necesitan los desarrolladores como la exhaustividad que requieren los programas de seguridad.