yiskw note

機械学習やプログラミングについて気まぐれで書きます

【Python】Banditを使用して,コードのセキュリティ上の問題を検知する


概要

今回はPythonのStatic Application Security Testing (SAST)を実施してくれるツールであるbanditを使用してみました.
banditを用いることで,Pythonのコード上に潜むセキュリティの問題を検知することが可能です.
またpre-commitで使用することもでき,コミット時などに簡単にチェックを行うこともできます.

banditとは

banditとは,PythonのStatic Application Security Testing (SAST)を実施してくれるツールで,
Pythonのコード上に潜むセキュリティの脆弱性などを検知してくれるます.
特に複雑な設定も必要なく,簡単にコードの検査ができ,扱いやすいのも特徴です.

使い方

まずbanditをインストールします.pipで簡単にインストールできます.

pip install bandit

インストール後は以下を実行するだけです.

bandit -r path/to/your/code

-rは,--recursiveの略で,これをつけることで,ディレクトリに対して,再起的に実行することができます.
またその他のオプションとして,-fでファイル形式を指定し,-oでそのファイルの保存先をしているすることも可能です.

bandit -r -f json -o ./resullt.json .

使ってみる

以下のコード(sample.py)に対して,banditを実行してみます.

import yaml


class Sample():
    def __init__(self, password: str, data_path: str):
        self.password = password
        assert isinstane(password, int)

        if password == "root":
            self.is_admin = True
        else:
            self.is_admin = False
        
        self.data = yaml.load(data_path)

結果

$ bandit sample.py
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    running on Python 3.9.1
[node_visitor]  INFO    Unable to find qualified name for module: sample.py
Run started:2021-12-31 05:42:17.592097

Test results:
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   Location: sample.py:7:8
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html
6           self.password = password
7           assert isinstane(password, int)
8   
9           if password == "root":

--------------------------------------------------
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: 'root'
   Severity: Low   Confidence: Medium
   Location: sample.py:9:23
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html
8   
9           if password == "root":
10              self.is_admin = True

--------------------------------------------------
>> Issue: [B506:yaml_load] Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load().
   Severity: Medium   Confidence: High
   Location: sample.py:14:20
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b506_yaml_load.html
13          
14          self.data = yaml.load(data_path)
15  

--------------------------------------------------

Code scanned:
    Total lines of code: 10
    Total lines skipped (#nosec): 0

Run metrics:
    Total issues (by severity):
        Undefined: 0.0
        Low: 2.0
        Medium: 1.0
        High: 0.0
    Total issues (by confidence):
        Undefined: 0.0
        Low: 0.0
        Medium: 1.0
        High: 2.0
Files skipped (0):

こんな感じでコードのセキュリティ的な問題点を指摘してくれました.
assert文を使うな,やパスワードのハードコードだけでなく,yaml.load脆弱性についても指摘してくれています.

pre-commitで使用する

最後にgitのフックスクリプトを簡単に管理できるpre-commitを使用して,コミット前にbanditによる検査を実施するようにしてみます.
pre-commitのより詳しい使い方に関しては,以下の記事を参照してください.

zenn.dev

まず,pre-commitをインストールします.

pip install pre-commit

次にgit配下のレポジトリにて以下を実行します.

pre-commit install

.pre-commit-config.yamlという名前のファイルを作成し,以下を記述します.

repos:
- repo: https://github.com/PyCQA/bandit
  rev: 1.7.0
  hooks:
  - id: bandit

先程のsample.pyをコミットしてみます.

$ git add .
$ git commit -m 'test'
[INFO] Initializing environment for https://github.com/PyCQA/bandit.
[INFO] Installing environment for https://github.com/PyCQA/bandit.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
bandit...................................................................Failed
- hook id: bandit
- exit code: 1

[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    running on Python 3.9.1
[node_visitor]  INFO    Unable to find qualified name for module: sample.py
Run started:2021-12-31 06:01:41.575370

Test results:
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   Location: sample.py:7
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html
6           self.password = password
7           assert isinstane(password, int)
8   
9           if password == "root":

(以下略)

コミット時にBanditを実行させて,コード上のセキュリティの問題を発見することができました!
その都度自分でbanditコマンドを実行させる必要がなく,非常に便利そうです

まとめ

PythonのStatic Application Security Testing (SAST)を実施してくれるbanditを使用してみました.
またpre-commitと組み合わせることで,自動的にPythonのコード上に潜むセキュリティの問題を検知することも可能です.
非常に手軽なので,日頃の開発にも導入していきたいです.

参考