Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
codeql-workshop — CVE-2024-32022を検出するクエリを作成して、Python向けCodeQLの最初の一歩を踏み出す | Kitploit
ツール/GitHubGitHub/sylwia-budzynska/codeql-workshop
静的分析脆弱性分析コード分析学習と教育厳選リソース学習パスとコースラボと実践
GitHubsylwia-budzynska/codeql-workshop

codeql-workshop

CVE-2024-32022を検出するクエリを作成して、Python向けCodeQLの最初の一歩を踏み出す

リポジトリを見る
1281ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CodeQL を使用した脆弱性の発見

元のワークショップ: Sylwia Budzynska

前提条件 • リソース • ワークショップ

  • 対象者: セキュリティエンジニア、セキュリティ研究者、開発者。
  • 学べること: コード探索とセキュリティ問題の発見に CodeQL を使用する方法を学びます。
  • 作成するもの: セキュリティアドバイザリに基づく CodeQL クエリを作成して、コマンドインジェクションを発見します。

📣 前提条件

ワークショップの演習を実行するには、次の2つのオプションから選択できます:

  • オプション A: ローカルインストール (VS Code を使用 - CodeQL はお使いのマシン上でローカルに実行されます)
  • オプション B: GitHub Codespace (ブラウザまたは VS Code を使用 - CodeQL はクラウド内の Linux ベースの GitHub Codespace 上でリモート実行されます)

オプション A: ローカルインストール

ローカルの CodeQL インストールを使用して、ワークショップの演習に取り組みます。

前提条件

  • Visual Studio Code (VS Code) と git がローカルマシンにインストールされていること。

