banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

autodecode aes復号化浸透実戦の記録

最近いくつかのサイトをテストしました。最初にログインフォームがあり、パケットキャプチャ後にユーザー名とパスワードが暗号化されていました。形式は以下の通りです:

Pasted image 20241129200536

フロントエンドでよく使用される暗号化方式は aes で、aes のキーを rsa で暗号化し、その後 aes でデータを暗号化して送信するケースもありました。

上の図は aes を直接使用した暗号化の例です。

ブラウザを通じて暗号化された js ファイルを見つけることができ、通常はソースコード / ソース内の js ディレクトリで見つけます。このサイトは比較的簡単で、crypto-js.js ファイルを直接使用しており、開くと aes のキーと暗号化方式がすぐに確認できます。

Pasted image 20241129200734

上の図から、キーが与えられ、モードは ECB、パディングは Pkcs7 であることがわかります。これらの情報があれば、データを解読することができます。

burpsuite のautodecoderプラグインを使用して、今回の解読もこのプラグインを使用しました。

Pasted image 20241129201305

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

Pasted image 20241129201504

最初の options タブは、いくつかの設定です。

  • モジュール制御:burp のどのモジュールで autodecoder の暗号化 / 復号化を実行するか
  • 暗号化 / 復号化オプション:自前のアルゴリズムを使用するか、インターフェースを使用するかを制御します。

Pasted image 20241129201749

後のオプションは最初のオプションに関連しており、インターフェースを使用する場合、データヘッダーを処理するまたはリクエスト応答の異なる暗号化/復号化オプションを設定できます。

  • 暗号化 / 復号化設定:暗号化ドメインを必ず記入する必要があります。そうしないと autodecoder タブに表示されません。他はデフォルトで構いません。
  • 設定が完了したら、必ず保存してください。

2 番目のタブは autodecoder の自前のアルゴリズムによる暗号化 / 復号化です。

Pasted image 20241129202124

3 番目のタブはインターフェースによる暗号化 / 復号化です。

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

Pasted image 20241129202150

今回遭遇したように、2 つのパラメータが存在する場合、自前のアルゴリズムによる暗号化 / 復号化では要件を満たすことができません。

Pasted image 20241129200536

自前のアルゴリズムによる暗号化 / 復号化には正規表現パターンマッチングがあり、1 つの暗号化された文字列(name)しかマッチできず、pwd パラメータの暗号化された文字列を抽出することができません。

4 番目のタブはリクエスト応答の置換です。

権限のない脆弱性をテストするために使用でき、burp の Autorize プラグインと似ていると感じますが、使用したことはありません。

Pasted image 20241129202217

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バイトのキー
    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

まずはパケットをキャプチャしてテストしてみてください。成功裏に解読されたことが確認できます。

Pasted image 20241129203021

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

Pasted image 20241129203246

Pasted image 20241129203422

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

Pasted image 20241129203459

また、burp の intruder モジュールを使用してログインブルートフォース攻撃を開始することもできます。

ここで、非対称暗号、対称暗号、署名、再送信禁止のテストシナリオを含むフロントエンド暗号対抗練習用の靶場をお勧めします。AES、DES、RSA などを使用したペネトレーションテストの練習に適しています。

靶場のアドレス:https://github.com/SwagXz/encrypt-labs/tree/main

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。