Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
codeql-workshop — Machen Sie erste Schritte in CodeQL für Python, indem Sie eine Abfrage schreiben, um CVE-2024-32022 zu finden | Kitploit
Tools/GitHubGitHub/sylwia-budzynska/codeql-workshop
Statische AnalyseSchwachstellenanalyseCode-AnalyseLernen & BildungKuratierte RessourcenLernpfade & KurseLabs & Praxis
GitHubsylwia-budzynska/codeql-workshop

codeql-workshop

Machen Sie erste Schritte in CodeQL für Python, indem Sie eine Abfrage schreiben, um CVE-2024-32022 zu finden

Repository anzeigen
128vor 1 MonatNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Schwachstellen mit CodeQL finden

Original-Workshop von Sylwia Budzynska

Voraussetzungen • Ressourcen • Workshop

  • Für wen ist das gedacht: Sicherheitsingenieure, Sicherheitsforscher, Entwickler.
  • Was Sie lernen werden: Lernen Sie, wie Sie CodeQL zur Code-Erkundung und zum Auffinden von Sicherheitsproblemen einsetzen.
  • Was Sie erstellen werden: Erstellen Sie eine CodeQL-Abfrage basierend auf einer Sicherheitswarnung, um eine Befehlseinschleusung zu finden.

📣 Voraussetzungen

Sie haben die Wahl zwischen zwei Optionen, um die Workshop-Übungen durchzuführen:

  • Option A: Lokale Installation (Verwendung von VS Code – CodeQL wird lokal auf Ihrem Rechner ausgeführt)
  • Option B: GitHub Codespace (Verwendung eines Browsers oder VS Code – CodeQL wird remote auf einem Linux-basierten GitHub Codespace in der Cloud ausgeführt)

Option A: Lokale Installation

Verwenden Sie eine lokale CodeQL-Installation, um an den Workshop-Übungen zu arbeiten.

Voraussetzungen

  • Visual Studio Code (VS Code) und git installiert auf Ihrem lokalen Rechner.

