Conceptos

SAST (Static Application Security Testing)

#appsec#vulnmgmt

SAST (Static Application Security Testing) es el uso de herramientas automatizadas para analizar código fuente (sin ejecutar la aplicación) con el objetivo de detectar debilidades y…

Definición

SAST (Static Application Security Testing) es el uso de herramientas automatizadas para analizar código fuente (sin ejecutar la aplicación) con el objetivo de detectar debilidades y vulnerabilidades durante el desarrollo.

Contexto

SAST es una práctica “shift-left” dentro de un Secure SDLC. En el RAW se remarca que:

  • No pretende reemplazar la revisión manual, sino automatizar comprobaciones y acelerar la detección temprana.
  • Se complementa con técnicas como DAST y SCA para cubrir ángulos que SAST no ve (comportamiento en runtime, dependencias/OSS, etc.).

Desarrollo (MIT-style)

1) Revisión de código: manual vs automatizada

La revisión de código (caja blanca) busca vulnerabilidades mirando el código fuente.

Manual

  • Ventaja: análisis más profundo y contextual (mejor para lógica compleja).
  • Riesgo: fatiga y escalabilidad (bases de código grandes → se pasan cosas).

Automatizada (SAST)

  • Ventaja: rapidez y consistencia; detecta patrones comunes de forma repetible.
  • Riesgo: depende de reglas/modelado; puede generar falsos positivos/negativos.

En práctica: automatiza primero lo “barato” (reglas estructurales, patrones comunes) y reserva revisión manual para lo complejo (flujos de negocio, autorizaciones, etc.).

2) Ventajas y limitaciones (del RAW)

Ventajas

  • No requiere app en ejecución.
  • Mayor cobertura del código que técnicas dinámicas.
  • Rápido y útil para iterar.
  • Señala ubicación exacta en código.
  • Fácil de integrar en CI/CD.

Contras

  • Si no hay código (terceros), no aplica.
  • Propenso a falsos positivos.
  • No ve vulnerabilidades puramente dinámicas.
  • Muchas herramientas son específicas por lenguaje.

3) “Bajo el capó”: AST + análisis

El RAW describe dos pasos frecuentes:

  1. Convertir el código a un modelo abstracto (típicamente un AST).
  2. Ejecutar técnicas de análisis sobre ese modelo para encontrar problemas.

4) Técnicas de análisis típicas en SAST (del RAW)

No todas las herramientas implementan todas estas técnicas.

4.1 Análisis semántico (patrones locales)

Busca uso inseguro en el contexto cercano (p.ej. concatenación directa de input en una SQL):

mysqli_query($db, "SELECT * from users where username=".$_GET['username'])

4.2 Análisis de flujo de datos (taint / contaminación)

Rastrea cómo la información fluye desde fuentes (inputs controlables, p.ej. $_GET) hacia receptores/sinks peligrosos (p.ej. mysqli_query(), include()).

Idea clave: si datos de una fuente llegan al receptor sin sanearse, hay vulnerabilidad.

Gráfico de flujo de datos

4.3 Análisis de flujo de control

Analiza orden de operaciones para detectar problemas como variables no inicializadas, fugas de recursos o condiciones de error.

Ejemplo del RAW (Java): si cmd es NULL, trim() rompe en runtime.

4.4 Análisis estructural

Analiza estructuras del lenguaje y buenas prácticas (código muerto, bloques try/catch, y también señales de criptografía débil).

Ejemplo del RAW (RSA 1024 bits):

$options = array('private_key_bits' => 1024, 'private_key_type' => OPENSSL_KEYTYPE_RSA);
$res = openssl_pkey_new($options);

4.5 Análisis de configuración

Busca riesgos en archivos de configuración (no en el código) como web.config/php.ini.

Ejemplo del RAW (PHP) que suele alertar por facilitar RFI/SSRF:

allow_url_include = On
allow_url_fopen = On

5) Falsos positivos y falsos negativos

Definiciones (del RAW):

  • Falso positivo: se reporta una vulnerabilidad que no existe.
  • Falso negativo: no se reporta una vulnerabilidad que sí existe.

Buenas prácticas (operativas):

  • Triaging: validar el flujo real (fuente→sink), contexto y sanitización.
  • Ajustar reglas/config, scope y severidades para reducir ruido.
  • Mantener revisión manual como “segunda capa” para rutas críticas.

6) Ejemplo práctico (del RAW): Psalm sobre una app PHP

