Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
codeql-workshop — Da tus primeros pasos en CodeQL para Python escribiendo una consulta para encontrar CVE-2024-32022 | Kitploit
Herramientas/GitHubGitHub/sylwia-budzynska/codeql-workshop
Análisis EstáticoAnálisis de VulnerabilidadesAnálisis de CódigoAprendizaje y EducaciónRecursos CuradosRutas de Aprendizaje y CursosLabs y Práctica
GitHubsylwia-budzynska/codeql-workshop

codeql-workshop

Da tus primeros pasos en CodeQL para Python escribiendo una consulta para encontrar CVE-2024-32022

Ver Repositorio
128hace 1 mesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Encontrando vulnerabilidades con CodeQL

Taller original de Sylwia Budzynska

Requisitos previos • Recursos • Taller

  • ¿Para quién es?: Ingenieros de seguridad, investigadores de seguridad y desarrolladores.
  • Lo que aprenderás: Aprende a usar CodeQL para explorar código y para encontrar problemas de seguridad.
  • Lo que crearás: Crea una consulta de CodeQL basada en un aviso de seguridad para encontrar una inyección de comandos.

📣 Requisitos previos

Puedes elegir entre dos opciones para ejecutar los ejercicios del taller:

  • Opción A: Instalación local (Usando VS Code: CodeQL se ejecuta localmente en tu máquina)
  • Opción B: GitHub Codespace (Usando un navegador o VS Code: CodeQL se ejecuta de forma remota en un GitHub Codespace basado en Linux en la nube)

Opción A: Instalación local

Usa una instalación local de CodeQL para trabajar en los ejercicios del taller.

Requisitos previos

  • Visual Studio Code (VS Code) y git instalados en tu máquina local.

