今回はSASTを触ってみました。
SAST(Static Application Security Test) とは
静的にプログラムのセキュリティをチェックしてくれるツールです。 コマンドで実行することで、ソースコードがセキュアかどうかの確認をしてくれます。
CI/CDに組み込みやすく、PullRequestの作成時など特定のタイミングでユニットテストと同じように実行することが可能。エンジニアのミスでセキュアではない設定が組み込まれることを防ぐことができます。
bandit
Bandit is a tool designed to find common security issues in Python code. To do this Bandit processes each file, builds an AST from it, and runs appropriate plugins against the AST nodes. Once Bandit has finished scanning all the files it generates a report. Bandit was originally developed within the OpenStack Security Project and later rehomed to PyCQA.
日本語訳(Google翻訳)
Banditは、Pythonコードの一般的なセキュリティ問題を見つけるために設計されたツールです。 これを行うために、Banditは各ファイルを処理し、そこからASTを構築し、ASTノードに対して適切なプラグインを実行します。 Banditがすべてのファイルのスキャンを終了すると、レポートが生成されます。 Banditは元々OpenStackSecurity Project内で開発され、後にPyCQAにリホームされました。
インストール
pip install bandit
実行結果
試しに手元にあったvaltan
という、Djangoプロジェクトに対してかけてみました。
実行コマンド
$ bandit -r ./
実行結果
実行した結果は下記です。 一つ一つの指摘事項に対して、リンクが貼られておりとてもみやすい。 基本的には設定ファイルへの指摘が多いですが、エンジニアが忘れてしまいそうな初期設定のままリリースというのを止めてくれそうなツールですね。
[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.7.2 Run started:2021-07-04 04:42:05.329107 Test results: >> Issue: [B105:hardcoded_password_string] Possible hardcoded password: '★★★★★★★★★' Severity: Low Confidence: Medium Location: ./django_manage/settings.py:23 More Info: https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html 22 # SECURITY WARNING: keep the secret key used in production secret! 23 SECRET_KEY = '★★★★★★★★★' 24 25 # SECURITY WARNING: don't run with debug turned on in production! 26 DEBUG = True -------------------------------------------------- >> Issue: [B404:blacklist] Consider possible security implications associated with subprocess module. Severity: Low Confidence: High Location: ./valtan/models/server.py:5 More Info: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html#b404-import-subprocess 4 import threading 5 import subprocess 6 7 8 class Server(): -------------------------------------------------- >> Issue: [B404:blacklist] Consider possible security implications associated with subprocess module. Severity: Low Confidence: High Location: ./valtan/tool/client.py:6 More Info: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html#b404-import-subprocess 5 import threading 6 import subprocess 7 8 # global verbs 9 listen = False -------------------------------------------------- >> 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: ./valtan/tool/client.py:46 More Info: https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html 45 else: 46 assert False, "Unhandled Option" 47 -------------------------------------------------- >> Issue: [B104:hardcoded_bind_all_interfaces] Possible binding to all interfaces. Severity: Medium Confidence: Medium Location: ./valtan/tool/client.py:56 More Info: https://bandit.readthedocs.io/en/latest/plugins/b104_hardcoded_bind_all_interfaces.html 55 if not len(target): 56 target = "0.0.0.0" 57 -------------------------------------------------- >> Issue: [B602:subprocess_popen_with_shell_equals_true] subprocess call with shell=True identified, security issue. Severity: High Confidence: High Location: ./valtan/tool/client.py:76 More Info: https://bandit.readthedocs.io/en/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html 75 output = subprocess.check_output( 76 command, stderr=subprocess.STDOUT, shell=True) 77 except: 78 output = "Failed To excute command.\r\n" -------------------------------------------------- >> Issue: [B310:blacklist] Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected. Severity: Medium Confidence: High Location: ./valtan/views/check_vulnerability.py:25 More Info: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html#b310-urllib-urlopen 24 try: 25 with urllib.request.urlopen(check_request) as response: 26 header_info = response.info() -------------------------------------------------- Code scanned: Total lines of code: 519 Total lines skipped (#nosec): 0 Run metrics: Total issues (by severity): Undefined: 0.0 Low: 4.0 Medium: 2.0 High: 1.0 Total issues (by confidence): Undefined: 0.0 Low: 0.0 Medium: 2.0 High: 5.0 Files skipped (0):