最近いくつかのサイトをテストしました。最初にログインフォームが表示され、パケットキャプチャを行ったところ、ユーザー名とパスワードが暗号化されていました。形式は以下の通りです:
![]()
フロントエンドでよく使用される暗号化方式は aes で、rsa を使って aes の key を暗号化し、その後 aes でデータを暗号化して送信するケースもありました。
上の図は aes を直接使用した暗号化の例です。
ブラウザを通じて暗号化された js ファイルを見つけることができ、通常はソースコード / ソースの中で js ディレクトリを見つけます。このサイトは比較的シンプルで、crypto-js.js ファイルを直接使用しており、開くと aes の key と暗号化方式がすぐに確認できます。

上の図からわかるように、key が与えられ、モードは ECB、pad は Pkcs7 です。この情報があれば、データを解読することができます。
burpsuite のautodecoderプラグインを使用して、今回の解読もこのプラグインを使いました。

autoDecoder には 4 つのタブがあります。

最初の options タブは、いくつかの設定です。
- モジュール制御:burp のどのモジュールで autodecoder の暗号化 / 復号化を実行するか
- 暗号化 / 復号化オプション:暗号化 / 復号化の方法を制御し、内蔵アルゴリズムを使用するか、インターフェースを使用するか

後のオプションは最初のオプションに関連しており、インターフェース暗号化 / 復号化を選択した場合、データヘッダーを処理するまたはリクエスト応答の異なる暗号化/復号化オプションを設定できます。
- 暗号化 / 復号化設定:暗号化ドメインを必ず記入する必要があります。そうしないと autodecoder タブに表示されません。他はデフォルトで構いません。
- 設定が完了したら、必ず
保存してください。
2 つ目のタブは autodecoder の内蔵アルゴリズムによる暗号化 / 復号化です。

3 つ目のタブはインターフェースによる暗号化 / 復号化です。
インターフェースを設定する必要があり、インターフェースは作者が提供したものを参考にできます。リクエストパラメータをカスタマイズする必要がある場合、大部分はインターフェースによる暗号化 / 復号化を使用する必要があります。

今回遭遇したように、2 つのパラメータが存在する場合、内蔵のアルゴリズムによる暗号化 / 復号化では要件を満たすのが難しくなります。
![]()
内蔵のアルゴリズムによる暗号化 / 復号化には正規表現パターンマッチングがあり、1 つの暗号化された文字列(name)のみをマッチさせることができ、pwd パラメータの暗号化された文字列を抽出することはできません。
4 つ目のタブはリクエスト応答の置換です。
権限のない脆弱性をテストするために使用でき、burp の Autorize プラグインと同じように感じますが、使用したことはありません。

autodecoder プラグインについて簡単に紹介しました。
作者のスクリプトを少し変更し、現在テストしているサイトに適応しました。
from flask import Flask, request
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
import base64
from urllib.parse import parse_qs,quote
import hashlib
def aes_encrypt(key, data):
cipher = AES.new(key, AES.MODE_ECB)
padded_data = pad(data.encode(), AES.block_size)
cipher_text = cipher.encrypt(padded_data)
return base64.b64encode(cipher_text).decode()
def aes_decrypt(key, data):
cipher = AES.new(key, AES.MODE_ECB)
decrypted_data = cipher.decrypt(base64.b64decode(data))
unpadded_data = unpad(decrypted_data, AES.block_size)
return unpadded_data.decode()
app = Flask(__name__)
@app.route('/encode', methods=["POST"])
def encrypt():
key = b'ここにaesのkeyを書く' # 16バイトのkey
str1 = '123'
param = request.form.get('dataBody') # POSTパラメータを取得
md5value = param + str1
param1 = quote(aes_encrypt(key,param))
param2 = hashlib.md5(md5value.encode()).hexdigest()
return f"Param={param1}&Autograph={param2}"
'''
data = json.loads(param)
encrypted_id = aes_encrypt(key, data["id"])
encry_param = param.replace(data["id"], encrypted_id)
return base64.b64decode(encry_param.encode()).decode()
'''
@app.route('/decode', methods=["POST"])
def decrypt():
key = b'ここにaesのkeyを書く'
param = request.form.get('dataBody')
print('param: ',param)
parsed_params = parse_qs(param)
print(parsed_params)
# 2つのパラメータを解読、nameとpwd
decrypted_name = aes_decrypt(key, parsed_params["name"][0])
decrypted_value = aes_decrypt(key, parsed_params["pwd"][0])
# 2つのパラメータを含むJSONレスポンスを返す
return f"name={decrypted_name}&pwd={decrypted_value}"
if __name__ == '__main__':
app.debug = True # デバッグモードを設定、運用時はオフにすることを忘れずに
app.run(host="0.0.0.0", port=8888)
スクリプトを書いたので、実行します。プログラムは 127.0.0.1:8888 でリッスンします。
python3 aed_decode.py
まずはパケットをキャプチャしてテストしてみてください。成功裏に解読できたことが確認できます。

現在の設定は以下の通りです:


設定が完了した後、パケットをキャプチャすると、各リクエストが自動的に解読されているのがわかります。autoDecoder タブで解読内容を確認できます。

また、burp の intruder モジュールを利用してログインブルートフォース攻撃を開始することもできます。
ここで、非対称暗号、対称暗号、署名、再送信禁止のテストシナリオを含むフロントエンド暗号化対抗練習用の靶場をお勧めします。AES、DES、RSA など、ペネトレーションテストの練習に使用されます。