Instrucciones

  1. Instala la extensión de VS Code para CodeQL
  2. Ejecuta en la terminal:```bash git clone https://github.com/sylwia-budzynska/codeql-workshop cd codeql-workshop git submodule init git submodule update --recursive --depth 1

Download CodeQL databases

curl -L -O "https://github.com/sylwia-budzynska/codeql-workshop/releases/download/v1/test-app-db.zip" curl -L -O "https://github.com/sylwia-budzynska/codeql-workshop/releases/download/v1/kohya_ss-db.zip"

root@kitploit:~
3. En VS Code: Archivo -> **Abrir espacio de trabajo desde archivo...** `vscode-codeql-starter.code-workspace`
4. Continúa con [Seleccionar una base de datos de CodeQL](#select-codeql-database)
5. Luego, [Prueba tu instalación](#test-your-installation)

### Opción B: GitHub Codespace

Usa un GitHub Codespace remoto para trabajar en los ejercicios del taller.

#### Requisitos previos

* Cuenta de GitHub ([regístrate](https://github.com/) gratis)
* Navegador (puedes realizar todo el taller en un navegador; es la configuración más rápida) o [Visual Studio Code](https://code.visualstudio.com/download) (VS Code) con la extensión [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) instalada en tu máquina local.

Nota: Las primeras 120 horas por núcleo de uso de Codespace son gratuitas al mes; usamos un codespace con 4 núcleos para este taller, ya que 4 núcleos es el máximo actual para cuentas gratuitas. (Si tienes una cuenta Pro, recomendamos cambiar a una máquina de 8 núcleos).

#### Instrucciones

1. Inicia sesión en tu cuenta de [GitHub](https://github.com/login)
2. Ve al repositorio https://github.com/sylwia-budzynska/codeql-workshop
3. Haz clic en Code -> Codespaces
4. Haz clic en el signo más (+) para crear un nuevo codespace.

<img src="https://assets.kitploit.com/production/public/readmes/33098/c86e537f9e7891fb6bdb5da727cae5b6ad0b2c9ac94f67854d48296f2dad89cb.png"  width="439" alt="Captura de pantalla: Crear Codespace, haz clic en el signo más">

VS Code se iniciará en tu navegador y se creará un Codespace remoto. Esto puede tardar unos minutos.
Si se te pide abrir el espacio de trabajo `vscode-codeql-starter.code-workspace`, haz clic en "Abrir espacio de trabajo".

5. Si quieres usar VS Code localmente, pulsa el botón de las tres líneas en la esquina superior izquierda y selecciona "Abrir VS Code Desktop". La opción puede tardar unos minutos en aparecer.

<img src="https://assets.kitploit.com/production/public/readmes/33098/f2c8c2fe6da80142344b17c208da31a23c3fa68a3917a124f0e2f7871b6a20f7.png" width="300" alt="Captura de pantalla: Pulsa el botón de las tres líneas y abre en VS Code Desktop">

6. Continúa con [Seleccionar una base de datos de CodeQL](#select-codeql-database)
7. Luego, [Prueba tu instalación](#test-your-installation)

Puedes ver tus codespaces en [github.com/codespaces](https://github.com/codespaces). El codespace se apagará solo después de unas horas sin usarlo, pero para asegurarte de no usar horas adicionales de las 120 gratuitas, recuerda ir a [github.com/codespaces](https://github.com/codespaces) > tres puntos > "Detener codespace" después del taller.

#### Solución de problemas de la instalación

En caso de que veas errores como:
* `Failed to run query: Could not resolve library path for [..]`
* `Could not resolve module [..]`
* `Could not resolve type [..]`

Es muy probable que hayas omitido clonar los submódulos de git (es decir, el repositorio ql). Para solucionarlo, ejecuta `git submodule init && git submodule update --recursive`.

### Seleccionar base de datos de CodeQL

1. Asegúrate de tener el espacio de trabajo `vscode-codeql-starter.code-workspace` abierto en VS Code.
2. Haz clic en el icono "QL" en el panel de pestañas izquierdo para ir a la vista de CodeQL.
3. Haz clic en "Elegir base de datos desde archivo" y selecciona el archivo `test-app-db.zip` en la raíz del repositorio.
   Nota: En este punto, es posible que encuentres un error en VSCode con un mensaje emergente que pide instalar el CodeQL CLI. Aceptar esta instalación debería solucionar el problema. Después de que se complete la instalación de la CLI, deberías poder completar la selección de base de datos anterior.
   <img src="https://assets.kitploit.com/production/public/readmes/33098/65cc5790b8b49113623bc9a9b34a1be61575b05bea2428c46f83115e2271148b.png"  alt="Captura de pantalla: mensaje de error de VSCode sobre CodeQL">
   <img src="https://assets.kitploit.com/production/public/readmes/33098/c3bf9c304d9c1f6199f591c9bcbf6e446ee4f5388ab209e30887326698129f84.png"  alt="Captura de pantalla: VSCode instalando CodeQL CLI">

### Prueba tu instalación

#### Requisitos previos

Asegúrate de que la base de datos de CodeQL elegida anteriormente esté seleccionada en la vista de CodeQL. (Haz clic en "Seleccionar" si no lo está)

Cuando la base de datos esté seleccionada, debería verse así (observa la marca de verificación):

<img src="https://assets.kitploit.com/production/public/readmes/33098/fee6e47c0d9b0754c7ac9e29e2f0b3a721093aa5ce882615b3839a99f4862506.png"  alt="Captura de pantalla: Base de datos de CodeQL seleccionada">

#### Instrucciones

1. En VS Code: ve a la carpeta del espacio de trabajo: `codeql-custom-queries-python`
2. Crea un nuevo archivo `test.ql`
3. agrega el siguiente contenido: `select "Hello World!"`
4. Guarda el archivo, haz clic derecho en el área del archivo y elige "CodeQL: Ejecutar consulta en la base de datos seleccionada"
5. Deberías ver una nueva pestaña abierta con el resultado "Hello World!"

## :books: Recursos

- [Tutoriales de QL](https://codeql.github.com/docs/writing-codeql-queries/ql-tutorials/)
- [Guía del lenguaje CodeQL para Python](https://codeql.github.com/docs/codeql-language-guides/codeql-for-python/)
- [Documentación de CodeQL](https://codeql.github.com/docs/)
- [Referencia del lenguaje QL](https://codeql.github.com/docs/ql-language-reference/)
- [Biblioteca de CodeQL para Python](https://codeql.github.com/codeql-standard-libraries/python/)
- [Consulta básica para código Python](https://codeql.github.com/docs/codeql-language-guides/basic-query-for-python-code/)
- [Clases de QL](https://codeql.github.com/docs/ql-language-reference/types/#classes)
- [CodeQL de cero a héroe parte 1: los fundamentos del análisis estático para la investigación de vulnerabilidades](https://github.blog/2023-03-31-codeql-zero-to-hero-part-1-the-fundamentals-of-static-analysis-for-vulnerability-research/)
- [CodeQL de cero a héroe parte 2: primeros pasos con CodeQL](https://github.blog/2023-06-15-codeql-zero-to-hero-part-2-getting-started-with-codeql/)
- [CodeQL de cero a héroe parte 3: investigación de seguridad](https://github.blog/2024-04-29-codeql-zero-to-hero-part-3-security-research-with-codeql/)
- [CodeQL de cero a héroe parte 4: estudio de caso de Gradio](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-4-gradio-framework-case-study/)
- [CodeQL de cero a héroe parte 5: depuración de consultas](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-5-debugging-queries/)

## Taller

¡Bienvenido al taller "Encontrando vulnerabilidades con CodeQL"!

Esta sesión presentará los fundamentos de la investigación de seguridad y el análisis estático que se utilizan al buscar vulnerabilidades en el software. Usaremos el ejemplo de una vulnerabilidad simple, repasaremos cómo CodeQL podría detectarla y proporcionaremos ejemplos de cómo el público puede usar CodeQL para encontrar vulnerabilidades por sí mismo.

Antes de comenzar, es importante que se cumplan todos los requisitos previos para que puedas participar en el taller.

El taller está dividido en varias secciones y cada sección consta de ejercicios que se acumulan hasta llegar a la consulta final.
Para cada sección proporcionamos *pautas* que te ayudan a completar el ejercicio, proporcionándote referencias a las clases de QL y a los predicados de miembros que puedes usar.

### Resumen

En este taller buscaremos vulnerabilidades conocidas de *inyección de comandos* en [kohya_ss](https://securitylab.github.com/advisories/GHSL-2024-019_GHSL-2024-024_kohya_ss/). Estas vulnerabilidades pueden ocurrir cuando información controlada por un usuario llega a código de la aplicación que construye y ejecuta un comando de forma insegura. El comando construido de forma insegura a partir de la entrada del usuario puede modificarse para realizar acciones no deseadas, como la ejecución arbitraria de comandos o la divulgación de información sensible.

Las inyecciones de comandos tratadas en este taller son [CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027](https://securitylab.github.com/advisories/GHSL-2024-019_GHSL-2024-024_kohya_ss/).

## Teoría

### Fuentes y sumideros

Piensa en una de las vulnerabilidades más conocidas: la inyección de comandos. Ocurre si la entrada del usuario se usa en funciones que permiten ejecutar comandos en una shell directamente en el servidor. Permite a un atacante ejecutar comandos del sistema operativo (SO) en el servidor que ejecuta una aplicación y, por lo general, comprometer por completo la aplicación y sus datos.

La causa principal de las vulnerabilidades de inyección es que la entrada no confiable controlada por el usuario se use en funciones sensibles o peligrosas del programa. Para representar esto en el análisis estático, usamos términos como flujo de datos, fuentes y sumideros.

La entrada del usuario generalmente proviene de los puntos de entrada de una aplicación: el origen de los datos. Estos incluyen parámetros en métodos HTTP, como GET y POST, o argumentos de línea de comandos de un programa. Estos se denominan “**fuentes**”.

Continuando con nuestra inyección de comandos, un ejemplo de una función peligrosa que no debería llamarse con datos no confiables sin sanitizar podría ser `os.system`. Estas funciones peligrosas se denominan “**sumideros**”. Ten en cuenta que el hecho de que una función sea potencialmente peligrosa no significa que sea inmediatamente una vulnerabilidad explotable y deba eliminarse. Muchos sumideros tienen formas de usarse de manera segura. Otros ejemplos de sumideros que no deberían usarse con entrada de usuario son `MySQLCursor.execute()` de la librería MySQLdb en Python (que causa inyección SQL) o la función integrada `eval()` de Python, que evalúa expresiones arbitrarias (causando inyección de código).

Para que exista una vulnerabilidad, la entrada insegura controlada por el usuario debe usarse sin una sanitización o validación de entrada adecuada en una función peligrosa. En otras palabras, tiene que haber una ruta de código entre la fuente y el sumidero; en ese caso decimos que los datos fluyen de una fuente a un sumidero: hay un “**flujo de datos**” de la fuente al sumidero.

<img src="https://assets.kitploit.com/production/public/readmes/33098/ff60a1649737805a71bd27710209dba66203a77159cc72ae435c165353e56491.png">

### Hoja de referencia de CodeQL

La estructura básica de la consulta```codeql
import python

