今回は、GitHub が開発し、また、GitHub で使われている CodeQL という、セキュリティ脆弱性を検出するオープンソースのツール(コード分析エンジン)を使ってみたいと思います。
VSCode(Visual Studio Code)に、CodeQL をインストールして使われる場合が多いかもしれませんが、ここでは、まずは、ローカルで使っていこうと思います(CodeQL CLI)。
それでは、やっていきます。
はじめに
「セキュリティ」の記事一覧です。良かったら参考にしてください。
セキュリティの記事一覧
以下は、CodeQL の公式サイトです。
codeql.github.com
また、CodeQL CLI の公式ドキュメントは以下です。ありがたいことに、日本語のドキュメントがあります。
docs.github.com
このページにリンクがある ライセンスのページ を見ると、CodeQL は、GitHub で公開されているリポジトリのように、オープンソースに使うことは許されていますが、GitHub のプライベートリポジトリのような公開されていないソフトウェアに使う場合は、商用ライセンスが必要になるようです。
CodeQL CLI を使用してコードをセキュリティで保護する
上のリンクをクリックすると、3つのリンク先として、「CodeQL CLI の使用を開始する」、「CodeQL CLI の高度な機能の使用」、「CodeQL CLI コマンドのマニュアル」が見えます。
CodeQL CLI の使用を開始する
以下の CodeQL CLI の公式ドキュメントの「CodeQL CLI の使用を開始する」の通りに、CodeQL CLI を実行できる環境構築を進めてみます。使用する環境は、Parrot OS です。
docs.github.com
CodeQL CLI について
最初の項目は、「CodeQL CLI について」です。
ここでは、CodeQL CLI について、簡単な説明があります。
CodeQL CLI は、スタンドアロンのコマンドラインツールであり、ソースコードをデータベース化し、そこにクエリ(問い合わせ)することで、コード分析を行うことが出来ると説明されています。
CodeQL CLI が対応するのは、コンパイルを必要としない言語は JavaScript や、Python があり、コンパイルを必要とする言語では、C/C++、C#、Go、Java、Kotlin、Swift に対応しているようです。
CodeQL CLI を使う流れとしては、まず、ソースコードからデータベースを作成します($ codeql database create)。その後、データベースに対して、コード分析を行います($ codeql database analyze)。そして、その結果をいろんなフォーマットで出力することが出来ます。
CodeQL CLI の設定
次の項目は、「CodeQL CLI の設定」です。
ここでは、CodeQL CLI の環境を構築します。インストーラーは無く、リリースされている圧縮ファイルを解凍するだけで実行できる環境が構築できます。
以下の GitHub のリリースページから最新の CodeQL CLI をダウンロードします。
github.com
この記事を書いてる時点の最新版(Latest)は、v2.22.0 です。Assets というところから、codeql-bundle-linux64.tar.gz というファイルをダウンロードして、解凍します。
$ mkdir v2.22.0-bundle
$ cd v2.22.0-bundle/
$ wget https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.22.0/codeql-bundle-linux64.tar.gz
$ wget https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.22.0/codeql-bundle-linux64.tar.gz.checksum.txt
$ sha256sum -c codeql-bundle-linux64.tar.gz.checksum.txt
codeql-bundle-linux64.tar.gz: 完了
$ tar zxvf codeql-bundle-linux64.tar.gz
これで、CodeQL CLI を実行できる状況になりましたが、動作確認をしてみます。
まず実行するのは、CodeQL が持っている CodeQL クエリパックを一覧で主力しています。CodeQL では、最小単位がクエリというルールのようなものがあり、このルールに従って、ソースコードを分析します。CodeQL クエリパックとは、いくつかのルールを集めたものです。
cpp や csharp(C#)などのクエリパックが見つかります。
$ codeql/codeql resolve packs
Searching directories specified by `--additional-packs`. All directories have equal priority.
Searching in:
No packs were found at this location.
Searching directories specified by `--search-path`. Directories are searched in order.
Searching the root of the CodeQL distribution.
Searching in:
/home/user/svn/CodeQL/v2.22.0-bundle/codeql
The following packs were found:
codeql/actions-all@0.4.11: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/actions-all/0.4.11/qlpack.yml
codeql/actions-queries@0.6.3: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/actions-queries/0.6.3/qlpack.yml
codeql/controlflow@2.0.9: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/controlflow/2.0.9/qlpack.yml
codeql/cpp-all@5.1.0: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-all/5.1.0/qlpack.yml
codeql/cpp-examples@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-examples/0.0.0/qlpack.yml
codeql/cpp-queries@1.4.2: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/qlpack.yml
codeql/csharp-all@5.1.8: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/csharp-all/5.1.8/qlpack.yml
codeql/csharp-examples@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/csharp-examples/0.0.0/qlpack.yml
codeql/csharp-queries@1.2.2: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/csharp-queries/1.2.2/qlpack.yml
codeql/dataflow@2.0.9: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/dataflow/2.0.9/qlpack.yml
codeql/go-all@4.2.7: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/go-all/4.2.7/qlpack.yml
codeql/go-examples@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/go-examples/0.0.0/qlpack.yml
codeql/go-queries@1.3.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/go-queries/1.3.0/qlpack.yml
codeql/java-all@7.3.1: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/java-all/7.3.1/qlpack.yml
codeql/java-examples@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/java-examples/0.0.0/qlpack.yml
codeql/java-queries@1.5.2: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/java-queries/1.5.2/qlpack.yml
codeql/javascript-all@2.6.5: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/javascript-all/2.6.5/qlpack.yml
codeql/javascript-examples@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/javascript-examples/0.0.0/qlpack.yml
codeql/javascript-queries@1.6.2: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/javascript-queries/1.6.2/qlpack.yml
codeql/mad@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/mad/1.0.25/qlpack.yml
codeql/python-all@4.0.9: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/python-all/4.0.9/qlpack.yml
codeql/python-examples@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/python-examples/0.0.0/qlpack.yml
codeql/python-queries@1.5.2: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/python-queries/1.5.2/qlpack.yml
codeql/quantum@0.0.3: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/quantum/0.0.3/qlpack.yml
codeql/rangeanalysis@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/rangeanalysis/1.0.25/qlpack.yml
codeql/regex@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/regex/1.0.25/qlpack.yml
codeql/ruby-all@4.1.8: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/ruby-all/4.1.8/qlpack.yml
codeql/ruby-examples@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/ruby-examples/0.0.0/qlpack.yml
codeql/ruby-queries@1.3.2: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/ruby-queries/1.3.2/qlpack.yml
codeql/rust-all@0.1.10: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/rust-all/0.1.10/qlpack.yml
codeql/rust-queries@0.1.10: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/rust-queries/0.1.10/qlpack.yml
codeql/ssa@2.0.1: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/ssa/2.0.1/qlpack.yml
codeql/suite-helpers@1.0.25: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/suite-helpers/1.0.25/qlpack.yml
codeql/swift-all@5.0.1: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/swift-all/5.0.1/qlpack.yml
codeql/swift-queries@1.1.5: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/swift-queries/1.1.5/qlpack.yml
codeql/threat-models@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/threat-models/1.0.25/qlpack.yml
codeql/tutorial@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/tutorial/1.0.25/qlpack.yml
codeql/typeflow@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/typeflow/1.0.25/qlpack.yml
codeql/typeinference@0.0.6: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/typeinference/0.0.6/qlpack.yml
codeql/typetracking@2.0.9: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/typetracking/2.0.9/qlpack.yml
codeql/typos@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/typos/1.0.25/qlpack.yml
codeql/util@2.0.12: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/util/2.0.12/qlpack.yml
codeql/xml@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/xml/1.0.25/qlpack.yml
codeql/yaml@1.0.25: (library) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/yaml/1.0.25/qlpack.yml
legacy-upgrades@0.0.0: (query) /home/user/svn/CodeQL/v2.22.0-bundle/codeql/legacy-upgrades/qlpack.yml
Searching the parent directory of the CodeQL distribution.
Searching in:
/home/user/svn/CodeQL/v2.22.0-bundle
Some packs were hidden by previously found packs. Use --show-hidden-packs to see them.
Searching the local pack cache. This only applies when searching for a particular version of a pack specified in a lock file.
Searching in: /home/user/.codeql/packages
No packs were found at this location.
次に、同じような感じのもので、クエリスイートというものがあります。これは、特定のメタデータ プロパティに基づいて、実行するクエリを選択するというものらしいです。これも一覧を出力してみます。
こちらも、cpp や、いろんな言語のものが見つかります。
$ codeql/codeql resolve queries
No queries were specified.
If you don't know where to start, one of these query suites might be what
you want? (Beware that not all of them may be compatible with your database).
actions-all.qls - Standard Code Scanning queries for GitHub Actions
actions-bughalla.qls - Bughalla queries for GitHub Actions
actions-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/actions-queries/0.6.3/codeql-suites/actions-code-quality.qls)
actions-code-scanning.qls - Standard Code Scanning queries for GitHub Actions
actions-security-and-quality.qls - Security-and-quality queries for GitHub Actions
actions-security-experimental.qls - Extended and experimental security queries for GitHub Actions
actions-security-extended.qls - Security-extended queries for GitHub Actions
actions-summaries-queries.qls - Queries to model composite actions
cpp-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/codeql-suites/cpp-code-quality.qls)
cpp-code-scanning.qls - Standard Code Scanning queries for C and C++
cpp-lgtm-full.qls - Standard LGTM queries for C/C++, including ones not displayed by default
cpp-lgtm.qls - Standard LGTM queries for C/C++
cpp-security-and-quality.qls - Security-and-quality queries for C and C++
cpp-security-experimental.qls - Extended and experimental security queries for C and C++
cpp-security-extended.qls - Security-extended queries for C and C++
csharp-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/csharp-queries/1.2.2/codeql-suites/csharp-code-quality.qls)
csharp-code-scanning.qls - Standard Code Scanning queries for C#
csharp-lgtm-full.qls - Standard LGTM queries for C#, including ones not displayed by default
csharp-lgtm.qls - Standard LGTM queries for C#
csharp-security-and-quality.qls - Security-and-quality queries for C#
csharp-security-experimental.qls - Extended and experimental security queries for C#
csharp-security-extended.qls - Security-extended queries for C#
go-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/go-queries/1.3.0/codeql-suites/go-code-quality.qls)
go-code-scanning.qls - Standard Code Scanning queries for Go
go-developer-happiness.qls - Experimental queries showing how we use CodeQL internally for developer happiness
go-lgtm-full.qls - Standard LGTM queries for Go, including ones not displayed by default
go-lgtm.qls - Standard LGTM queries for Go
go-security-and-quality.qls - Security-and-quality queries for Go
go-security-experimental.qls - Extended and experimental security queries for Go
go-security-extended.qls - Security-extended queries for Go
java-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/java-queries/1.5.2/codeql-suites/java-code-quality.qls)
java-code-scanning.qls - Standard Code Scanning queries for Java
java-lgtm-full.qls - Standard LGTM queries for Java, including ones not displayed by default
java-lgtm.qls - Standard LGTM queries for Java
java-security-and-quality.qls - Security-and-quality queries for Java
java-security-experimental.qls - Extended and experimental security queries for Java and Kotlin
java-security-extended.qls - Security-extended queries for Java
javascript-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/javascript-queries/1.6.2/codeql-suites/javascript-code-quality.qls)
javascript-code-scanning.qls - Standard Code Scanning queries for JavaScript
javascript-lgtm-full.qls - Standard LGTM queries for JavaScript, including ones not displayed by default
javascript-lgtm.qls - Standard LGTM queries for JavaScript
javascript-security-and-quality.qls - Security-and-quality queries for JavaScript
javascript-security-experimental.qls - Extended and experimental security queries for JavaScript and TypeScript
javascript-security-extended.qls - Security-extended queries for JavaScript
python-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/python-queries/1.5.2/codeql-suites/python-code-quality.qls)
python-code-scanning.qls - Standard Code Scanning queries for Python
python-lgtm-full.qls - Standard LGTM queries for Python, including ones not displayed by default
python-lgtm.qls - Standard LGTM queries for Python
python-security-and-quality.qls - Security-and-quality queries for Python
python-security-experimental.qls - Extended and experimental security queries for Python
python-security-extended.qls - Security-extended queries for Python
ruby-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/ruby-queries/1.3.2/codeql-suites/ruby-code-quality.qls)
ruby-code-scanning.qls - Standard Code Scanning queries for Ruby
ruby-lgtm-full.qls - Standard LGTM queries for Ruby, including ones not displayed by default
ruby-lgtm.qls - Standard LGTM queries for Ruby
ruby-security-and-quality.qls - Security-and-quality queries for Ruby
ruby-security-experimental.qls - Extended and experimental security queries for Ruby
ruby-security-extended.qls - Security-extended queries for Ruby
rust-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/rust-queries/0.1.10/codeql-suites/rust-code-quality.qls)
rust-code-scanning.qls - Standard Code Scanning queries for Rust
rust-security-and-quality.qls - Security-and-quality queries for Rust
rust-security-experimental.qls - Extended and experimental security queries for Rust
rust-security-extended.qls - Security-extended queries for Rust
swift-code-quality.qls - (unnamed suite at /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/swift-queries/1.1.5/codeql-suites/swift-code-quality.qls)
swift-code-scanning.qls - Standard Code Scanning queries for Swift
swift-security-and-quality.qls - Security-and-quality queries for Swift
swift-security-experimental.qls - Extended and experimental security queries for Swift
swift-security-extended.qls - Security-extended queries for Swift
CodeQL CLI は、正しく動作していそうです。
分析対象のソースコードを準備する
ここまで、CodeQL CLI の公式ドキュメント通りに進めてきましたが、次の「CodeQL 分析のためのコードの準備」の前に、分析する対象のソースコードを探そうと思います。
ChatGPT に、ちょうどいいサンプルについて、相談してみたところ、以下のリポジトリが紹介されました。これを使ってみます。
ヒープの脆弱性を含むソースコードと、それをエクスプロイトするコードが含まれているようです。
github.com
$ git clone https://github.com/NVombat/Use-After-Free.git
$ cd Use-After-Free/
$ ll
合計 136K
drwxr-xr-x 1 user user 342 6月 27 22:56 ./
drwxr-xr-x 1 user user 178 6月 27 22:55 ../
drwxr-xr-x 1 user user 138 6月 27 22:55 .git/
-rw-r--r-- 1 user user 430 6月 27 22:55 .gitignore
drwxr-xr-x 1 user user 26 6月 27 22:55 .vscode/
-rw-r--r-- 1 user user 1.1K 6月 27 22:55 LICENSE
-rw-r--r-- 1 user user 828 6月 27 22:55 Makefile
-rw-r--r-- 1 user user 3.5K 6月 27 22:55 README.md
-rwxr-xr-x 1 user user 659 6月 27 22:55 exploit1.sh*
-rwxr-xr-x 1 user user 555 6月 27 22:55 exploit2.sh*
-rwxr-xr-x 1 user user 19K 6月 27 22:56 heap_overflow*
-rw-r--r-- 1 user user 662 6月 27 22:55 heap_overflow.c
-rwxr-xr-x 1 user user 22K 6月 27 22:56 test_uaf*
-rwxr-xr-x 1 user user 22K 6月 27 22:56 use_after_free*
-rw-r--r-- 1 user user 6.4K 6月 27 22:55 use_after_free.c
-rwxr-xr-x 1 user user 22K 6月 27 22:56 use_after_free_fix*
-rw-r--r-- 1 user user 5.6K 6月 27 22:55 use_after_free_fix.c
use_after_free.c を見てみます。
ユーザに、メニュー表示として、1~5 の選択肢が与えられます。
1 は、ユーザ名入力です。malloc関数により、20byte のメモリ領域(変数:username)を確保した後、username をユーザが入力し、最大 254byte + ヌル終端の 255byte の文字列が格納されます。ヒープバッファオーバーフローの脆弱性がありそうです。また、"root" という文字列が与えられた場合、それは無効とし、username はヌル終端が入れられます。1 を何度も実行すると、その都度、20byte のメモリ確保を行ってしまいそうです。
2 は、パスワード入力です。ただし、username に有効な文字列が格納されていない場合は、メニュー表示に戻ります。malloc関数により、20byte のメモリ領域(変数:password)を確保した後、password をユーザが入力し、最大 254byte + ヌル終端の 255byte の文字列が格納されます。こちらも、ヒープバッファオーバーフローの脆弱性がありそうです。2 についても、1 と同様に、何度も実行すると、その都度、20byte のメモリ確保を行ってしまいそうです。
3 は、メモリ解放です。password が NULL、かつ、username が NULL の場合はメニュー表示に戻ります。そうではない場合(2つの変数のうち、どちらかが NULL ではない場合)、password と username を free関数でメモリ解放します。どちらの変数にも、メモリ解放後に NULL を設定していないため、Use After Free の脆弱性がありそうです。
4 は、少し長いです。まず、password、username のどちらか一方が NULL の場合、メニュー表示に戻ります。そうではない場合、temp_uname、temp_pwd にそれぞれ、20byte のメモリを確保し、ユーザに 最大 254byte の文字列を入力させて、それぞれに格納します。ここもヒープバッファオーバーフローの脆弱性がありそうです。次に、username が root だった場合の処理があります(しかし、5 の処理を含めても、username が root にすることは出来ないはず)。ここには、system関数の実行が可能であり、ユーザはシェルを実行することが出来そうです。最後に、temp_uname、temp_pwd のメモリ解放を行って終了(メニューに戻る)します。
5 は、プログラムを終了させます。
username に "root" という文字列を設定して、エクスプロイトすることが目的のようです。
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
printf("Okay, so here's what YOU need to do...\n");
printf("You have access to the source code...\n");
printf("Try and become root so you can execute a command of your choice and drop a shell...\n");
printf("There's atleast 2 different ways to exploit this code so...\n");
printf("If you can't become root, you stoopid!\n");
printf("Type shit Type shit!\n");
time_t start_time;
time(&start_time);
char * username = 0;
char * password = 0;
int flag = 0;
while(1)
{
if(username){
printf("USERNAME ADDRESS: %x\nUSERNAME: %s\n", username, username);
}
if(password){
printf("PASSWORD ADDRESS: %x\nPASSWORD: %s\n", password, password);
}
printf("1: Username\n");
printf("2: Password\n");
printf("3: Reset\n");
printf("4: Login\n");
printf("5: Exit\n");
printf("Choose an option [1-5]: ");
int choice = 0;
scanf("%d", &choice);
switch(choice)
{
case 1:
username = malloc(20*sizeof(char));
printf("Enter username: ");
scanf("%254s", username);
if(!strcmp(username, "root"))
{
printf("[root]: Ain't no way it's that easy. Try again fool!\n");
strcpy(username, "");
}
break;
case 2:
if (!username){
printf("What tf are you setting a password for? Set a username first fool\n");
break;
}
password = malloc(20*sizeof(char));
printf("Enter password: ");
scanf("%254s", password);
printf("Bruh! My grandmother is stronger than that password!\n");
break;
case 3:
if (!password && !username){
printf("Do you want me to reset yo ass? Use your brains man!\n");
printf("How tf you gonna reset smth that don't exist!\n");
break;
}
free(password);
free(username);
break;
case 4:
if (!password || !username){
printf("How tf you gonna log in without both credentials [username & password] dumbass! Set them up first\n");
break;
}
char * temp_uname = (char*)malloc(20*sizeof(char));
char * temp_pwd = (char*)malloc(20*sizeof(char));
printf("Enter username: ");
scanf("%254s", temp_uname);
printf("Enter password: ");
scanf("%254s", temp_pwd);
if(!strcmp(username, "root"))
{
time_t end_time;
time(&end_time);
double time_spent = difftime(end_time, start_time);
printf("You took %.2f seconds...\n", time_spent);
flag = 1;
printf("Congratulations! You figured out how to exploit the vulnerability and drop a shell you fkn nerd!\n");
printf("---SOME PRIVILEGED SHIT GOING ON HERE---\n");
char * command = (char*)malloc(20*sizeof(char));
printf("$ Trying to mimic a shell. Enter a command cuz u root my g: ");
scanf("%254s", command);
system(command);
free(command);
exit(0);
}
if(!strcmp(temp_uname, username) && !strcmp(temp_pwd, password)){
BUG
printf("Logged in successfully but DID NOT drop a shell sucka! Not as smart as you thought you were lmao!\n");
}
else{
printf("Incorrect username or password! Try again dumbass!\n");
}
free(temp_pwd);
free(temp_uname);
break;
case 5:
time_t end_time;
time(&end_time);
double time_spent = difftime(end_time, start_time);
if (flag == 0){
printf("You just wasted %.2f seconds!\n", time_spent);
printf("Seems like you gave up on trying to drop a shell! Sucks to be You(se-After-Free)\n");
}
else{
printf("You took %.2f seconds...\n", time_spent);
printf("Congratulations! You figured out how to exploit the vulnerability and drop a shell you fkn nerd!\n");
}
exit(0);
default:
printf("Invalid Option! Try Again Dipshit!\n");
break;
}
}
}
ビルドして、実行してみます。いくつか警告が出ていますが、printf関数の型に関するもので、問題は無さそうです。
$ make
Makefile:32: 警告: ターゲット 'heap_overflow' のためのレシピを置き換えます
Makefile:16: 警告: ターゲット 'heap_overflow' のための古いレシピは無視されます
Makefile:37: 警告: ターゲット 'use_after_free' のためのレシピを置き換えます
Makefile:19: 警告: ターゲット 'use_after_free' のための古いレシピは無視されます
Makefile:42: 警告: ターゲット 'use_after_free_fix' のためのレシピを置き換えます
Makefile:22: 警告: ターゲット 'use_after_free_fix' のための古いレシピは無視されます
make: 循環 heap_overflow <- heap_overflow 依存関係が破棄されました.
gcc -Wall -g -O2 -o heap_overflow heap_overflow.c
gcc -Wall -g -O2 -o use_after_free use_after_free.c
use_after_free.c: In function ‘main’:
use_after_free.c:27:40: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
27 | printf("USERNAME ADDRESS: %x\nUSERNAME: %s\n", username, username);
| ~^ ~~~~~~~~
| | |
| unsigned int char *
| %s
use_after_free.c:30:40: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
30 | printf("PASSWORD ADDRESS: %x\nPASSWORD: %s\n", password, password);
| ~^ ~~~~~~~~
| | |
| unsigned int char *
| %s
gcc -Wall -g -O2 -o use_after_free_fix use_after_free_fix.c
use_after_free_fix.c: In function ‘main’:
use_after_free_fix.c:26:40: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
26 | printf("USERNAME ADDRESS: %x\nUSERNAME: %s\n", username, username);
| ~^ ~~~~~~~~
| | |
| unsigned int char *
| %s
use_after_free_fix.c:29:40: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
29 | printf("PASSWORD ADDRESS: %x\nPASSWORD: %s\n", password, password);
| ~^ ~~~~~~~~
| | |
| unsigned int char *
| %s
gcc -Wall -g -O2 -o test_uaf use_after_free.c
use_after_free.c: In function ‘main’:
use_after_free.c:27:40: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
27 | printf("USERNAME ADDRESS: %x\nUSERNAME: %s\n", username, username);
| ~^ ~~~~~~~~
| | |
| unsigned int char *
| %s
use_after_free.c:30:40: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘char *’ [-Wformat=]
30 | printf("PASSWORD ADDRESS: %x\nPASSWORD: %s\n", password, password);
| ~^ ~~~~~~~~
| | |
| unsigned int char *
| %s
$ ./use_after_free
Okay, so here's what YOU need to do...
You have access to the source code...
Try and become root so you can execute a command of your choice and drop a shell...
There's atleast 2 different ways to exploit this code so...
If you can't become root, you stoopid!
Type shit Type shit!
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 1
Enter username: root
[root]: Ain't no way it's that easy. Try again fool!
USERNAME ADDRESS: 24f16ac0
USERNAME:
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 2
Enter password: abcde
Bruh! My grandmother is stronger than that password!
USERNAME ADDRESS: 24f16ac0
USERNAME:
PASSWORD ADDRESS: 24f16ae0
PASSWORD: abcde
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 1
Enter username: root
[root]: Ain't no way it's that easy. Try again fool!
USERNAME ADDRESS: 24f16b00
USERNAME:
PASSWORD ADDRESS: 24f16ae0
PASSWORD: abcde
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 5
You just wasted 76368.00 seconds!
Seems like you gave up on trying to drop a shell! Sucks to be You(se-After-Free)
では、表層解析からやっていきます。
特に制限は無さそうです。
$ file use_after_free
use_after_free: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=b99b4090edf7bafc857552c2fc379d7a50048ca1, for GNU/Linux 3.2.0, with debug_info, not stripped
$ ~/bin/checksec --file=use_after_free
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 45 Symbols No 0 1 use_after_free
$ pwn checksec --file=use_after_free
[*] Checking for new versions of pwntools
To disable this functionality, set the contents of /home/user/.cache/.pwntools-cache-3.11/update to 'never' (old way).
Or add the following lines to ~/.pwn.conf or ~/.config/pwn.conf (or /etc/pwn.conf system-wide):
[update]
interval=never
[!] An issue occurred while checking PyPI
[*] You have the latest version of Pwntools (4.13.0)
[*] '/home/user/svn/CodeQL/v2.22.0-bundle/Use-After-Free/use_after_free'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No
Debuginfo: Yes
では、4 を実行したときに、シェルを取る方法を考えていきます。
少し考えたところ、いくつかの方法がありそうです。
まず、username を入力した後、password を入力します。そして、3 を実行してメモリ解放します。password → username の順で解放されるので、tcache は、username → password になってるはずで、次は、username の領域が、malloc関数で確保されるはずです。次に、password を入力します。本来なら、username がメモリ解放されてるので、password を先に入力できないはずですが、username に NULL を設定していないため、password を入力できそうです。password のためのメモリ確保で、tcache の username が確保されます。password として "root" を入力します。すると、username も同じ場所を指してるので、username にも "root" が入ってることになります。
では、実際にやってみたところ、シェルが取れたようです。
$ ./use_after_free
Okay, so here's what YOU need to do...
You have access to the source code...
Try and become root so you can execute a command of your choice and drop a shell...
There's atleast 2 different ways to exploit this code so...
If you can't become root, you stoopid!
Type shit Type shit!
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 1
Enter username: root
[root]: Ain't no way it's that easy. Try again fool!
USERNAME ADDRESS: a51c9ac0
USERNAME:
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 2
Enter password: pass
Bruh! My grandmother is stronger than that password!
USERNAME ADDRESS: a51c9ac0
USERNAME:
PASSWORD ADDRESS: a51c9ae0
PASSWORD: pass
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 3
USERNAME ADDRESS: a51c9ac0
USERNAME: )�&��U
PASSWORD ADDRESS: a51c9ae0
PASSWORD: �Q:Z
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 2
Enter password: root
Bruh! My grandmother is stronger than that password!
USERNAME ADDRESS: a51c9ac0
USERNAME: root
PASSWORD ADDRESS: a51c9ac0
PASSWORD: root
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 4
Enter username: a
Enter password: b
You took 11.00 seconds...
Congratulations! You figured out how to exploit the vulnerability and drop a shell you fkn nerd!
---SOME PRIVILEGED SHIT GOING ON HERE---
$ Trying to mimic a shell. Enter a command cuz u root my g: /bin/sh
$ ls
LICENSE README.md exploit2.sh heap_overflow.c use_after_free use_after_free_fix
Makefile exploit1.sh heap_overflow test_uaf use_after_free.c use_after_free_fix.c
$
他の方法として、1 の username の入力 → 2 の password の入力 → 3 のメモリ解放を行っておきます。tcache は username → password の順です。4 を実行すると、temp_uname に username の領域が割り当てられます。temp_uname に root を入力するとシェルが取れそうです。実際にやってみます。
シェルが取れました。こちらの方が少し簡単です。
$ ./use_after_free
Okay, so here's what YOU need to do...
You have access to the source code...
Try and become root so you can execute a command of your choice and drop a shell...
There's atleast 2 different ways to exploit this code so...
If you can't become root, you stoopid!
Type shit Type shit!
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 1
Enter username: root
[root]: Ain't no way it's that easy. Try again fool!
USERNAME ADDRESS: 24ffbac0
USERNAME:
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 2
Enter password: pass
Bruh! My grandmother is stronger than that password!
USERNAME ADDRESS: 24ffbac0
USERNAME:
PASSWORD ADDRESS: 24ffbae0
PASSWORD: pass
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 3
USERNAME ADDRESS: 24ffbac0
USERNAME: ��EV
PASSWORD ADDRESS: 24ffbae0
PASSWORD: �Oa
1: Username
2: Password
3: Reset
4: Login
5: Exit
Choose an option [1-5]: 4
Enter username: root
Enter password: b
You took 10.00 seconds...
Congratulations! You figured out how to exploit the vulnerability and drop a shell you fkn nerd!
---SOME PRIVILEGED SHIT GOING ON HERE---
$ Trying to mimic a shell. Enter a command cuz u root my g: /bin/sh
$ ls
LICENSE README.md exploit2.sh heap_overflow.c use_after_free use_after_free_fix
Makefile exploit1.sh heap_overflow test_uaf use_after_free.c use_after_free_fix.c
$
ヒープのエクスプロイトの話になりましたが、CodeQL の対象のソースコードはこれにしようと思います。
CodeQL 分析のためのコードの準備
CodeQL CLI の公式ドキュメントに戻ります。ここでは、先ほど言った CodeQL CLI の実行の最初のステップのソースコードのデータベース化を進めていきます。
対象のソースコードはビルド可能である必要があります。データベース化のときに、ビルドが実行されるためです。
CodeQL のデータベース化には、codeql database create <database> --language=<language-identifier> を実行する必要があります。<database> は、作成するデータベース名なので、任意の名前(その名前のディレクトリが存在しないこと)を指定できます。--language は、C言語なので、c-cpp を指定します。また、--source-root で、対象のソースコードの場所を指定します。ちなみに、--language は -l、--source-root は -s でも同じです。
CodeQL CLI の実行は、先ほどやったように、直接バイナリを実行するか、パスを通しておくかをしておく必要があります。ここでは、直接バイナリを実行する方法とします。
では、実際にやってみます。ビルドターゲットが既に存在するとエラーが出た?のか、make clean してから、実行します。
末尾の行に、Successfully と出たので、成功したようです。
$ cd Use-After-Free/
$ make clean
Makefile:32: 警告: ターゲット 'heap_overflow' のためのレシピを置き換えます
Makefile:16: 警告: ターゲット 'heap_overflow' のための古いレシピは無視されます
Makefile:37: 警告: ターゲット 'use_after_free' のためのレシピを置き換えます
Makefile:19: 警告: ターゲット 'use_after_free' のための古いレシピは無視されます
Makefile:42: 警告: ターゲット 'use_after_free_fix' のためのレシピを置き換えます
Makefile:22: 警告: ターゲット 'use_after_free_fix' のための古いレシピは無視されます
rm -f heap_overflow use_after_free use_after_free_fix test_uaf
$ cd ..
$ codeql/codeql database create db_uaf -l c-cpp -s Use-After-Free
Initializing database at /home/user/svn/CodeQL/v2.22.0-bundle/db_uaf.
Running build command: [/home/user/svn/CodeQL/v2.22.0-bundle/codeql/cpp/tools/autobuild.sh]
Running command in /home/user/svn/CodeQL/v2.22.0-bundle/Use-After-Free: [/home/user/svn/CodeQL/v2.22.0-bundle/codeql/cpp/tools/autobuild.sh]
[2025-06-28 22:36:43] [build-stderr] cpp/autobuilder: Using build system found in '.'
[2025-06-28 22:36:43] [build-stderr] ln: シンボリックリンク '_codeql_detected_source_root/.' の作成に失敗しました: ファイルが存在します
[2025-06-28 22:36:43] [build-stdout] ~/svn/CodeQL/v2.22.0-bundle/Use-After-Free ~/svn/CodeQL/v2.22.0-bundle/Use-After-Free
[2025-06-28 22:36:43] [build-stderr] cpp/autobuilder: trying to run make -j 2 [current dir: /home/user/svn/CodeQL/v2.22.0-bundle/Use-After-Free]
[2025-06-28 22:36:43] [build-stdout] Makefile:32: 警告: ターゲット 'heap_overflow' のためのレ シピを置き換えます
[2025-06-28 22:36:43] [build-stdout] Makefile:16: 警告: ターゲット 'heap_overflow' のための古 いレシピは無視されます
[2025-06-28 22:36:43] [build-stdout] Makefile:37: 警告: ターゲット 'use_after_free' のためのレシピを置き換えます
[2025-06-28 22:36:43] [build-stdout] Makefile:19: 警告: ターゲット 'use_after_free' のための古いレシピは無視されます
[2025-06-28 22:36:43] [build-stdout] Makefile:42: 警告: ターゲット 'use_after_free_fix' のためのレシピを置き換えます
[2025-06-28 22:36:43] [build-stdout] Makefile:22: 警告: ターゲット 'use_after_free_fix' のための古いレシピは無視されます
[2025-06-28 22:36:43] [build-stdout] make: 循環 heap_overflow <- heap_overflow 依存関係が破棄 されました.
[2025-06-28 22:36:43] [build-stdout] gcc -Wall -g -O2 -o heap_overflow heap_overflow.c
[2025-06-28 22:36:43] [build-stdout] gcc -Wall -g -O2 -o use_after_free use_after_free.c
[2025-06-28 22:36:47] [build-stdout] gcc -Wall -g -O2 -o use_after_free_fix use_after_free_fix.c
[2025-06-28 22:36:47] [build-stdout] gcc -Wall -g -O2 -o test_uaf use_after_free.c
[2025-06-28 22:36:48] [build-stderr] cpp/autobuilder: autobuild summary.
Finalizing database at /home/user/svn/CodeQL/v2.22.0-bundle/db_uaf.
Running pre-finalize script /home/user/svn/CodeQL/v2.22.0-bundle/codeql/cpp/tools/pre-finalize.sh in /home/user/svn/CodeQL/v2.22.0-bundle/Use-After-Free.
Running command in /home/user/svn/CodeQL/v2.22.0-bundle/Use-After-Free: [/home/user/svn/CodeQL/v2.22.0-bundle/codeql/cpp/tools/pre-finalize.sh]
Running TRAP import for CodeQL database at /home/user/svn/CodeQL/v2.22.0-bundle/db_uaf...
Grouping TRAP files by link target
Grouping unlinked TRAP files together
Scanning TRAP files
Importing TRAP files
Merging relations
Finished writing database (relations: 131.98 KiB; string pool: 2.13 MiB).
TRAP import complete (17.2s).
Finished zipping source archive (106.92 KiB).
Successfully created database at /home/user/svn/CodeQL/v2.22.0-bundle/db_uaf.
ビルドに make を使ってないなどの場合は、--command で、ビルドのためのコマンドを指定する必要があります。
CodeQL クエリによるコード分析
データベースを作成したので、ここでは、それに対して、コードの分析を行います。
実行方法は、codeql database analyze <database> --format=<format> --output=<output> <query-specifiers>... です。database には、先ほど作成したデータベース名を指定します。--format=<format> には、CSV や SARIF(静的解析ツールの出力の標準フォーマットで、中身は JSON らしい)など、出力フォーマットを指定します。--output=<output> には、出力ファイル名を指定します。<query-specifiers>... には、CodeQLクエリパック、または、クエリを指定します。これを省略すると、標準クエリを実行することになります。
では、標準クエリで実行します。非力なマシンで実行したので、対象ファイルが少ないにもかかわらず、5分ぐらいかかりました。実は、一度失敗しました(仮想マシンがハングアップ)が、今度は、正常に実行できたようです。
$ codeql/codeql database analyze db_uaf --format csv --output out_uaf.csv
Running queries.
[1/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Critical/DoubleFree.qlx.
[2/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Critical/IncorrectCheckScanf.qlx.
[3/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Critical/NewFreeMismatch.qlx.
[4/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Critical/OverflowStatic.qlx.
[5/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Critical/UseAfterFree.qlx.
[6/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.qlx.
[7/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Arithmetic/IntMultToLong.qlx.
[8/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Arithmetic/SignedOverflowCheck.qlx.
[9/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Conversion/CastArrayPointerArithmetic.qlx.
[10/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Format/SnprintfOverflow.qlx.
[11/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Format/WrongNumberOfFormatArguments.qlx.
[12/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Format/WrongTypeFormatArguments.qlx.
[13/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Memory Management/AllocaInLoop.qlx.
[14/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Memory Management/PointerOverflow.qlx.
[15/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.qlx.
[16/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Memory Management/SuspiciousCallToStrncat.qlx.
[17/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Memory Management/UsingExpiredStackAddress.qlx.
[18/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/OO/UnsafeUseOfThis.qlx.
[19/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/RedundantNullCheckSimple.qlx.
[20/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Likely Bugs/Underspecified Functions/TooFewArguments.qlx.
[21/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-014/MemsetMayBeDeleted.qlx.
[22/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-078/ExecTainted.qlx.
[23/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-079/CgiXss.qlx.
[24/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-089/SqlTainted.qlx.
[25/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-120/BadlyBoundedWrite.qlx.
[26/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-120/VeryLikelyOverrunWrite.qlx.
[27/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-131/NoSpaceForZeroTerminator.qlx.
[28/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-134/UncontrolledFormatString.qlx.
[29/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-190/ArithmeticUncontrolled.qlx.
[30/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-190/ComparisonWithWiderType.qlx.
[31/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.qlx.
[32/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-253/HResultBooleanConversion.qlx.
[33/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-311/CleartextFileWrite.qlx.
[34/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-311/CleartextTransmission.qlx.
[35/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-319/UseOfHttp.qlx.
[36/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-326/InsufficientKeySize.qlx.
[37/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qlx.
[38/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-327/OpenSslHeartbleed.qlx.
[39/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-367/TOCTOUFilesystemRace.qlx.
[40/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-416/IteratorToExpiredContainer.qlx.
[41/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.qlx.
[42/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.qlx.
[43/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-468/SuspiciousAddWithSizeof.qlx.
[44/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-497/ExposedSystemData.qlx.
[45/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-611/XXE.qlx.
[46/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-676/DangerousFunctionOverflow.qlx.
[47/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-676/DangerousUseOfCin.qlx.
[48/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-704/WcharCharConversion.qlx.
[49/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-732/OpenCallMissingModeArgument.qlx.
[50/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.qlx.
[51/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Diagnostics/ExtractedFiles.qlx.
[52/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Diagnostics/ExtractionWarnings.qlx.
[53/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Diagnostics/FailedExtractorInvocations.qlx.
[54/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Summary/LinesOfCode.qlx.
[55/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Summary/LinesOfUserCode.qlx.
[56/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Telemetry/CompilerErrors.qlx.
[57/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Telemetry/DatabaseQuality.qlx.
[58/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Telemetry/ExtractionMetrics.qlx.
[59/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Telemetry/MissingIncludes.qlx.
[60/60] Loaded /home/user/svn/CodeQL/v2.22.0-bundle/codeql/qlpacks/codeql/cpp-queries/1.4.2/Telemetry/SucceededIncludes.qlx.
DoubleFree.ql : [1/60 eval 1m21s] Results written to codeql/cpp-queries/Critical/DoubleFree.bqrs.
IncorrectCheckScanf.ql : [2/60 eval 254ms] Results written to codeql/cpp-queries/Critical/IncorrectCheckScanf.bqrs.
NewFreeMismatch.ql : [3/60 eval 5.9s] Results written to codeql/cpp-queries/Critical/NewFreeMismatch.bqrs.
OverflowStatic.ql : [4/60 eval 6.1s] Results written to codeql/cpp-queries/Critical/OverflowStatic.bqrs.
UseAfterFree.ql : [5/60 eval 1.7s] Results written to codeql/cpp-queries/Critical/UseAfterFree.bqrs.
ExtractedFiles.ql : [6/60 eval 47ms] Results written to codeql/cpp-queries/Diagnostics/ExtractedFiles.bqrs.
ExtractionWarnings.ql : [7/60 eval 6ms] Results written to codeql/cpp-queries/Diagnostics/ExtractionWarnings.bqrs.
FailedExtractorInvocations.ql : [8/60 eval 68ms] Results written to codeql/cpp-queries/Diagnostics/FailedExtractorInvocations.bqrs.
BadAdditionOverflowCheck.ql : [9/60 eval 315ms] Results written to codeql/cpp-queries/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.bqrs.
IntMultToLong.ql : [10/60 eval 547ms] Results written to codeql/cpp-queries/Likely Bugs/Arithmetic/IntMultToLong.bqrs.
SignedOverflowCheck.ql : [11/60 eval 887ms] Results written to codeql/cpp-queries/Likely Bugs/Arithmetic/SignedOverflowCheck.bqrs.
CastArrayPointerArithmetic.ql : [12/60 eval 403ms] Results written to codeql/cpp-queries/Likely Bugs/Conversion/CastArrayPointerArithmetic.bqrs.
SnprintfOverflow.ql : [13/60 eval 618ms] Results written to codeql/cpp-queries/Likely Bugs/Format/SnprintfOverflow.bqrs.
WrongNumberOfFormatArguments.ql : [14/60 eval 642ms] Results written to codeql/cpp-queries/Likely Bugs/Format/WrongNumberOfFormatArguments.bqrs.
WrongTypeFormatArguments.ql : [15/60 eval 822ms] Results written to codeql/cpp-queries/Likely Bugs/Format/WrongTypeFormatArguments.bqrs.
AllocaInLoop.ql : [16/60 eval 144ms] Results written to codeql/cpp-queries/Likely Bugs/Memory Management/AllocaInLoop.bqrs.
PointerOverflow.ql : [17/60 eval 66ms] Results written to codeql/cpp-queries/Likely Bugs/Memory Management/PointerOverflow.bqrs.
ReturnStackAllocatedMemory.ql : [18/60 eval 339ms] Results written to codeql/cpp-queries/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.bqrs.
SuspiciousCallToStrncat.ql : [19/60 eval 100ms] Results written to codeql/cpp-queries/Likely Bugs/Memory Management/SuspiciousCallToStrncat.bqrs.
UsingExpiredStackAddress.ql : [20/60 eval 540ms] Results written to codeql/cpp-queries/Likely Bugs/Memory Management/UsingExpiredStackAddress.bqrs.
UnsafeUseOfThis.ql : [21/60 eval 12ms] Results written to codeql/cpp-queries/Likely Bugs/OO/UnsafeUseOfThis.bqrs.
RedundantNullCheckSimple.ql : [22/60 eval 160ms] Results written to codeql/cpp-queries/Likely Bugs/RedundantNullCheckSimple.bqrs.
TooFewArguments.ql : [23/60 eval 49ms] Results written to codeql/cpp-queries/Likely Bugs/Underspecified Functions/TooFewArguments.bqrs.
MemsetMayBeDeleted.ql : [24/60 eval 256ms] Results written to codeql/cpp-queries/Security/CWE/CWE-014/MemsetMayBeDeleted.bqrs.
ExecTainted.ql : [25/60 eval 2.6s] Results written to codeql/cpp-queries/Security/CWE/CWE-078/ExecTainted.bqrs.
CgiXss.ql : [26/60 eval 385ms] Results written to codeql/cpp-queries/Security/CWE/CWE-079/CgiXss.bqrs.
SqlTainted.ql : [27/60 eval 667ms] Results written to codeql/cpp-queries/Security/CWE/CWE-089/SqlTainted.bqrs.
BadlyBoundedWrite.ql : [28/60 eval 530ms] Results written to codeql/cpp-queries/Security/CWE/CWE-120/BadlyBoundedWrite.bqrs.
VeryLikelyOverrunWrite.ql : [29/60 eval 1.3s] Results written to codeql/cpp-queries/Security/CWE/CWE-120/VeryLikelyOverrunWrite.bqrs.
NoSpaceForZeroTerminator.ql : [30/60 eval 513ms] Results written to codeql/cpp-queries/Security/CWE/CWE-131/NoSpaceForZeroTerminator.bqrs.
UncontrolledFormatString.ql : [31/60 eval 2.9s] Results written to codeql/cpp-queries/Security/CWE/CWE-134/UncontrolledFormatString.bqrs.
ArithmeticUncontrolled.ql : [32/60 eval 962ms] Results written to codeql/cpp-queries/Security/CWE/CWE-190/ArithmeticUncontrolled.bqrs.
ComparisonWithWiderType.ql : [33/60 eval 421ms] Results written to codeql/cpp-queries/Security/CWE/CWE-190/ComparisonWithWiderType.bqrs.
UnsignedDifferenceExpressionComparedZero.ql: [34/60 eval 55ms] Results written to codeql/cpp-queries/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.bqrs.
HResultBooleanConversion.ql : [35/60 eval 126ms] Results written to codeql/cpp-queries/Security/CWE/CWE-253/HResultBooleanConversion.bqrs.
CleartextFileWrite.ql : [36/60 eval 848ms] Results written to codeql/cpp-queries/Security/CWE/CWE-311/CleartextFileWrite.bqrs.
CleartextTransmission.ql : [37/60 eval 755ms] Results written to codeql/cpp-queries/Security/CWE/CWE-311/CleartextTransmission.bqrs.
UseOfHttp.ql : [38/60 eval 469ms] Results written to codeql/cpp-queries/Security/CWE/CWE-319/UseOfHttp.bqrs.
InsufficientKeySize.ql : [39/60 eval 365ms] Results written to codeql/cpp-queries/Security/CWE/CWE-326/InsufficientKeySize.bqrs.
BrokenCryptoAlgorithm.ql : [40/60 eval 267ms] Results written to codeql/cpp-queries/Security/CWE/CWE-327/BrokenCryptoAlgorithm.bqrs.
OpenSslHeartbleed.ql : [41/60 eval 47ms] Results written to codeql/cpp-queries/Security/CWE/CWE-327/OpenSslHeartbleed.bqrs.
TOCTOUFilesystemRace.ql : [42/60 eval 300ms] Results written to codeql/cpp-queries/Security/CWE/CWE-367/TOCTOUFilesystemRace.bqrs.
IteratorToExpiredContainer.ql : [43/60 eval 1.2s] Results written to codeql/cpp-queries/Security/CWE/CWE-416/IteratorToExpiredContainer.bqrs.
UseOfStringAfterLifetimeEnds.ql : [44/60 eval 7ms] Results written to codeql/cpp-queries/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.bqrs.
UseOfUniquePointerAfterLifetimeEnds.ql : [45/60 eval 17ms] Results written to codeql/cpp-queries/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.bqrs.
SuspiciousAddWithSizeof.ql : [46/60 eval 59ms] Results written to codeql/cpp-queries/Security/CWE/CWE-468/SuspiciousAddWithSizeof.bqrs.
ExposedSystemData.ql : [47/60 eval 471ms] Results written to codeql/cpp-queries/Security/CWE/CWE-497/ExposedSystemData.bqrs.
XXE.ql : [48/60 eval 438ms] Results written to codeql/cpp-queries/Security/CWE/CWE-611/XXE.bqrs.
DangerousFunctionOverflow.ql : [49/60 eval 8ms] Results written to codeql/cpp-queries/Security/CWE/CWE-676/DangerousFunctionOverflow.bqrs.
DangerousUseOfCin.ql : [50/60 eval 3ms] Results written to codeql/cpp-queries/Security/CWE/CWE-676/DangerousUseOfCin.bqrs.
WcharCharConversion.ql : [51/60 eval 129ms] Results written to codeql/cpp-queries/Security/CWE/CWE-704/WcharCharConversion.bqrs.
OpenCallMissingModeArgument.ql : [52/60 eval 51ms] Results written to codeql/cpp-queries/Security/CWE/CWE-732/OpenCallMissingModeArgument.bqrs.
UnsafeDaclSecurityDescriptor.ql : [53/60 eval 513ms] Results written to codeql/cpp-queries/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.bqrs.
LinesOfCode.ql : [54/60 eval 32ms] Results written to codeql/cpp-queries/Summary/LinesOfCode.bqrs.
LinesOfUserCode.ql : [55/60 eval 603ms] Results written to codeql/cpp-queries/Summary/LinesOfUserCode.bqrs.
CompilerErrors.ql : [56/60 eval 3ms] Results written to codeql/cpp-queries/Telemetry/CompilerErrors.bqrs.
DatabaseQuality.ql : [57/60 eval 108ms] Results written to codeql/cpp-queries/Telemetry/DatabaseQuality.bqrs.
ExtractionMetrics.ql : [58/60 eval 18ms] Results written to codeql/cpp-queries/Telemetry/ExtractionMetrics.bqrs.
MissingIncludes.ql : [59/60 eval 15ms] Results written to codeql/cpp-queries/Telemetry/MissingIncludes.bqrs.
SucceededIncludes.ql : [60/60 eval 1.5s] Results written to codeql/cpp-queries/Telemetry/SucceededIncludes.bqrs.
Shutting down query evaluator.
Interpreting results.
CodeQL scanned 3 out of 3 C/C++ files in this invocation. Typically CodeQL is configured to analyze a single CodeQL language per invocation, so check other invocations to determine overall coverage information.
今回は、CSV形式で出力しました。公式ドキュメントに、CSV出力の説明について書かれているページ「CodeQL CLI の CSV 出力」へのリンクがあります。ここに、出力内容の説明が書かれています。ちょっと日本語訳が微妙なので、タイトルについては少し変更しました。
use_after_free.c だけを見ていきます。7件が error という重要度で検出されています。
それぞれの内容については、"CodeQL”、"検出したクエリ名" で、Web検索すると、CodeQL の公式のページがヒットします。
"Wrong type of arguments to formatting function" について、2件が検出されています。これは、printf関数に関するもので、これは、ビルド時に出ていた警告と同じだと思います。
"Likely overrunning write" について、5件が検出されています。これは、バッファオーバーフローに関するもののようです。scanf("%254s", username); のように、20byte しかないのに、255byte を格納しようとしているところを指摘しているようです。
期待していた Use After Free の指摘は検出されなかったようです。
| 検出したクエリ名 |
クエリの説明 |
重要度 |
警告メッセージ |
パス |
開始行 |
開始列 |
終了行 |
終了列 |
| Wrong type of arguments to formatting function |
Calling a printf-like function with the wrong type of arguments causes unpredictable behavior. |
error |
This format specifier for type 'unsigned int' does not match the argument type 'char *'. |
/use_after_free.c |
27 |
60 |
27 |
67 |
| Wrong type of arguments to formatting function |
Calling a printf-like function with the wrong type of arguments causes unpredictable behavior. |
error |
This format specifier for type 'unsigned int' does not match the argument type 'char *'. |
/use_after_free.c |
30 |
60 |
30 |
67 |
| Wrong type of arguments to formatting function |
Calling a printf-like function with the wrong type of arguments causes unpredictable behavior. |
error |
This format specifier for type 'unsigned int' does not match the argument type 'char *'. |
/use_after_free_fix.c |
26 |
60 |
26 |
67 |
| Wrong type of arguments to formatting function |
Calling a printf-like function with the wrong type of arguments causes unpredictable behavior. |
error |
This format specifier for type 'unsigned int' does not match the argument type 'char *'. |
/use_after_free_fix.c |
29 |
60 |
29 |
67 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free.c |
49 |
32 |
49 |
39 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free.c |
71 |
32 |
71 |
39 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free.c |
107 |
32 |
107 |
41 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free.c |
110 |
32 |
110 |
39 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free.c |
128 |
36 |
128 |
42 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free_fix.c |
48 |
32 |
48 |
39 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free_fix.c |
68 |
32 |
68 |
39 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free_fix.c |
98 |
32 |
98 |
41 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free_fix.c |
101 |
32 |
101 |
39 |
| Likely overrunning write |
Buffer write operations that do not control the length of data written may overflow |
error |
This 'scanf string argument' operation requires 255 bytes but the destination is only 20 bytes. |
/use_after_free_fix.c |
118 |
36 |
118 |
42 |
公式ドキュメントの「CodeQL クエリによるコード分析」では、他にも、様々なクエリの指定方法が説明されています。
CodeQL 分析結果を GitHub にアップロードする
ここでは、CodeQL の分析結果を SARIF形式で出力し、GitHub にアップロードする方法が説明されています。
現状は、この機能を使わないので、割愛します。
おわりに
今回は、CodeQL の基本的な機能を使ってみました。まずは、標準クエリを使ってみましたが、最低限の検出だったような印象です。少なくとも UAF は検出してほしかったところですが、もう少し、実行方法について詳しく知る必要がありそうです。
次回は、もう少し CodeQL CLI の使い方の詳細を理解していく予定です。
最後になりましたが、エンジニアグループのランキングに参加中です。
気楽にポチッとよろしくお願いいたします🙇
今回は以上です!
最後までお読みいただき、ありがとうございました。