Anleitung

  1. Installieren Sie die VS Code-Erweiterung für CodeQL
  2. Führen Sie im Terminal aus:```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. In VS Code: Datei -> **Arbeitsbereich aus Datei öffnen...** `vscode-codeql-starter.code-workspace`
4. Fahren Sie fort mit [Auswählen einer CodeQL-Datenbank](#select-codeql-database)
5. Dann [Testen Sie Ihre Installation](#test-your-installation)

### Option B: GitHub Codespace

Verwenden Sie einen remote GitHub Codespace, um an den Workshop-Übungen zu arbeiten.

#### Voraussetzungen

* GitHub-Konto ([kostenlos anmelden](https://github.com/))
* Browser (Sie können den gesamten Workshop in einem Browser durchführen – dies ist der schnellste Setup) oder [Visual Studio Code](https://code.visualstudio.com/download) (VS Code) mit der [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces)-Erweiterung, die auf Ihrem lokalen Rechner installiert ist.

Hinweis: Die ersten 120 Stunden pro Kern der Codespace-Nutzung sind pro Monat kostenlos. Wir verwenden für diesen Workshop einen Codespace mit 4 Kernen, da 4 Kerne das derzeitige Maximum für kostenlose Konten sind. (Wenn Sie ein Pro-Konto haben, empfehlen wir, auf eine 8-Kern-Maschine umzusteigen.)

#### Anleitung

1. Melden Sie sich bei Ihrem [GitHub](https://github.com/login)-Konto an
2. Gehen Sie zum Repository https://github.com/sylwia-budzynska/codeql-workshop
3. Klicken Sie auf Code -> Codespaces
4. Klicken Sie auf das Pluszeichen (+), um einen neuen Codespace zu erstellen.

<img src="https://assets.kitploit.com/production/public/readmes/33098/c86e537f9e7891fb6bdb5da727cae5b6ad0b2c9ac94f67854d48296f2dad89cb.png"  width="439" alt="Screenshot: Codespace erstellen, klicken Sie auf Plus">

VS Code wird in Ihrem Browser gestartet und ein remote Codespace wird erstellt. Dies kann einige Minuten dauern.
Wenn Sie aufgefordert werden, den Arbeitsbereich `vscode-codeql-starter.code-workspace` zu öffnen, klicken Sie auf "Arbeitsbereich öffnen".

5. Wenn Sie VS Code lokal verwenden möchten, drücken Sie die Drei-Linien-Taste oben links und wählen Sie "Open VS Code Desktop". Die Option kann einige Minuten dauern, bis sie erscheint.

<img src="https://assets.kitploit.com/production/public/readmes/33098/f2c8c2fe6da80142344b17c208da31a23c3fa68a3917a124f0e2f7871b6a20f7.png" width="300" alt="Screenshot: Drücken Sie die Drei-Linien-Taste und VS Code Desktop öffnen">

6. Fahren Sie fort mit [Auswählen einer CodeQL-Datenbank](#select-codeql-database)
7. Dann [Testen Sie Ihre Installation](#test-your-installation)

Sie können Ihre Codespaces unter [github.com/codespaces](https://github.com/codespaces) einsehen. Der Codespace schaltet sich nach einigen Stunden der Nichtbenutzung von selbst aus. Um sicherzustellen, dass Sie keine zusätzlichen Stunden der 120 kostenlosen Stunden verbrauchen, denken Sie daran, nach dem Workshop zu [github.com/codespaces](https://github.com/codespaces) > drei Punkte > "Codespace stoppen" zu gehen.

#### Fehlerbehebung bei der Installation

Falls Fehler wie diese auftreten:
* `Failed to run query: Could not resolve library path for [..]`
* `Could not resolve module [..]`
* `Could not resolve type [..]`

Haben Sie sehr wahrscheinlich vergessen, die Git-Submodule (nämlich das ql-Repository) zu klonen. Führen Sie zur Behebung `git submodule init && git submodule update --recursive` aus.

### CodeQL-Datenbank auswählen

1. Stellen Sie sicher, dass der Arbeitsbereich `vscode-codeql-starter.code-workspace` in VS Code geöffnet ist.
2. Klicken Sie in der linken Tab-Leiste auf das "QL"-Symbol, um zur CodeQL-Ansicht zu gelangen.
3. Klicken Sie auf "Datenbank aus Archiv auswählen" und wählen Sie die Datei `test-app-db.zip` im Stammverzeichnis des Repositorys.
   Hinweis: Möglicherweise tritt an dieser Stelle ein Fehler in VSCode mit einer Pop-up-Meldung auf, die Sie auffordert, die CodeQL CLI zu installieren. Wenn Sie dieser Installation zustimmen, sollte das Problem behoben werden. Nachdem die CLI-Installation abgeschlossen ist, sollten Sie die obige Datenbankauswahl abschließen können.
   <img src="https://assets.kitploit.com/production/public/readmes/33098/65cc5790b8b49113623bc9a9b34a1be61575b05bea2428c46f83115e2271148b.png"  alt="Screenshot: VSCode Fehlermeldung bzgl. CodeQL">
   <img src="https://assets.kitploit.com/production/public/readmes/33098/c3bf9c304d9c1f6199f591c9bcbf6e446ee4f5388ab209e30887326698129f84.png"  alt="Screenshot: VSCode installiert CodeQL CLI">

### Testen Sie Ihre Installation

#### Voraussetzungen

Stellen Sie sicher, dass die zuvor ausgewählte CodeQL-Datenbank in der CodeQL-Ansicht ausgewählt ist. (Klicken Sie auf "Auswählen", falls nicht)

Wenn die Datenbank ausgewählt ist, sollte dies wie folgt aussehen (beachten Sie das Häkchen):

<img src="https://assets.kitploit.com/production/public/readmes/33098/fee6e47c0d9b0754c7ac9e29e2f0b3a721093aa5ce882615b3839a99f4862506.png"  alt="Screenshot: CodeQL-Datenbank ausgewählt">

#### Anleitung

1. Gehen Sie in VS Code zum Arbeitsbereichsordner: `codeql-custom-queries-python`
2. Erstellen Sie eine neue Datei `test.ql`
3. Fügen Sie den folgenden Inhalt hinzu: `select "Hello World!"`
4. Speichern Sie die Datei, klicken Sie mit der rechten Maustaste in den Dateibereich und wählen Sie "CodeQL: Abfrage auf ausgewählter Datenbank ausführen"
5. Es sollte ein neuer Tab mit dem Ergebnis "Hello World!" geöffnet werden.

## :books: Ressourcen

- [QL-Tutorials](https://codeql.github.com/docs/writing-codeql-queries/ql-tutorials/)
- [CodeQL für Python – Sprachleitfaden](https://codeql.github.com/docs/codeql-language-guides/codeql-for-python/)
- [CodeQL-Dokumentation](https://codeql.github.com/docs/)
- [QL-Sprachreferenz](https://codeql.github.com/docs/ql-language-reference/)
- [CodeQL-Bibliothek für Python](https://codeql.github.com/codeql-standard-libraries/python/)
- [Grundlegende Abfrage für Python-Code](https://codeql.github.com/docs/codeql-language-guides/basic-query-for-python-code/)
- [QL-Klassen](https://codeql.github.com/docs/ql-language-reference/types/#classes)
- [CodeQL von Null zu Held Teil 1: Die Grundlagen der statischen Analyse für die Schwachstellenforschung](https://github.blog/2023-03-31-codeql-zero-to-hero-part-1-the-fundamentals-of-static-analysis-for-vulnerability-research/)
- [CodeQL von Null zu Held Teil 2: Erste Schritte mit CodeQL](https://github.blog/2023-06-15-codeql-zero-to-hero-part-2-getting-started-with-codeql/)
- [CodeQL von Null zu Held Teil 3: Sicherheitsforschung](https://github.blog/2024-04-29-codeql-zero-to-hero-part-3-security-research-with-codeql/)
- [CodeQL von Null zu Held Teil 4: Gradio-Fallstudie](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-4-gradio-framework-case-study/)
- [CodeQL von Null zu Held Teil 5: Debugging von Abfragen](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-5-debugging-queries/)

## Workshop

Willkommen zum Workshop "Schwachstellen mit CodeQL finden"!

Diese Sitzung führt in die Grundlagen der Sicherheitsforschung und statischen Analyse ein, die bei der Suche nach Schwachstellen in Software verwendet werden. Wir werden am Beispiel einer einfachen Schwachstelle demonstrieren, wie CodeQL sie erkennen könnte, und Beispiele geben, wie das Publikum CodeQL selbst zur Schwachstellensuche einsetzen kann.

Bevor wir beginnen, ist es wichtig, dass alle Voraussetzungen erfüllt sind, damit Sie am Workshop teilnehmen können.

Der Workshop ist in mehrere Abschnitte unterteilt, und jeder Abschnitt besteht aus Übungen, die zur endgültigen Abfrage hinführen.
Für jeden Abschnitt stellen wir *Richtlinien* bereit, die Ihnen helfen, die Übung zu absolvieren, indem wir auf QL-Klassen und Member-Prädikate verweisen, die Sie verwenden können.

### Überblick

In diesem Workshop werden wir nach einer bekannten *Befehlsinjektions-Schwachstelle* in [kohya_ss](https://securitylab.github.com/advisories/GHSL-2024-019_GHSL-2024-024_kohya_ss/) suchen. Solche Schwachstellen können auftreten, wenn von einem Benutzer kontrollierte Informationen in Anwendungscode gelangen, der unsicher einen Befehl konstruiert und ausführt. Der unsicher aus Benutzereingaben konstruierte Befehl kann so umgeschrieben werden, dass unbeabsichtigte Aktionen wie die Ausführung beliebiger Befehle oder die Offenlegung sensibler Informationen möglich sind.

Die in diesem Workshop behandelten Befehlsinjektionen sind [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/).

## Theorie

### Quellen und Senken

Denken Sie an eine der bekanntesten Schwachstellen – Befehlsinjektion. Sie tritt auf, wenn Benutzereingaben in Funktionen verwendet werden, die es erlauben, Befehle in einer Shell direkt auf dem Server auszuführen. Ein Angreifer kann dadurch Betriebssystembefehle auf dem Server ausführen, auf dem eine Anwendung läuft, und typischerweise die Anwendung und ihre Daten vollständig kompromittieren.

Die Hauptursache für Injektionsschwachstellen sind nicht vertrauenswürdige, vom Benutzer kontrollierte Eingaben, die in sensiblen oder gefährlichen Funktionen des Programms verwendet werden. Um dies in der statischen Analyse darzustellen, verwenden wir Begriffe wie Datenfluss, Quellen und Senken.

Benutzereingaben stammen im Allgemeinen von Einstiegspunkten in eine Anwendung – dem Ursprung der Daten. Dazu gehören Parameter in HTTP-Methoden wie GET und POST oder Befehlszeilenargumente eines Programms. Diese werden als "**Quellen**" bezeichnet.

Um bei unserer Befehlsinjektion zu bleiben: Ein Beispiel für eine gefährliche Funktion, die nicht mit unsauberen, nicht vertrauenswürdigen Daten aufgerufen werden sollte, ist `os.system`. Diese gefährlichen Funktionen werden "**Senken**" genannt. Beachten Sie, dass nur weil eine Funktion potenziell gefährlich ist, dies nicht bedeutet, dass es sich sofort um eine ausnutzbare Schwachstelle handelt, die entfernt werden muss. Viele Senken haben Möglichkeiten, sie sicher zu verwenden. Weitere Beispiele für Senken, die nicht mit Benutzereingaben verwendet werden sollten, sind `MySQLCursor.execute()` aus der MySQLdb-Bibliothek in Python (was SQL-Injection verursacht) oder Pythons eingebaute `eval()`-Funktion, die beliebige Ausdrücke auswertet (was Code-Injection verursacht).

Damit eine Schwachstelle vorhanden ist, muss die unsichere, vom Benutzer kontrollierte Eingabe ohne ordnungsgemäße Bereinigung oder Eingabevalidierung in einer gefährlichen Funktion verwendet werden. Mit anderen Worten: Es muss einen Codepfad zwischen der Quelle und der Senke geben; in diesem Fall sagen wir, dass Daten von einer Quelle zu einer Senke fließen – es gibt einen "**Datenfluss**" von der Quelle zur Senke.

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

### CodeQL-Spickzettel
Die grundlegende Abfragestruktur```codeql
import python

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