from <type> <name> 		//variables used in the query

where <conditions for variables>

select <output>			//results, referring to the variables

Buscar referencias a llamadas a `os.system()````codeql import python import semmle.python.ApiGraphs

from API::CallNode call where call = API::moduleImport("os") .getMember("system") .getACall() select call, "Call to os.system"

root@kitploit:~
Busca referencias a llamadas a `os.system()`, esta vez con un predicado```codeql
predicate isOsSystemSink(API::CallNode call) {
	call = API::moduleImport("os")
	.getMember("system").getACall()
  }


from API::CallNode call
where isOsSystemSink(call)
select call, "Call to os.system"

Buscar referencias a llamadas a os.system(), esta vez con una clase```codeql class OsSystemSink extends API::CallNode { OsSystemSink() { this = API::moduleImport("os") .getMember("system").getACall() } }

from API::CallNode call where call instanceof OsSystemSink select call, "Call to os.system"

root@kitploit:~
Busca referencias a llamadas a `os.system()`, esta vez con una clase.
Especifica que el tipo con el que empezamos es `OsSystemSink````codeql
class OsSystemSink extends API::CallNode {
  OsSystemSink() {
    this = API::moduleImport("os")
    .getMember("system").getACall()
	}
}


from OsSystemSink s
select s, "Call to os.system"

