🎃

どインフラな私でもBedrockでコードレビューができるか試してみた

2023/10/11に公開

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな吉井 亮です。

Generative AI には疎くて3周くらい遅れています。3周遅れているのに満腹感もあったりします。
そんな私ですが、業務の何かで Generative AI を使えないかと日々アンテナ低く張っています。AWS ブログで私でも使えそうなソリューションが紹介されていたので試してみました。

やってみた

ソリューションの概要や手順は上のブログで説明されています。詳細に知りたい方はそちらを参照ください。

CodeCommit リポジトリ作成

マネジメントコンソールで CodeCommit を開き リポジトリを作成 をクリックします。

Amazon CodeGuru Reviewer for Java and Python を有効にする にチェックを入れ、リポジトリを作成します。

img

サンプルコード Push

AWS のサンプル Amazon CodeGuru Reviewer Python Detector repository を使います。
サンプルコードを CodeCommit リポジトリに push します。
your-regionyour-repo-name はご自身の環境に置き換えてください。
AWS ブログでは https でしたが私の環境ではうまくいかなかったので GRC を使っています。

git clone https://github.com/aws-samples/amazon-codeguru-reviewer-python-detectors.git
cd amazon-codeguru-reviewer-python-detectors/
git remote add codecommit codecommit::your-region://your-repo-name

git push codecommit main:main

CodeGuru でコードレビュー

次に CodeGuru を開きます。

前の手順で作成したリポジトリが関連付けられていることを確認します。

img

左ペインから コードレビュー をクリックします。

フルリポジトリ分析を作成 をクリックします。

以下の値を入力し、フルリポジトリ分析を作成 をクリックします。

  • 関連付けられたリポジトリ: 前の手順で作成したリポジトリ
  • ソースブランチ: スキャンするブランチ
  • コードレビュー名: 識別しやすい名称

コードレビュー結果の表示

しばらく待つとステータスが Completed になりました。
コードレビュー名をクリックすると詳細画面に遷移します。
サンプルコードを使うと推奨事項が126個ピックアップされるはずです。

AWS ブログの例に従って一番上の「hashlib_constructor.py」を Bedrock で遊んでみます。

Bedrock

Bedrock を開きます。
左ペインから Text をクリックします。

モデルを選択します。使うモデルは Anthropic Claude V2 にしました。カタカナで書くと「クロード」だそうです。
img

右側にある Inference configuration をよしなに設定します。(スクショは執筆日時点のデフォルト値)
img

プロンプトを入力します。初めて ChatGPT を触った日を思い出すドキドキ感。

入力

Source Code:
def constructor_noncompliant():
    import hashlib

    text = "ExampleString"

    # Noncompliant: uses the new() constructor instead of the hashlib
    # constructor, which is slower.
    result = hashlib.new('sha256', text.encode())

    print("The hexadecimal equivalent of SHA256 is : ")
    print(result.hexdigest())

Code Analysis Finding: 
The constructors for the hashlib module are faster than new(). We recommend using hashlib.sha256() instead.

Request:
Code Analysis Finding に示した内容をもとに修正したコードを教えてください

この3つの段落がコツのようです。

Source Code、CodeGuru コードレビューで指摘されたコードを貼り付けています。

Code Analysis Finding、CodeGuru コードレビューで指摘された解析結果を貼り付けてします。

Request、日本語いけました。

Run ボタンをクリックします。

レスポンス

Assistant:
 コード解析の結果に基づいて、コードを以下のように修正します。

```python
import hashlib

text = "ExampleString"

# 使用するハッシュアルゴリズムを明示的に指定
result = hashlib.sha256(text.encode()) 

print("The hexadecimal equivalent of SHA256 is :")
print(result.hexdigest())
```

主な変更点:

- hashlib.new() の代わりに、hashlib.sha256() を使用するようにした。
- ハッシュアルゴリズムを明示的に指定することで、より高速に動作する。

このようにhashlibモジュールのコンストラクタを直接使用することで、new() メソッドを呼び出すオーバーヘッドを避け、パフォーマンスを改善できます。

おお! Request に書いた通り修正コードを提示してくれました。主な変更点まで示してくれて親切です。
ここまでは AWS ブログと同じ内容です。

もう少しだけ遊んでみた

ちょっとした感動を味わいました。
もう少し遊んでみます。CodeGuru コードレビューのタイプをセキュリティに絞って表示された指摘をピックアップしてみました。
clear_text_credentials_non_compliant.py というファイルで遊びます。

このファイルの危険性は何でしょうか?

入力

Source Code:
# {fact rule=clear-text-credentials@v1.0 defects=1}
PASSWORD_HASHERS = [
        # Noncompliant: uses non-standard or insecure password hashers.
        "django.contrib.auth.hashers.MD5PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2PasswordHasher"
    ]
# {/fact}

