De cero a héroe parte 3 en CodeQL: Investigación de seguridad con CodeQL

Elena Digital López

Profundizando en el análisis estático y la escritura de consultas CodeQL, el objetivo de este artículo es examinar técnicas avanzadas de investigación de seguridad con CodeQL. Para aquellos interesados en fortalecer sus habilidades en estas áreas, se recomienda participar en los desafíos interactivos disponibles en línea.

El análisis estático y la capacidad de escribir consultas CodeQL son fundamentales para la investigación de vulnerabilidades. Anteriormente, hemos tocado brevemente estas cuestiones en publicaciones pasadas, pero hoy nos centraremos en el análisis de variantes, la escritura de consultas de seguimiento de contaminación y varias técnicas de investigación de seguridad.

Cuando se audita una nueva base de código, puede resultar útil identificar llamadas a funciones o métodos de bibliotecas específicas. Por ejemplo, al auditar una aplicación Django para inyecciones SQL, uno puede buscar todas las llamadas al método execute() de django.db.connection.cursor(). En el contexto de CodeQL para Python, se hace uso de la biblioteca de gráficos de API para referirse a funciones y clases externas. Aquí se muestra un ejemplo de consulta para encontrar todas las llamadas al método execute desde la librería django.db:

/**
 * @id codeql-zero-to-hero/3-1
 * @severity error
 * @kind problem
 */

import python
import semmle.python.ApiGraphs

from API::CallNode node
where node =
    API::moduleImport("django").getMember("db").getMember("connection").getMember("cursor").getReturn().getMember("execute").getACall()
  and
    node.getLocation().getFile().getRelativePath().regexpMatch("2/challenge-1/.*")

select node, "Call to django.db execute"

Esta consulta ayuda a refinar los resultados y concentrarse en métodos específicos de bibliotecas cuando existen múltiples definiciones de un mismo método en varias bibliotecas.

En la versión más reciente de la API de seguimiento de contaminación de CodeQL, la configuración se realiza de manera diferenciada. Aquí presentamos un ejemplo de una consulta que encuentra el flujo de datos desde una solicitud Flask (request) hacia un sumidero (execute) de django.db:

/**
 * @kind path-problem
 * @problem.severity error
 * @id githubsecuritylab/3-6
 */

import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.ApiGraphs
import MyFlow::PathGraph

class ExecuteCall extends DataFlow::CallCfgNode {
  ExecuteCall() {
    this = API::moduleImport("django").getMember("db").getMember("connection").getMember("cursor").getReturn().getMember("execute").getACall()
  }
}

private module MyConfig implements DataFlow::ConfigSig {
  predicate isSource(DataFlow::Node source) {
    source = API::moduleImport("flask").getMember("request").asSource()
  }

  predicate isSink(DataFlow::Node sink) {
    exists(ExecuteCall ec |
      sink = ec.getArg(0)
    )
  }
}

module MyFlow = TaintTracking::Global<myconfig>;

from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "execute sink called with untrusted data"

Este tipo de análisis es esencial para rastrear pasos no conservadores de valor a diferencias del análisis de flujo de datos.

El análisis de variantes es un componente crucial en el proceso de identificación de vulnerabilidades en grandes bases de código modernas. Este proceso parte de un problema conocido y busca identificar variantes de esa vulnerabilidad. Utilizando CodeQL podemos modelar patrones vulnerables y aplicar estas consultas para buscar variantes no solo dentro de una aplicación, sino en múltiples aplicaciones a la vez a través del análisis de variantes en múltiples repositorios (MRVA).

El proceso de investigación de seguridad generalmente involucra las siguientes etapas:

  1. Exploración inicial: Habilitar el escaneo de código para obtener un panorama general de posibles vulnerabilidades.
  2. Ejecución de consultas específicas: Ejecutar consultas individuales o en conjunto para tipos específicos de vulnerabilidades.
  3. Identificación de fuentes y sumideros: Utilizar tipos como RemoteFlowSource para identificar las entradas de datos no confiables y sumideros en la base de código.
  4. Modelado de vulnerabilidades: Modelar vulnerabilidades específicas para encontrar variantes dentro de la base de código.

La herramienta MRVA permite ejecutar consultas CodeQL contra miles de repositorios simultáneamente. Esta capacidad es invaluable para detectar variantes de vulnerabilidades en grandes volúmenes de código abierto.

Se han publicado muchos estudios de casos y artículos de investigación utilizando CodeQL, que ofrecen valiosos ejemplos sobre cómo otros investigadores han utilizado esta herramienta para descubrir vulnerabilidades críticas. Entre ellos figura el análisis de RCE (Remote Code Execution) en pgAdmin por Salih Demir (@frycos) usando consultas de APIs no confiables.

Para aquellos interesados en compartir sus hallazgos o recibir asistencia, la comunidad de GitHub Security Lab en Slack está disponible para preguntas y discusiones sobre CodeQL y sus aplicaciones en la investigación de seguridad.

vía: GitHub Security

Scroll al inicio