Taller parte I - base de datos de prueba

En este taller vamos a encontrar inyecciones de comandos, en las que la entrada del usuario termina en una llamada a os.system.

En la primera parte del taller, escribiremos consultas de CodeQL para encontrar fuentes y sumideros, llamadas a os.system, en una base de código intencionalmente vulnerable. En la segunda parte del taller, usaremos esas consultas para encontrar una inyección de comandos desde una fuente hasta un sumidero en un software de código abierto, kohya_ss v22.6.1.

Con la consulta de CodeQL que escribamos, podremos encontrar inyecciones de comandos como la siguiente.

La entrada del usuario proviene de un componente interactivo de Gradio (framework web para aplicaciones de aprendizaje automático) gr.Textbox en #1. gr.Button.click en #2 vincula el clic del botón a la función execute_cmd, pasando los valores de folder. Eso significa que cuando se hace clic en gr.Button, folder se pasa a execute_cmd, donde folder se concatena en un comando y se ejecuta en el sistema en una llamada a os.system en #3.```python import gradio as gr import os

def execute_cmd(folder): cmd = f"python caption.py --dir={folder}" os.system(cmd) #3

with gr.Blocks() as demo: gr.Markdown("Create caption files for images in a directory") with gr.Row(): folder = gr.Textbox(placeholder="Directory to caption") #1 logs = gr.Checkbox(label="Add verbose logs")