手順

  1. VS Code 用 CodeQL 拡張機能 をインストールします。
  2. ターミナルで次を実行します:```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. VS Code で: ファイル -> **ワークスペースをファイルから開く...** を選択し、`vscode-codeql-starter.code-workspace` を開きます。
4. 次に [CodeQL データベースの選択](#select-codeql-database) に進みます。
5. その後 [インストールのテスト](#test-your-installation) を行います。

### オプション B: GitHub Codespace

リモートの GitHub Codespace を使用して、ワークショップの演習に取り組みます。

#### 前提条件

* GitHub アカウント ([無料登録](https://github.com/))
* ブラウザー(ワークショップ全体をブラウザーだけで行えます。これが最速のセットアップです)または、ローカルマシンに [GitHub Codespaces](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces) 拡張機能がインストールされた [Visual Studio Code](https://code.visualstudio.com/download) (VS Code)。

注: Codespace の使用は、コアあたり月間 120 時間まで無料です。このワークショップでは、無料アカウントの現在の最大コア数である 4 コアの Codespace を使用します。(Pro アカウントをお持ちの場合は、8 コアのマシンに切り替えることをお勧めします。)

#### 手順

1. [GitHub](https://github.com/login) アカウントにログインします。
2. リポジトリ https://github.com/sylwia-budzynska/codeql-workshop に移動します。
3. Code -> Codespaces をクリックします。
4. プラス記号 (+) をクリックして、新しい Codespace を作成します。

<img src="https://assets.kitploit.com/production/public/readmes/33098/c86e537f9e7891fb6bdb5da727cae5b6ad0b2c9ac94f67854d48296f2dad89cb.png"  width="439" alt="Screenshot: Create Codespace, click on plus">

VS Code がブラウザーで起動し、リモートの Codespace が構築されます。これには数分かかる場合があります。
ワークスペース `vscode-codeql-starter.code-workspace` を開くように求められたら、"Open Workspace" をクリックします。

5. ローカルで VS Code を使用する場合は、左上隅の三本線ボタンを押して、"Open VS Code Desktop" を選択します。このオプションが表示されるまでに数分かかる場合があります。

<img src="https://assets.kitploit.com/production/public/readmes/33098/f2c8c2fe6da80142344b17c208da31a23c3fa68a3917a124f0e2f7871b6a20f7.png" width="300" alt="Screenshot: Press the three lines button and Open in VS Code Desktop">

6. 次に [CodeQL データベースの選択](#select-codeql-database) に進みます。
7. その後 [インストールのテスト](#test-your-installation) を行います。

Codespace は [github.com/codespaces](https://github.com/codespaces) で確認できます。Codespace は数時間使用しないと自動的に停止しますが、無料の 120 時間を追加で消費しないようにするため、ワークショップ終了後は [github.com/codespaces](https://github.com/codespaces) > 三点リーダー > "Stop codespace" の順に操作して停止することを忘れないでください。

#### インストールのトラブルシューティング

次のようなエラーが表示された場合:
* `Failed to run query: Could not resolve library path for [..]`
* `Could not resolve module [..]`
* `Could not resolve type [..]`

git サブモジュール(具体的には ql リポジトリ)のクローンを忘れている可能性が高いです。これを修正するには、`git submodule init && git submodule update --recursive` を実行します。

### CodeQL データベースの選択

1. VS Code でワークスペース `vscode-codeql-starter.code-workspace` が開いていることを確認します。
2. 左側のタブペインにある "QL" アイコンをクリックして、CodeQL ビューに移動します。
3. "Choose Database from Archive" をクリックし、リポジトリのルートにある `test-app-db.zip` ファイルを選択します。
   注: この時点で、VSCode に CodeQL CLI のインストールを求めるポップアップエラーが表示される場合があります。このインストールを受け入れると問題が解決するはずです。CLI のインストールが完了したら、上記のデータベース選択を完了できるようになります。
   <img src="https://assets.kitploit.com/production/public/readmes/33098/65cc5790b8b49113623bc9a9b34a1be61575b05bea2428c46f83115e2271148b.png"  alt="Screenshot: VSCode error msg re. CodeQL">
   <img src="https://assets.kitploit.com/production/public/readmes/33098/c3bf9c304d9c1f6199f591c9bcbf6e446ee4f5388ab209e30887326698129f84.png"  alt="Screenshot: VSCode installing CodeQL CLI">

### インストールのテスト

#### 前提条件

以前に選択した CodeQL データベースが CodeQL ビューで選択されていることを確認します。(選択されていない場合は "Select" をクリックします)

データベースが選択されると、次のようになります(チェックマークに注目):

<img src="https://assets.kitploit.com/production/public/readmes/33098/fee6e47c0d9b0754c7ac9e29e2f0b3a721093aa5ce882615b3839a99f4862506.png"  alt="Screenshot: CodeQL Database selected">

#### 手順

1. VS Code で、ワークスペースフォルダー `codeql-custom-queries-python` に移動します。
2. 新しいファイル `test.ql` を作成します。
3. 次の内容を追加します: `select "Hello World!"`
4. ファイルを保存し、ファイル領域で右クリックして "CodeQL: Run Query on Selected Database" を選択します。
5. 結果 "Hello World!" が表示された新しいタブが開くはずです。

## :books: リソース

- [QL チュートリアル](https://codeql.github.com/docs/writing-codeql-queries/ql-tutorials/)
- [Python 向け CodeQL 言語ガイド](https://codeql.github.com/docs/codeql-language-guides/codeql-for-python/)
- [CodeQL ドキュメント](https://codeql.github.com/docs/)
- [QL 言語リファレンス](https://codeql.github.com/docs/ql-language-reference/)
- [Python 向け CodeQL ライブラリ](https://codeql.github.com/codeql-standard-libraries/python/)
- [Python コードの基本クエリ](https://codeql.github.com/docs/codeql-language-guides/basic-query-for-python-code/)
- [QL クラス](https://codeql.github.com/docs/ql-language-reference/types/#classes)
- [CodeQL zero to hero パート1: 脆弱性調査のための静的解析の基礎](https://github.blog/2023-03-31-codeql-zero-to-hero-part-1-the-fundamentals-of-static-analysis-for-vulnerability-research/)
- [CodeQL zero to hero パート2: CodeQL 入門](https://github.blog/2023-06-15-codeql-zero-to-hero-part-2-getting-started-with-codeql/)
- [CodeQL zero to hero パート3: セキュリティ調査](https://github.blog/2024-04-29-codeql-zero-to-hero-part-3-security-research-with-codeql/)
- [CodeQL zero to hero パート4: Gradio のケーススタディ](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-4-gradio-framework-case-study/)
- [CodeQL zero to hero パート5: クエリのデバッグ](https://github.blog/security/vulnerability-research/codeql-zero-to-hero-part-5-debugging-queries/)

## ワークショップ

ワークショップ「CodeQL で脆弱性を見つける」へようこそ!

このセッションでは、ソフトウェアの脆弱性を探す際に使用されるセキュリティ調査と静的解析の基礎を紹介します。単純な脆弱性の例を使用し、CodeQL がそれをどのように検出できるかを説明し、参加者が CodeQL を使って自分自身で脆弱性を見つける方法の例を提供します。

始める前に、ワークショップに参加できるように、すべての前提条件が満たされていることが重要です。

ワークショップは複数のセクションに分かれており、各セクションは最終的なクエリに至るまでの演習で構成されています。
各セクションでは、使用できる QL クラスとメンバー述語への参照を提供する *ガイドライン* を用意しており、演習を完了するのに役立ちます。

### 概要

このワークショップでは、[kohya_ss](https://securitylab.github.com/advisories/GHSL-2024-019_GHSL-2024-024_kohya_ss/) における既知の *コマンドインジェクションの脆弱性* を探します。このような脆弱性は、ユーザーが制御する情報が、コマンドを安全でない方法で構築して実行するアプリケーションコードに到達したときに発生する可能性があります。ユーザー入力から安全でない方法で構築されたコマンドは、任意のコマンド実行や機密情報の開示などの意図しない動作を実行するように書き換えられる可能性があります。

このワークショップで説明するコマンドインジェクションは、[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/) です。

## 理論

### ソースとシンク

最もよく知られている脆弱性の 1 つであるコマンドインジェクションについて考えてみましょう。これは、ユーザー入力が、サーバー上で直接シェルでコマンドを実行できる関数で使用された場合に発生します。これにより、攻撃者はアプリケーションを実行しているサーバー上でオペレーティングシステム (OS) コマンドを実行でき、通常はアプリケーションとそのデータを完全に侵害します。

インジェクション脆弱性の主な原因は、信頼できないユーザー制御の入力が、プログラムの機密性の高い、または危険な関数で使用されることです。これを静的解析で表現するために、データフロー、ソース、シンクなどの用語を使用します。

ユーザー入力は一般に、アプリケーションへのエントリポイント、つまりデータの発生源から取得されます。これには、GET や POST などの HTTP メソッドのパラメータや、プログラムへのコマンドライン引数が含まれます。これらは「**ソース**」と呼ばれます。

コマンドインジェクションの話に戻ると、サニタイズされていない信頼できないデータで呼び出すべきではない危険な関数の例としては、`os.system` が挙げられます。これらの危険な関数は「**シンク**」と呼ばれます。関数が潜在的に危険であるというだけで、それが直ちに悪用可能な脆弱性であり、削除しなければならないというわけではないことに注意してください。多くのシンクには、安全に使用する方法があります。ユーザー入力とともに使用すべきでないシンクの他の例としては、Python の MySQLdb ライブラリの MySQLCursor.execute()(SQL インジェクションを引き起こす)や、任意の式を評価する Python の組み込み関数 eval()(コードインジェクションを引き起こす)があります。

脆弱性が存在するためには、安全でないユーザー制御の入力が、適切なサニタイズや入力検証なしに危険な関数で使用されなければなりません。言い換えれば、ソースとシンクの間にコードパスが存在する必要があり、その場合、データがソースからシンクに流れる、つまりソースからシンクへの「**データフロー**」が存在すると言います。

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

### CodeQL チートシート
基本的なクエリ構造```codeql
import python

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