El RAW usa una app simple-webapp y Psalm para demostrar:

  • Análisis estructural básico.
  • Análisis de contaminación (--taint-analysis) con trazas fuente→sink.
  • Cómo el contexto (wrappers) afecta a la detección.

6.1 Configuración (psalm.xml) y scope

El RAW muestra que el proyecto:

  • Escanea el directorio de la app (html/).
  • Ignora dependencias (vendor/) para no “probar terceros”.
  • Ajusta errorLevel para controlar rigor.

6.2 Ejecución (estructural)

Terminal window
cd /home/ubuntu/Desktop/simple-webapp/
./vendor/bin/psalm --no-cache

6.3 Ejecución (taint analysis)

Terminal window
./vendor/bin/psalm --no-cache --taint-analysis

Ejemplo del RAW: TaintedInclude cuando $_GET['img'] llega a include() (LFI por concatenación):

include('./gallery-files/'.$_GET['img']);

6.4 Ajuste para entender wrappers (sinks especializados)

El RAW muestra cómo añadir anotaciones para que Psalm trate db_query() como sink SQL:

/**
* @psalm-taint-sink sql $query
* @psalm-taint-specialize
*/
function db_query($conn, $query){
$result = mysqli_query($conn, $query);
return $result;
}

6.5 Resultado: discrepancias vs revisión manual

El RAW compara manual vs Psalm (ejemplo):

  • $sql: vulnerable (ok)
  • $sql2: no vulnerable → Psalm vulnerable (falso positivo)
  • $sql3: vulnerable → Psalm no vulnerable (falso negativo)

7) Integración en el ciclo de desarrollo (del RAW)

SAST suele entrar pronto (fase de codificación) y el RAW propone dos patrones:

  • CI/CD: escanear en PR/merge (o solo en merges si el runtime es costoso).
  • IDE: feedback en tiempo real para corregir antes de llegar al pipeline.

El RAW sugiere una combinación razonable:

  • IDE: checks estructurales rápidos.
  • CI/CD: análisis más costoso (p.ej. taint/dataflow).

SAST en el ciclo de desarrollo

Ejemplos

  • Detectar SQLi con reglas semánticas (concatenación directa de input en SQL) y confirmar con revisión manual.
  • Detectar LFI cuando un parámetro (p.ej. $_GET['img']) llega a include() sin validación.

Pitfalls / Errores comunes

  • Tratar SAST como sustituto de revisión manual o de DAST.
  • No definir scope (escanea vendor/terceros y el ruido mata la adopción).
  • Sin proceso de triage: backlog infinito de alertas sin priorización.
  • Bloquear CI por findings “ruidosos” sin estrategia de baseline/excepciones.
  • No adaptar a workflows (PR vs merge, severidad por tipo de repo).

Diagrama

flowchart TD
  Dev[Dev escribe código] --> IDE[SAST en IDE]
  Dev --> PR[PR/Merge]
  PR --> CI[SAST en CI/CD]
  CI --> AST[Parseo a AST]
  AST --> A1[Análisis semántico]
  AST --> A2[Análisis flujo datos/taint]
  AST --> A3[Análisis flujo control]
  AST --> A4[Análisis estructural]
  AST --> A5[Análisis configuración]
  A1 --> Findings[Findings]
  A2 --> Findings
  A3 --> Findings
  A4 --> Findings
  A5 --> Findings
  Findings --> Triage[Triage + validación]
  Triage --> Fix[Fix]
  Fix --> PR

Referencias

  1. TryHackMe — OWASP Top 10 (2021): https://tryhackme.com/room/owasptop102021
  2. TryHackMe — OWASP API Top 10 (parte 1): https://tryhackme.com/room/owaspapisecuritytop105w
  3. TryHackMe — SDLC: https://tryhackme.com/room/sdlc
  4. TryHackMe — DAST (ZAP/Jenkins): https://tryhackme.com/room/dastzap
  5. Psalm — instalación: https://psalm.dev/docs/running_psalm/installation/
  6. VS Code Marketplace — Psalm plugin: https://marketplace.visualstudio.com/items?itemName=getpsalm.psalm-vscode-plugin
  7. VS Code Marketplace — Semgrep plugin: https://marketplace.visualstudio.com/items?itemName=Semgrep.semgrep
  8. PHP manual — preg_replace: https://www.php.net/manual/en/function.preg-replace.php