root@kitploit:~
btn = gr.Button("Run")
btn.click(fn=execute_cmd, inputs=[folder]) #2

if name == "main": demo.launch(debug=True)

root@kitploit:~
También notarás otro ejemplo de inyección de comandos en el taller, en una aplicación creada con el framework `Flask`. En este caso, la entrada del usuario proviene de un parámetro GET de una petición de Flask (popular framework web en Python), que se almacena en la variable `files` (ver #1). A continuación, `files` se pasa a la llamada de `os.system` y se concatena con `ls`, lo que provoca una inyección de comandos (ver #2).```python
import os
from flask import Flask, request

app = Flask(__name__)

@app.route("/command1")
def command_injection1():
    files = request.args.get('files', '')   #1
    os.system("ls " + files)                #2

Empezaremos construyendo gradualmente una consulta para detectar llamadas a os.system y, después, una consulta para fuentes.

1. Encontrar todas las llamadas a funciones de bibliotecas externas

Podemos encontrar todas las llamadas a funciones de bibliotecas externas (no definidas en el código base) utilizando el módulo ApiGraphs de CodeQL.

Utiliza la plantilla siguiente:```codeql import python import semmle.python.ApiGraphs

from //TODO: fill me in. Start typing API:: and press Ctrl+Space to see a list of available types. Name your variable call select //TODO: fill me in

root@kitploit:~
Haga clic derecho en el área de archivos y elija "CodeQL: Run Query on Selected Database" para ejecutar la consulta.

<details>
<summary>Directrices</summary>

- En la cláusula `from`, comience con `API::` y presione `Ctrl + Space` para ver los tipos disponibles en el módulo API Graphs.
- Una llamada se representa mediante el tipo `API::CallNode`. Cree una variable con ese tipo y el nombre `call`.
- Para limitar los resultados solo a las llamadas en la carpeta raíz de la aplicación (llamada `test-app`), agregue una cláusula `where` con la condición `where call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")`.

</details>
<details>
<summary>Solución</summary>```codeql
import python
import semmle.python.ApiGraphs

from API::CallNode call
where call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call, "A call"

2. Encontrar todas las llamadas a os.system

Directrices
  • En la cláusula from, crea una variable call del tipo API::CallNode.
  • En la cláusula where, usa el operador de igualdad = para afirmar que call es igual a las llamadas a os.system. Usa el operador lógico and para especificar varias condiciones.
  • Para encontrar nodos correspondientes a la librería os, usa el método API::moduleImport() con os como argumento. Para acceder a la función system de la librería os, usa el predicado getMember() sobre . Por último, obtén cualquier llamada a con el predicado .

3. Encontrar los primeros argumentos de las llamadas a os.system

Queremos encontrar los primeros argumentos de las llamadas a os.system, para luego poder ver si alguna entrada del usuario fluye hacia los primeros argumentos (es decir, hacia el comando que se ejecutará).

Pautas
  • Completa la plantilla:```codeql import python import semmle.python.ApiGraphs

from API::CallNode call where call = API::moduleImport("os").getMember("system").getACall() and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*") select call // TODO: fill me in. Type a dot . right after call and press Ctrl+Space to see available predicates.

root@kitploit:~
</details>
<details>
<summary>Solución</summary>```codeql
import python
import semmle.python.ApiGraphs

from API::CallNode call
where call = API::moduleImport("os").getMember("system").getACall() and
call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call.getArg(0), "First argument of an `os.system` call"

4. Transforma tu consulta que encuentra las llamadas a os.system en una clase de CodeQL

classes en CodeQL se pueden usar para encapsular porciones reutilizables de lógica. Las clases representan conjuntos únicos de valores, y también pueden incluir operaciones (conocidas como predicados miembro) específicas de ese conjunto de valores. Ya has visto numerosos ejemplos de clases de CodeQL (API::CallNode) y predicados miembro (getLocation() etc.)

Pautas
  • Para crear un nuevo tipo, tenemos que extender un supertipo, aquí API::CallNode, darle un nombre y un predicado característico con el mismo nombre. Llamaremos a nuestra clase, OsSystemSink.

Rellena la plantilla:```codeql import python import semmle.python.ApiGraphs

class OsSystemSink extends API::CallNode { OsSystemSink() { //TODO: fill me in } }

from API::CallNode call where // TODO: fill me in and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*") select call.getArg(0), "Call to os.system"

root@kitploit:~
- Usa la palabra clave mágica `this`, que se refiere a las instancias de los nodos de llamada (`API::CallNode`s) que estamos describiendo en la clase. Usa `this` para encontrar las llamadas a `os.system` de la misma manera que hiciste antes con `API::moduleImport`.
- Cambia la cláusula `where` para que tu variable `call` sea un `instanceof` de tu nueva clase `OsSystemSink`.

</details>
<details>
<summary>Solución</summary>```codeql
import python
import semmle.python.ApiGraphs

class OsSystemSink extends API::CallNode {
	OsSystemSink() {
		this = API::moduleImport("os").getMember("system").getACall()
	}
}


from API::CallNode call
where call instanceof OsSystemSink
and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call.getArg(0), "First argument of an `os.system` call"

5. Encuentra todas las fuentes con la clase RemoteFlowSource

Ahora pasamos a encontrar fuentes.

La mayoría de las fuentes ya están modeladas en CodeQL y tienen el tipo RemoteFlowSource. Podemos usar el tipo para encontrar cualquier fuente en una base de código.

Directrices
  • Importa semmle.python.dataflow.new.RemoteFlowSources para usar el tipo RemoteFlowSource.
  • En la cláusula from, pulsa Ctrl + Espacio para ver todos los tipos disponibles.

Completa la plantilla:```codeql import python import semmle.python.dataflow.new.RemoteFlowSources

from //TODO: fill me in where //TODO: fill me in select //TODO: fill me in

root@kitploit:~
</details>
<details>
<summary>Solución</summary>```codeql
import python
import semmle.python.dataflow.new.RemoteFlowSources

from RemoteFlowSource rfs
where rfs.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select rfs

Taller parte II - encontrar inyecciones de comandos en kohya_ss

Kohya_ss es una GUI para los scripts de Stable Diffusion de Kohya para entrenamiento, generación y utilidades para Stable Diffusion.

En la segunda parte del taller, vamos a cambiar la base de código sobre la que estamos haciendo consultas a la de kohya_ss y a encontrar los flujos de datos desde las fuentes hasta los sumideros en kohya_ss, que conducen a inyecciones de comandos: CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027

Antes de empezar con el siguiente ejercicio:

  • Ve a la pestaña CodeQL en VSCode, a la sección Databases, haz clic en "Choose Database from Archive" y selecciona el archivo kohya_ss-db.zip en la raíz del repositorio. Debería aparecer una marca de verificación. Esto seleccionará la base de datos de CodeQL en la que estás trabajando.

6. Encuentra los flujos de datos desde las fuentes hasta el primer argumento de las llamadas a os.system

Pautas
  • Usa la plantilla de abajo y ten en cuenta:
  • en el predicado isSource, refina la variable source para que sea del tipo RemoteFlowSource.
  • en el predicado isSink, refina la variable sink para que sea el primer argumento de una llamada a os.system. Hazlo usando el mecanismo exists y tu clase OsSystemSink.
    • exists es un mecanismo para introducir variables temporales con un ámbito restringido. Puedes pensar en cada una como su propio from-where-select. En este caso, usa exists para introducir la variable call con tipo OsSystemSink y luego refina sink para que sea el primer argumento de .```codeql /**

Ejercicios adicionales, si el tiempo lo permite

7. Consulta el código fuente con las consultas predeterminadas

Las consultas de CodeQL para Python se encuentran en la carpeta ql/python/ql/src/Security. Ya existen consultas para las vulnerabilidades más populares: inyección SQL, inyección de comandos, inyección de código, etc. Ejecuta la consulta de inyección SQL (CWE-089) en la base de datos de prueba (tendrás que seleccionarla en la extensión CodeQL > Databases. Observa la marca de verificación).

💡 Esto es muy interesante para los investigadores de seguridad: con las consultas predeterminadas podemos hacernos una idea general de qué vulnerabilidades potenciales podrían existir en un proyecto determinado.

8. Ejecuta tus propias consultas mediante el análisis de variantes multi-repositorio (MRVA)

El poder de CodeQL radica en la capacidad de reutilizar las consultas y los modelos de CodeQL para ejecutarlos en cualquier base de código escrita en el mismo lenguaje. Podemos ejecutar consultas de CodeQL en hasta 1000 repositorios a la vez mediante el análisis de variantes multi-repositorio (MRVA). Los proyectos deben estar alojados en GitHub.

💡 Esto es muy interesante para los investigadores de seguridad: si has encontrado un sink o una fuente potencialmente peligrosos, puedes añadirlo a CodeQL (o ejecutarlo como consulta) y realizar tu investigación contra mil repositorios a la vez.

  • Sigue la configuración en la documentación.
  • Ten en cuenta que MRVA se ejecuta mediante flujos de trabajo de GitHub Actions. Los flujos de trabajo de Actions son gratuitos en los repositorios públicos y de pago en los privados.
  • Después de la configuración, haz clic con el botón derecho y elige "CodeQL: Run Variant Analysis".

Comentarios finales

Hoy has aprendido a explorar una base de código con CodeQL y a incorporar CodeQL en tu propio flujo de trabajo de investigación de seguridad.

Consulta estos recursos si quieres saber más sobre:

  • análisis estático y cómo funciona:
    • CodeQL de cero a héroe, parte 1: los fundamentos del análisis estático para la investigación de vulnerabilidades.
  • fundamentos del uso de CodeQL y su lenguaje de consultas:
    • CodeQL de cero a héroe, parte 2: primeros pasos con CodeQL.
  • investigación de seguridad con CodeQL:
    • CodeQL de cero a héroe, parte 3: investigación de seguridad.
  • Cómo modelar CodeQL para un framework web con el ejemplo de Gradio:
    • CodeQL de cero a héroe, parte 4: estudio de caso de Gradio.
  • Depurar por qué una consulta podría no estar funcionando:
    • CodeQL de cero a héroe, parte 5: depuración de consultas

Si terminas encontrando una vulnerabilidad usando CodeQL, no dudes en añadirla al CodeQL Wall of Fame.

Descargar herramienta
API::moduleImport()
os.system
getACall()

Completa la plantilla:```codeql import python import semmle.python.ApiGraphs

from API::CallNode call where call //TODO: fill me in and call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*") select call, "Call to os.system"

root@kitploit:~
</details>
<details>
<summary>Solución</summary>```codeql
import python
import semmle.python.ApiGraphs

from API::CallNode call
where call = API::moduleImport("os").getMember("system").getACall() and
call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")
select call, "Call to `os.system`"
call
  • @name Command injection in os.system sink
  • @kind path-problem
  • @id codeql-ws/dataflow-query */

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

//TODO: add previous class definition here

private module MyConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { // TODO: fill me in }

predicate isSink(DataFlow::Node sink) { // TODO: fill me in. Use the exists mechanism exists( | sink = ... ) } }

module MyFlow = TaintTracking::Global;

from MyFlow::PathNode source, MyFlow::PathNode sink where MyFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Command injection"

root@kitploit:~
</details>
<details>
<summary>Solución</summary>```codeql
/**
 * @name Command injection in os.system sink
 * @kind path-problem
 * @id codeql-ws/dataflow-query
 */

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

class OsSystemSink extends API::CallNode {
	OsSystemSink() {
		this = API::moduleImport("os").getMember("system").getACall()
	}
}

private module MyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
	source instanceof RemoteFlowSource
}

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

module MyFlow = TaintTracking::Global<MyConfig>;

from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Command injection"