Code Analysis Finding: 
Your code uses a non-standard or insecure password hashers, which could allow an attacker to gain access to protected data. To protect your code, use a standard and secure hasher like MyPBKDF2PasswordHasher, PBKDF2PasswordHasher, PBKDF2SHA1PasswordHasher, Argon2PasswordHasher, BCryptSHA256PasswordHasher and avoid the use of following hashes:SHA1PasswordHasher, MD5PasswordHasher, UnsaltedSHA1PasswordHasher, UnsaltedMD5PasswordHasher, CryptPasswordHasher. Do not create a custom hasher.
Credentials that are stored in clear text in memory or written to log files can be intercepted by a malicious actor.

Request:
Code Analysis Finding に示したコード解析がされています。このコードの危険性を教えてください。

レスポンス

このコードの問題点は、セキュリティの脆弱なパスワードハッシュアルゴリズムを使用していることです。

具体的には、MD5とPBKDF2の2つのハッシュアルゴリズムが使用されています。

MD5はもはやセキュアではないと考えられているハッシュ関数です。衝突攻撃に弱く、パスワードのハッシュには適していません。

PBKDF2はセキュアなハッシュ関数ですが、デフォルトの設定では十分なコストがかけられていないため、ブルートフォース攻撃に弱くなります。

したがって、このコードはパスワードを危険にさらしています。攻撃者がハッシュを突破し、パスワードを取得する可能性があります。

代わりに、Argon2、BCrypt、PBKDF2(適切な設定)などの最新でセキュアなハッシュアルゴリズムを使用するべきです。また、パスワードやその他の機密情報は決してプレーンテキストで保存せず、必ずハッシュ化するべきです。

問題点を詳しく教えてくれました。これならコードを書いた人にも理解してもらう説明ができそうです。
感謝しつつコードを修正してもらいましょう。

入力

ありがとうございます。最新のセキュアなハッシュアルゴリズムを使用した修正済みコードを教えてください。

レスポンス

 はい、セキュアなハッシュを使用した修正済みのコード例を示します。

```python
from django.contrib.auth.hashers import Argon2PasswordHasher

PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
]
```

ここでは、最新のArgon2とBCryptを使用しています。

Argon2はメモリハードでコスト調整可能な最新のアルゴリズムです。 

BCryptSHA256はBCryptにSHA-256を組み合わせた安全なハッシュです。

PBKDF2もまだセキュアではありますが、適切なiteration回数を設定する必要があります。

これらのアルゴリズムを組み合わせることで、強固なパスワード保護が実現できます。

必ずsaltもランダムに生成し、ハッシュ計算時に使用するようにしてください。

このように最新のアルゴリズムを利用することで、パスワードの安全性が大幅に向上します。

なるほど、最新のアルゴリズムを使ったコードを提示してくれました。
salt をランダムにしろ、というアドバイスまで貰いました。
そもそも修正しないとどのような危険があるのでしょうか? 聞いてみましょう。

入力

修正済みコードの提示ありがとうございます。
修正前のコードのままだとどのような攻撃を受けますか?具体例を教えてください。

レスポンス

修正前のコードがそのまま利用された場合、以下のような攻撃を受ける可能性があります。

- レインボーテーブル攻撃
MD5やSHA-1などのハッシュは高速に計算できるため、事前計算されたハッシュ値のテーブル(レインボーテーブル)を用意することで、ハッシュ値から原文を高速lookupできます。攻撃者はユーザーのハッシュを取得した上で、レインボーテーブルを用いて元のパスワードを簡単に特定できてしまいます。

- ブルートフォース攻撃
単純な列挙攻撃ですが、計算資源が豊富な攻撃者であれば、総当たりでパスワードの候補を生成し、ハッシュとの照合を行うことでパスワードを特定できます。コストのかからないハッシュでは防ぎきれません。

- パスワードリスト攻撃
一般的なパスワードの辞書を用意し、それらのハッシュ値を事前計算しておきます。ユーザーのハッシュ値と照合することで、パスワードを特定できる可能性があります。

- 脆弱性を突く攻撃
MD5やSHA-1には衝突耐性の脆弱性があるため、意図的に衝突ハッシュ値を生成し、システムを欺くことができます。

したがって、最新のアルゴリズムを用い、適切に設定されたハッシュ関数を利用することがセキュリティ確保には不可欠です。

受ける可能性がある攻撃をリストしてくれました。
修正前のままだと本番環境へデプロイできない、という判断ができそうであります。修正したコードで PR 出し直してみようかなという気持ちにさせます。

まとめ

開発経験が無い私でも CodeGuru と Bedrock を使えばある程度のコードレビューはできそうです。
どインフラの立場から考えると、重大な問題が発生した際にコードのどこに原因があるか探す時間が短縮できそうです。セキュリティ解析にも使えますね。
先行して Generative AI を活用している人に少しでも追いついていきたいものです。

参考

What is Amazon CodeGuru Reviewer?
What is Amazon CodeGuru Security?
Claude

Discussion