where <conditions for variables>

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

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:~
`os.system()` 呼び出しへの参照を検索します。今回は述語を指定します。```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"

os.system() 呼び出しへの参照を見つけます。今回はクラスを使用します。```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:~
`os.system()` 呼び出しへの参照を、今度はクラスを使って見つけます。
開始する型が `OsSystemSink` であることを指定します。```codeql
class OsSystemSink extends API::CallNode {
  OsSystemSink() {
    this = API::moduleImport("os")
    .getMember("system").getACall()
	}
}


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

ワークショップ パート I - テストデータベース

このワークショップでは、ユーザー入力が os.system 呼び出しに到達するコマンドインジェクションを発見します。

ワークショップの最初のパートでは、意図的に脆弱性を持たせたコードベース上で、ソースとシンク(os.system 呼び出し)を見つける CodeQL クエリを作成します。ワークショップの2番目のパートでは、それらのクエリを使用して、オープンソースソフトウェア kohya_ss v22.6.1 において、ソースからシンクへのコマンドインジェクションを見つけます。

私たちが作成する CodeQL クエリを使用すると、以下のようなコマンドインジェクションを見つけることができます。

ユーザー入力は、#1 にあるインタラクティブな Gradio(機械学習アプリケーション用の Web フレームワーク)コンポーネント gr.Textbox から取得されます。#2 の gr.Button.click は、ボタンのクリックを execute_cmd 関数にバインドし、folder の値を渡します。つまり、gr.Button がクリックされると、folder が execute_cmd に渡され、そこで folder がコマンドに連結され、#3 の os.system 呼び出しでシステム上で実行されます。```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:~
また、ワークショップでは、`Flask` フレームワークを使用して作成されたアプリでも、別のコマンドインジェクションの例が見られます。この場合、ユーザー入力は Flask(Python で人気のある Web フレームワーク)リクエストの GET パラメータから取得され、変数 `files` に格納されます(#1 を参照)。`files` はその後 `os.system` 呼び出しに渡され、`ls` と連結されるため、コマンドインジェクションが発生します(#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

まず、os.system 呼び出しを検出するクエリを段階的に構築し、その後ソース用のクエリを構築します。

1. 外部ライブラリの関数への呼び出しをすべて見つける

CodeQL の ApiGraphs モジュールを使用すると、外部ライブラリ(コードベース内で定義されていない)の関数への呼び出しをすべて見つけることができます。

以下のテンプレートを使用してください:```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:~
ファイル領域で右クリックし、クエリを実行するには "CodeQL: Run Query on Selected Database" を選択します。

<details>
<summary>ガイドライン</summary>

- `from` 句では、`API::` から始めて `Ctrl + Space` を押すと、API Graphs モジュールで利用可能な型が表示されます。
- 呼び出しは `API::CallNode` 型で表されます。その型で `call` という名前の変数を作成してください。
- アプリケーションのルートフォルダー(`test-app` と呼ばれる)内の呼び出しのみに結果を制限するには、` where` 句を追加して、条件 `where call.getLocation().getFile().getRelativePath().regexpMatch("test-app/.*")` を使用します。

</details>
<details>
<summary>解答</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. os.system へのすべての呼び出しを見つける

ガイドライン
  • from 句で、API::CallNode 型の call 変数を作成します。
  • where 句で、等価演算子 = を使用して、call が os.system 呼び出しと等しいことを表明します。論理演算子 and を使用して、複数の条件を指定します。
  • os ライブラリに対応するノードを見つけるには、引数として os を指定して API::moduleImport() メソッドを使用します。os ライブラリの system 関数にアクセスするには、API::moduleImport() に対して getMember() 述語を使用します。最後に、 述語を使用して任意の 呼び出しを取得します。

3. os.system への呼び出しの最初の引数を見つける

os.system 呼び出しの最初の引数を見つけたいので、後でユーザー入力が最初の引数(つまり実行されるコマンド)に流れ込むかどうかを確認できるようにします。

ガイドライン
  • テンプレートを記入してください:```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>解答</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. os.system への呼び出しを検出するクエリを CodeQL クラスに変換する

CodeQL の classes は、再利用可能なロジックの部分をカプセル化するために使用できます。クラスは値の単一の集合を表し、その集合に固有の操作(メンバー述語として知られる)を含めることもできます。あなたはすでに CodeQL クラス(API::CallNode)やメンバー述語(getLocation() など)の多くの例を見てきました。

ガイドライン
  • 新しい型を作成するには、スーパータイプ(ここでは API::CallNode)を拡張し、名前を付け、同じ名前の 特性述語 を与える必要があります。ここではクラスに OsSystemSink という名前を付けます。

テンプレートを埋めてください:```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:~
マジック`this`キーワードを使用してください。これは、クラス内で記述している呼び出しノード(`API::CallNode`)のインスタンスを参照します。`this`を使用して、前回`API::moduleImport`で行ったのと同じ方法で、`os.system`への呼び出しを検索します。
- `where`句を変更して、`call`変数が新しい`OsSystemSink`クラスの`instanceof`になるようにします。

</details>
<details>
<summary>解答</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. RemoteFlowSource クラスで全てのソースを検索する

ここからはソースの検索に切り替えます。

ほとんどのソースはすでにモデル化されて CodeQL に組み込まれており、RemoteFlowSource 型を持っています。この型を使うことで、コードベース内の任意のソースを検索できます。

ガイドライン
  • RemoteFlowSource 型を使用するには、semmle.python.dataflow.new.RemoteFlowSources をインポートします。
  • from 句で Ctrl + Space を押すと、利用可能なすべての型を確認できます。

テンプレートを記入してください。```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>解決策</summary>```codeql
import python
import semmle.python.dataflow.new.RemoteFlowSources

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

ワークショップ パート II - kohya_ss におけるコマンドインジェクションを見つける

Kohya_ss は、Kohya の Stable Diffusion 用トレーニング、生成、およびユーティリティのスクリプト の GUI です。

ワークショップの第 2 部では、クエリ対象のコードベースを kohya_ss に切り替え、kohya_ss 内でソースからシンクへのデータフローを見つけます。これらはコマンドインジェクションにつながります: CVE-2024-32022, CVE-2024-32026, CVE-2024-32025, CVE-2024-32027

次の演習を始める前に:

  • VSCode の CodeQL タブの Databases セクションに移動し、"Choose Database from Archive" をクリックして、リポジトリのルートにある kohya_ss-db.zip ファイルを選択します。チェックマークが表示されるはずです。これにより、作業対象の CodeQL データベースが選択されます。

6. ソースから os.system 呼び出しの最初の引数へのデータフローを見つける

ガイドライン
  • 以下のテンプレートを使用し、次の点に注意してください:
  • isSource 述語では、source 変数を RemoteFlowSource 型に絞り込みます。
  • isSink 述語では、sink 変数を os.system 呼び出しの最初の引数に絞り込みます。これは exists メカニズムと OsSystemSink クラスを使用して行います。
    • exists は、スコープが制限された一時変数を導入するためのメカニズムです。これは独自の from-where-select と考えることができます。この場合、exists を使用して OsSystemSink 型の変数 call を導入し、sink を call の最初の引数に絞り込みます。```codeql /**

ボーナス演習(時間が許せば)

7. デフォルトクエリを使用してコードベースにクエリを実行する

Python 用の CodeQL クエリは ql/python/ql/src/Security フォルダーにあります。SQL インジェクション、コマンドインジェクション、コードインジェクションなど、最も一般的な脆弱性に対するクエリがすでに存在します。テストデータベースに対して SQL インジェクションクエリ (CWE-089) を実行してください(CodeQL 拡張機能 > Databases でそれを選択する必要があります。チェックマークに注意してください)。

💡 これはセキュリティ研究者にとって非常に興味深いことです。デフォルトのクエリを使用することで、特定のプロジェクトに存在する可能性のある潜在的な脆弱性の概要を把握できます。

8. マルチリポジトリ変異解析 (MRVA) を使用して独自のクエリを実行する

CodeQL の強みは、CodeQL クエリとモデルを再利用して、同じ言語の任意のコードベースに対して実行できることです。マルチリポジトリ変異解析 (MRVA) を使用すると、最大 1000 個のリポジトリに対して同時に CodeQL クエリを実行できます。プロジェクトは GitHub 上でホストされている必要があります。

💡 これはセキュリティ研究者にとって非常に興味深いことです。潜在的に危険なシンクやソースを見つけた場合、それを CodeQL に追加(またはクエリとして実行)して、一度に 1000 個のリポジトリに対して調査を行うことができます。

  • ドキュメント のセットアップに従ってください。
  • MRVA は GitHub Actions ワークフローを使用して実行されることに注意してください。Actions ワークフローは公開リポジトリでは無料ですが、プライベートリポジトリでは有料です。
  • セットアップ後、右クリックして "CodeQL: Run Variant Analysis" を選択します。

おわりに

本日は、CodeQL を使用してコードベースを調査する方法と、自身のセキュリティ研究ワークフローで CodeQL を活用する方法を学びました。

さらに詳しく知りたい場合は、以下のリソースを参照してください:

  • 静的解析とその仕組み:
    • CodeQL zero to hero パート 1: 脆弱性調査のための静的解析の基礎。
  • CodeQL とそのクエリ言語の基礎:
    • CodeQL zero to hero パート 2: CodeQL 入門。
  • CodeQL によるセキュリティ研究:
    • CodeQL zero to hero パート 3: セキュリティ研究。
  • Gradio の例による Web フレームワーク向け CodeQL のモデル化方法
    • CodeQL zero to hero パート 4: Gradio ケーススタディ。
  • クエリが機能しない理由のデバッグ:
    • CodeQL zero to hero パート 5: クエリのデバッグ

CodeQL を使用して脆弱性を発見した場合は、CodeQL Wall of Fame に遠慮なく追加してください。

ツールをダウンロード
getACall()
os.system

テンプレートを記入してください:```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>解決策</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`"
  • @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>解答</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"