where <conditions for variables>

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

Finde Verweise auf os.system() Aufrufe```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:~
Finde Verweise auf `os.system()`-Aufrufe, diesmal mit einem Prädikat```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"

Finde Verweise auf os.system()-Aufrufe, diesmal mit einer Klasse.```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:~
Finde Verweise auf `os.system()`-Aufrufe, diesmal mit einer Klasse.
Geben Sie an, dass der Typ, mit dem wir beginnen, `OsSystemSink` ist.```codeql
class OsSystemSink extends API::CallNode {
  OsSystemSink() {
    this = API::moduleImport("os")
    .getMember("system").getACall()
	}
}


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

Workshop Teil I - Testdatenbank

In diesem Workshop werden wir Befehlseinschleusungen finden, bei denen Benutzereingaben in einem os.system-Aufruf landen.

Im ersten Teil des Workshops schreiben wir CodeQL-Abfragen, um Quellen und Senken zu finden, also os.system-Aufrufe, in einer absichtlich verwundbaren Codebasis. Im zweiten Teil des Workshops werden wir diese Abfragen nutzen, um eine Befehlseinschleusung von einer Quelle zu einer Senke in einer Open-Source-Software, kohya_ss v22.6.1, zu finden.

Mit der CodeQL-Abfrage, die wir schreiben, werden wir in der Lage sein, Befehlseinschleusungen wie die untenstehende zu finden.

