はじめに
本記事でやること。
- CodeQL を導入
- 脆弱なアプリケーションに対してのセキュリティテスト(XXEを検出)
- 検出結果を見てみる
CodeQL とは
CodeQL は SAST(Static application security testing) というセキュリティテスト手法を実現するためのツールです。
本ブログで何度か取りあげた GitHub Code Scanning も SAST に属しているセキュリティテスト手法です。
GitHubのCode Scanningを使ってみる・GitHubのCode Scanningを使ってみる パート2
そして GitHub Code Scanning は CodeQLの技術が利用されています。
CodeQL を使うメリットとしてはローカルPCに導入して利用することができるため、GitHubなどで管理していないソースコードに対してもセキュリティテストを実施することができます。
本記事では CodeQL をローカルPC上に導入し、脆弱性を含んだサンプルアプリケーションに対してセキュリティテストを行うまでを紹介します。
※本記事の情報は2021年2月時点のものです。
サポート言語
本記事では Javaで作成したアプリケーションを対象にセキュリティテストを実施しますが、CodeQL でサポートされている言語は以下の通りです。
- C/C++
- C#
- Golang
- Java
- JavaScript
- Python
- TypeScript
バージョンによってはサポート外のものもありますので詳細は公式ドキュメント(Supported languages and frameworks — CodeQL)をご覧ください。
準備
検証環境
- MacOS 10.15.7
- Java (AdoptOpenJDK) 11
本記事では以下のツールを導入して検証していきます。
ツール・アプリケーション | 簡単な説明 |
---|---|
CodeQL CLI | CodeQL のコマンドラインツールです。 バージョン: 2.3.4 |
CodeQL query | セキュリティテストに必要なクエリが保存されています。 バージョン: 1.26.0 |
検査対象アプリケーション | XXE の脆弱性を含んでいる Spring Boot 製のアプリケーションです。 motikan2010/GitHub-code-scanning-Test |
私の環境では CodeQL CLI 2.4.3 を使った場合に "CodeQLデータベースの生成" が上手くいかなかったので、少し古いバージョンを利用しています。
検証環境の構築
検証に使うツールは全て GitHub にありますので、それらをダウンロードしていきます。
■ 作業用ディレクトリを作成 $ mkdir codeql_work $ cd codeql_work/ ■ 検査対象アプリケーションのダウンロード $ git clone -b feature/xml-external-entity git@github.com:motikan2010/GitHub-code-scanning-Test.git ■ CodeQL CLI のダウンロード (v2.3.4 リリース日:2020/12/17) $ wget https://github.com/github/codeql-cli-binaries/releases/download/v2.3.4/codeql-osx64.zip $ unzip codeql-osx64.zip $ rm -f codeql-osx64.zip ■ CodeQL のダウンロード (v1.26.0 リリース日:2020/12/17) $ git clone -b v1.26.0 https://github.com/github/codeql.git ql ■ 作業用ディレクトリの状態 ~/Desktop/codeql_work $ ll total 0 drwxr-xr-x 12 motikan2010 staff 384 2 7 14:58 GitHub-code-scanning-Test drwxr-xr-x 18 motikan2010 staff 576 12 16 01:15 codeql drwxr-xr-x 25 motikan2010 staff 800 2 7 15:01 ql
CodeQL CLI の動作確認 (バージョンの表示)
CodeQL CLI が正常に動作するかバージョンを表示するコマンドを実行します。
$ cd codeql $ ./codeql version --format=json
{ "productName" : "CodeQL", "vendor" : "GitHub", "version" : "2.3.4", "sha" : "ff8bc627f2f24adc6ea19c838237d80a8f24a41f", "branches" : [ "codeql-cli-2.3.4" ], "copyright" : "Copyright (C) 2019-2020 GitHub, Inc.", "unpackedLocation" : "/Users/motikan2010/Desktop/codeql_work/codeql" }
動作確認
スキャンは3ステップで行えます。
- スキャン対象のソースコードを元に CodeQLデータベースの生成
- 「1.」 のデータベースに対して CodeQLクエリの実行
- スキャン結果の表示
CodeQLデータベースの生成
CodeQLデータベースの生成は codeql database create
コマンドで実行できます。
Creating CodeQL databases — CodeQL
$ ./codeql database create -l=java -s ../GitHub-code-scanning-Test codeql_db
コマンド実行時の出力です。テスト対象のアプリケーションをビルドしているようです。
Initializing database at /Users/motikan2010/Desktop/codeql_work/codeql/codeql_db. Running command [/Users/motikan2010/Desktop/codeql_work/codeql/java/tools/autobuild.sh] in /Users/motikan2010/Desktop/codeql_work/GitHub-code-scanning-Test. [2021-02-07 15:19:30] [build] [2021-02-07 15:19:30] Build directory is /Users/motikan2010/Desktop/codeql_work/GitHub-code-scanning-Test/. [2021-02-07 15:19:30] [build] [2021-02-07 15:19:30] [autobuild] > chmod +x gradlew [2021-02-07 15:19:30] [build] [2021-02-07 15:19:30] [autobuild] > ./gradlew -Dorg.gradle.caching=false --no-daemon -S clean [2021-02-07 15:19:34] [build] [2021-02-07 15:19:34] [autobuild] To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/6.6.1/userguide/gradle_daemon.html. [2021-02-07 15:19:36] [build] [2021-02-07 15:19:36] [autobuild] Daemon will be stopped at the end of the build stopping after processing [2021-02-07 15:19:41] [build] [2021-02-07 15:19:41] [autobuild] > Task :clean UP-TO-DATE [2021-02-07 15:19:41] [build] [2021-02-07 15:19:41] [autobuild] BUILD SUCCESSFUL in 8s [2021-02-07 15:19:41] [build] [2021-02-07 15:19:41] [autobuild] 1 actionable task: 1 up-to-date [2021-02-07 15:19:41] [build] [2021-02-07 15:19:41] [autobuild] > ./gradlew -Dorg.gradle.caching=false --no-daemon -S testClasses [2021-02-07 15:19:43] [build] [2021-02-07 15:19:43] [autobuild] To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/6.6.1/userguide/gradle_daemon.html. [2021-02-07 15:19:45] [build] [2021-02-07 15:19:45] [autobuild] Daemon will be stopped at the end of the build stopping after processing [2021-02-07 15:20:02] [build] [2021-02-07 15:20:02] [autobuild] > Task :compileJava [2021-02-07 15:20:02] [build] [2021-02-07 15:20:02] [autobuild] > Task :processResources [2021-02-07 15:20:02] [build] [2021-02-07 15:20:02] [autobuild] > Task :classes [2021-02-07 15:20:06] [build] [2021-02-07 15:20:06] [autobuild] > Task :compileTestJava [2021-02-07 15:20:06] [build] [2021-02-07 15:20:06] [autobuild] > Task :processTestResources NO-SOURCE [2021-02-07 15:20:06] [build] [2021-02-07 15:20:06] [autobuild] > Task :testClasses [2021-02-07 15:20:07] [build] [2021-02-07 15:20:07] [autobuild] BUILD SUCCESSFUL in 24s [2021-02-07 15:20:07] [build] [2021-02-07 15:20:07] [autobuild] 3 actionable tasks: 3 executed Finalizing database at /Users/motikan2010/Desktop/codeql_work/codeql/codeql_db. [2021-02-07 15:20:09] [build-err] Scanning for files in /Users/motikan2010/Desktop/codeql_work/GitHub-code-scanning-Test... Successfully created database at /Users/motikan2010/Desktop/codeql_work/codeql/codeql_db.
コマンド実行後、"codeql_db"というディレクトリが作成されます。 CodeQLデータベースの作成が正常に行われた場合のディレクトリの中身は以下の通りです。
$ ls -l codeql_db total 16 -rw-r--r-- 1 motikan2010 staff 136 2 7 15:20 codeql-database.yml drwxr-xr-x 5 motikan2010 staff 160 2 7 15:20 db-java drwxr-xr-x 15 motikan2010 staff 480 2 7 15:24 log drwxr-xr-x 3 motikan2010 staff 96 2 7 15:23 results -rw------- 1 motikan2010 staff 2172 2 7 15:20 src.zip
脆弱性の検出
スキャンは codeql database analyze
コマンドで実行できます。(database analyze — CLI manual)
検出対象の脆弱性は以下の通りです。
codeql/java/ql/src/Security/CWE at main · github/codeql
CWE 識別子 | 概要 (JVN iPedia) |
---|---|
CWE-20 | 不適切な入力確認 |
CWE-22 | パス・トラバーサル |
CWE-78 | OSコマンドインジェクション |
CWE-79 | クロスサイトスクリプティング |
CWE-89 | SQLインジェクション |
CWE-90 | LDAP インジェクション |
CWE-94 | コード・インジェクション |
CWE-113 | HTTP レスポンスの分割 |
CWE-129 | 配列インデックスの不適切な検証 |
CWE-134 | 書式文字列の問題 |
CWE-190 | 整数オーバーフローまたはラップアラウンド |
CWE-209 | エラーメッセージによる情報漏えい |
CWE-312 | 重要な情報の平文保存 |
CWE-319 | 重要な情報の平文での送信 |
CWE-327 | 不完全、または危険な暗号アルゴリズムの使用 |
CWE-335 | PRNG におけるシードの不正な使用 |
CWE-338 | 暗号における脆弱な PRNG の使用 |
CWE-352 | クロスサイトリクエストフォージェリ |
CWE-367 | Time-of-check Time-of-use (TOCTOU) 競合状態 |
CWE-421 | Race Condition During Access to Alternate Channel (by MITRE) |
CWE-502 | 信頼できないデータのデシリアライゼーション |
CWE-601 | オープンリダイレクト |
CWE-611 | XML 外部エンティティ参照の不適切な制限 |
CWE-614 | Sensitive Cookie in HTTPS Session Without 'Secure' Attribute (by MITRE) |
CWE-676 | Use of Potentially Dangerous Function (by MITRE) |
CWE-681 | 数値型間の変換の誤り |
CWE-732 | 重要なリソースに対する不適切なパーミッションの割り当て |
CWE-798 | ハードコードされた認証情報の使用 |
CWE-807 | Reliance on Untrusted Inputs in a Security Decision (by MITRE) |
CWE-829 | 信頼性のない制御領域からの機能の組み込み |
CWE-833 | Deadlock (by MITRE) |
CWE-835 | 無限ループ |
XXE の検査 ~ 検出されることの確認 ~
全ての脆弱性を検査対象にすると時間が掛かってしまうため、今回は「XXE攻撃(XML eXternal Entity attack)」のみを対象に検査します。
(全てを検査対象にした場合、10分ほど時間が掛かりました。)
検査の実施 ~ CSV形式で出力 ~
テスト結果はファイルに出力されるようになっています。ファイル形式は --format
で指定します。
CSV形式で出力した例です。
■ 検査の実行 $ ./codeql database analyze "codeql_db" \ ../ql/java/ql/src/Security/CWE/CWE-611/ \ --format csv --output xxe_result.csv ■ 検査結果の表示 $ cat xxe_result.csv "Resolving XML external entity in user-controlled data","Parsing user-controlled XML documents and allowing expansion of external entity references may lead to disclosure of confidential data or denial of service.","error","Unsafe parsing of XML file from [[""user input""|""relative:///src/main/java/com/motikan2010/github_code_scanning_test/controller/XxeController.java:26:52:26:92""]].","/src/main/java/com/motikan2010/github_code_scanning_test/controller/XxeController.java","29","41","29","79"
1行のCSVファイルとして結果が出力されました。
少々見づらいですが結果内容に脆弱性が見つかったファイルや行数の記載がされていることが確認できます。
検査の実施 ~ SARIFで出力 ~
次は SARIFで出力してみます。
SARIFという単語は馴染みありませんが「Static Analysis Results Interchange Format」の略称であり、
SARIF 標準は、静的分析ツールが結果を共有する方法を合理化するために使用されます。
とのことです。
(当初私は SARIF"形式"と書いていましたが、「Format」の"F"なので明らかな誤りですね...)
SARIF の見方は下のドキュメントが参考になります。
docs.github.com
■ 検査の実行 $ ./codeql database analyze "codeql_db" \ ../ql/java/ql/src/Security/CWE/CWE-611/ \ --format=sarif-latest --sarif-multicause-markdown --output=xxe_result.sarif --no-sarif-add-snippets
中身はJSON形式のようです。
$ cat xxe_result.sarif | jq .
結果を見てみると以下のような記載があります。
"locations": [ { "physicalLocation": { "artifactLocation": { "uri": "src/main/java/com/motikan2010/github_code_scanning_test/controller/XxeController.java", "uriBaseId": "%SRCROOT%", "index": 0 }, "region": { "startLine": 29, "startColumn": 41, "endColumn": 80 } } } ],
これはソースコード上で脆弱性を存在している部分を示しています。
指摘されたソースコードは下の画像です。
確かに脆弱性となっている部分です。
RCE の検査 ~ 検出されないことの確認 ~
次は RCE を検査し、脆弱性が検出されないことを確認します。
■ 検査の実行 $ ./codeql database analyze "codeql_db" \ ../ql/java/ql/src/Security/CWE/CWE-078/ \ --format csv --output rce_result.csv ■ 検査結果の表示 $ cat rce_result.csv (出力なし)
脆弱性が検出されなかったので、検査結果が格納されるファイルは空となりました。
(ツール使用当初は検査が失敗しているのではと疑っていました・・・)
まとめ
CodeQL。簡単。無料。 楽しい。
お金ないけどプライベートリポジトリに対して SAST したいよという方にはオススメです。
参考
- About CodeQL — CodeQL
- GitHubがセキュリティのためのコード分析ツールSemmleを買収 | TechCrunch Japan
- 共通脆弱性タイプ一覧CWE概説:IPA 独立行政法人 情報処理推進機構
更新履歴
- 2021年2月7日 新規作成
- 2021年2月8日 CWE記載など