Die Benutzereingabe stammt von einer interaktiven Gradio-Komponente (Web-Framework für maschinelle Lernanwendungen) gr.Textbox bei #1. gr.Button.click bei #2 bindet den Button-Klick an die Funktion execute_cmd und übergibt die Werte aus folder. Das bedeutet, wenn der gr.Button geklickt wird, wird folder an execute_cmd übergeben, wo folder in einen Befehl verkettet und in einem os.system-Aufruf bei #3 ausgeführt wird.```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:~
Sie werden auch ein weiteres Beispiel für eine Befehlseinschleusung im Workshop bemerken, in einer App, die mit dem `Flask`-Framework erstellt wurde. In diesem Fall stammt die Benutzereingabe aus einem GET-Parameter einer Flask-Anfrage (einem beliebten Web-Framework in Python), die in der Variablen `files` gespeichert ist (siehe #1). `files` wird dann an den `os.system`-Aufruf übergeben und mit `ls` verkettet, was zu einer Befehlseinschleusung führt (siehe #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

Wir beginnen damit, schrittweise eine Abfrage zur Erkennung von os.system-Aufrufen und anschließend eine Abfrage für Quellen aufzubauen.

1. Alle Aufrufe von Funktionen aus externen Bibliotheken finden

Wir können alle Aufrufe von Funktionen aus externen Bibliotheken (die nicht in der Codebasis definiert sind) mit Hilfe des CodeQL-Moduls ApiGraphs finden.

Verwenden Sie folgende Vorlage:```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:~
Right click in the file area and choose "CodeQL: Run Query on Selected Database" to run the query.

<details>
<summary>Richtlinien</summary>

- Verwenden Sie in der `from`-Klausel `API::` und drücken Sie `Ctrl + Space`, um die verfügbaren Typen im API-Graphs-Modul anzuzeigen.
- Ein Aufruf wird durch den Typ `API::CallNode` dargestellt. Erstellen Sie eine Variable mit diesem Typ und dem Namen `call`.
- Um die Ergebnisse nur auf Aufrufe im Stammverzeichnis der Anwendung (genannt `test-app`) zu beschränken, fügen Sie eine `where`-Klausel mit der Bedingung `where call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")` hinzu.

</details>
<details>
<summary>Lösung</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. Alle Aufrufe von os.system finden

Richtlinien
  • Erstellen Sie in der from-Klausel eine call-Variable vom Typ API::CallNode.
  • Verwenden Sie in der where-Klausel den Gleichheitsoperator =, um zu bestätigen, dass call den os.system-Aufrufen entspricht. Verwenden Sie den logischen Operator and, um mehrere Bedingungen zu spezifizieren.
  • Um Knoten zu finden, die der os-Bibliothek entsprechen, verwenden Sie die Methode API::moduleImport() mit os als Argument. Um auf die system-Funktion der os-Bibliothek zuzugreifen, verwenden Sie das Prädikat getMember() auf . Rufen Sie schließlich alle -Aufrufe mit dem Prädikat ab.

3. Finden Sie die ersten Argumente von Aufrufen an os.system

Wir möchten die ersten Argumente von os.system-Aufrufen finden, um später zu sehen, ob Benutzereingaben in die ersten Argumente (also in den auszuführenden Befehl) fließen.

Richtlinien
  • Füllen Sie die Vorlage aus:```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>Lösung</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. Transformieren Sie Ihre Abfrage, die die Aufrufe von os.system findet, in eine CodeQL-Klasse

classes in CodeQL können verwendet werden, um wiederverwendbare Logikteile zu kapseln. Klassen repräsentieren einzelne Wertemengen und können auch Operationen (sogenannte Member-Prädikate) enthalten, die für diese Wertemenge spezifisch sind. Sie haben bereits zahlreiche Beispiele von CodeQL-Klassen (API::CallNode) und Member-Prädikaten (getLocation() usw.) gesehen.

Richtlinien
  • Um einen neuen Typ zu erstellen, müssen wir einen Supertyp erweitern – hier API::CallNode – ihm einen Namen und ein charakteristisches Prädikat mit demselben Namen geben. Wir werden unsere Klasse OsSystemSink nennen.

Füllen Sie die Vorlage aus:

```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:~
- Verwenden Sie das magische `this`-Schlüsselwort, das sich auf die Instanzen der Aufrufknoten (`API::CallNode`s) bezieht, die wir in der Klasse beschreiben. Verwenden Sie `this`, um die Aufrufe von `os.system` auf die gleiche Weise zu finden, wie Sie es zuvor mit `API::moduleImport` getan haben.
- Ändern Sie die `where`-Klausel, um Ihre `call`-Variable zu einem `instanceof` Ihrer neuen `OsSystemSink`-Klasse zu machen.```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. Finden Sie alle Quellen mit der RemoteFlowSource-Klasse

Nun wechseln wir zum Auffinden von Quellen.

Die meisten Quellen sind bereits modelliert und in CodeQL vorhanden und haben den Typ RemoteFlowSource. Wir können diesen Typ verwenden, um alle Quellen in einer Codebasis zu finden.

Richtlinien
  • Importieren Sie semmle.python.dataflow.new.RemoteFlowSources, um den RemoteFlowSource-Typ zu verwenden.
  • Drücken Sie in der from-Klausel Strg + Leertaste, um alle verfügbaren Typen anzuzeigen.

Füllen Sie die Vorlage aus:```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>Lösung</summary>```codeql
import python
import semmle.python.dataflow.new.RemoteFlowSources

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

Workshop Teil II – Befehlsinjektionen in kohya_ss finden

Kohya_ss ist eine GUI für Kohyas Stable-Diffusion-Skripte für Training, Generierung und Hilfsprogramme für Stable Diffusion.

Im zweiten Teil des Workshops wechseln wir die Codebasis, die wir abfragen, zu kohya_ss und finden die Datenflüsse von Quellen zu Senken in kohya_ss, die zu Befehlsinjektionen führen: CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027

Bevor Sie mit der nächsten Übung beginnen:

  • Gehen Sie zum CodeQL-Tab in VSCode, zum Abschnitt Databases, klicken Sie auf "Choose Database from Archive" und wählen Sie die Datei kohya_ss-db.zip im Stammverzeichnis des Repositorys aus. Es sollte ein Häkchen erscheinen. Dadurch wird die CodeQL-Datenbank ausgewählt, mit der Sie arbeiten.

6. Datenflüsse von Quellen zum ersten Argument von os.system-Aufrufen finden

Richtlinien
  • Verwenden Sie die folgende Vorlage und beachten Sie:
  • Im isSource-Prädikat verfeinern Sie die Variable source auf den Typ RemoteFlowSource.
  • Im isSink-Prädikat verfeinern Sie die Variable sink auf das erste Argument eines os.system-Aufrufs. Tun Sie dies mit dem exists-Mechanismus und Ihrer OsSystemSink-Klasse.
    • exists ist ein Mechanismus zur Einführung temporärer Variablen mit eingeschränktem Gültigkeitsbereich. Sie können ihn sich als ein eigenes from-where-select vorstellen. Verwenden Sie in diesem Fall exists, um die Variable call vom Typ OsSystemSink einzuführen, und verfeinern Sie dann sink auf das erste Argument von .```codeql /**

Bonus-Übungen, falls die Zeit reicht

7. Durchsuchen Sie die Codebasis mit den Standardabfragen

CodeQL-Abfragen für Python befinden sich im Ordner ql/python/ql/src/Security. Es gibt bereits Abfragen für die gängigsten Schwachstellen: SQL-Injection, Command-Injection, Code-Injection usw. Führen Sie die SQL-Injection-Abfrage (CWE-089) auf der Testdatenbank aus (Sie müssen sie in der CodeQL-Erweiterung > Datenbanken auswählen. Beachten Sie das Häkchen).

💡 Dies ist für Sicherheitsforscher sehr interessant – mit den Standardabfragen können wir einen allgemeinen Eindruck davon gewinnen, welche potenziellen Schwachstellen in einem bestimmten Projekt existieren könnten.

8. Führen Sie Ihre eigenen Abfragen mit der Multi-Repository-Variantenanalyse (MRVA) durch

Die Stärke von CodeQL liegt darin, die CodeQL-Abfragen und -Modelle wiederverwenden zu können, um sie auf beliebige Codebasen in derselben Sprache anzuwenden. Wir können CodeQL-Abfragen mit der Multi-Repository-Variantenanalyse (MRVA) gleichzeitig auf bis zu 1000 Repositorys ausführen. Die Projekte müssen auf GitHub gehostet sein.

💡 Dies ist für Sicherheitsforscher sehr interessant – wenn Sie eine potenziell gefährliche Senke oder Quelle gefunden haben, können Sie sie zu CodeQL hinzufügen (oder als Abfrage ausführen) und Ihre Forschung gleichzeitig an tausend Repositorys durchführen.

  • Folgen Sie der Einrichtung in der Dokumentation.
  • Beachten Sie, dass MRVA mit GitHub-Actions-Workflows ausgeführt wird. Actions-Workflows sind auf öffentlichen Repositorys kostenlos und auf privaten kostenpflichtig.
  • Klicken Sie nach der Einrichtung mit der rechten Maustaste und wählen Sie „CodeQL: Variantenanalyse ausführen“

Abschließende Bemerkungen

Heute haben Sie gelernt, wie Sie eine Codebasis mit CodeQL erkunden und CodeQL in Ihrem eigenen Sicherheitsforschungs-Workflow einsetzen können.

Sehen Sie sich diese Ressourcen an, wenn Sie mehr über folgende Themen erfahren möchten:

  • Statische Analyse und wie sie funktioniert:
    • CodeQL zero to hero Teil 1: Die Grundlagen der statischen Analyse für die Schwachstellenforschung.
  • Grundlagen der Verwendung von CodeQL und seiner Abfragesprache:
    • CodeQL zero to hero Teil 2: Erste Schritte mit CodeQL.
  • Sicherheitsforschung mit CodeQL:
    • CodeQL zero to hero Teil 3: Sicherheitsforschung.
  • Wie man CodeQL für ein Web-Framework am Beispiel von Gradio modelliert:
    • CodeQL zero to hero Teil 4: Gradio-Fallstudie.
  • Debugging, warum eine Abfrage möglicherweise nicht funktioniert:
    • CodeQL zero to hero Teil 5: Debugging von Abfragen

Wenn Sie mit CodeQL eine Schwachstelle finden, können Sie sie gerne der CodeQL Ruhmeshalle hinzufügen.

Tool herunterladen
API::moduleImport()
os.system
getACall()

Füllen Sie die Vorlage aus:```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>Lösung</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>Lösung</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"