TOUCH THE SECURITY Powered by Security Service G

コラム

2023.10.06

Burp SuiteのExtenderを実装する方法について解説します

はじめまして。セキュリティGの「診断員Y」です。日頃Webアプリケーションの脆弱性診断業務を行う傍ら、自己学習中に当ブログの「診断員X」さんの記事を拝見し、Burp SuiteのExtenderについて興味をもちました。

そこで今回はBurp SuiteのExtender作成方法について私が学んだ知見を記事として公開したいと思います。

この記事を読んでもらいたい方

  • 日頃Burp Suiteを使用して診断業務を行っている
  • Burp SuiteのExtenderをよく利用する
  • pythonの知識がある

Burp SuiteのExtender実装について

Burp SuiteのExtenderの実装に使用するプログラミング言語はJavaとpythonの二種類があります。今回はpythonでの方法を解説します。以下のステップでExtenderの実装を行います。

  1. 事前準備
  2. Extenderでのhello world
  3. クエリをインクリメントするExtenderの実装
  4. 指定の2つのクエリの値を同期するExtenderの実装

事前準備

echoサーバの用意

実装したExtenderの動作確認用に、リクエストをそのまま返すechoサーバを用意します。

echoサーバの用意にはいくつかの手段がありますが、nodeのnpxコマンドが実行できる環境では「npx http-echo-server」を実行することで簡単に立ち上げられます。

Jythonのインストール

Burp Suiteでpython製Extenderを実行する場合、Jython(スタンドアロン版)を任意の場所に配置し、パスを通す必要があります。

  1. Jython公式サイトよりスタンドアロン版 Jythonをダウンロードする 。
  2. 任意の場所に配置し、Extender > Options > Python Environment の「Location of Jython standalone JAR file:」にダウンロードしたファイルを指定する。

Extenderでのhello world

まずはExtenderでのhello worldを実装します。

使用するコード


# coding: UTF-8
from burp import IBurpExtender
from burp import IHttpListener


class BurpExtender(IBurpExtender, IHttpListener):
    def registerExtenderCallbacks(self, callbacks):
        # Extenderの登録を行う
        callbacks.registerHttpListener(self)

        # ヘルパをメンバ変数に格納しておく
        self._helpers = callbacks.getHelpers()


    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        """通信毎に呼ばれるメソッド
        """
        # リクエストでなければ処理を打ち切る
        if not messageIsRequest:
            return
        
        print("hello world")


Extenderの実装はBurpのインタフェースを継承しインタフェースのメソッドを実装することによって行われます。特に重要なのが「processHttpMessage」メソッドで、こちらのメソッドは通信毎にコールバックとして呼ばれます。このメソッドでリクエストやメソッドの編集を行うことにより様々な挙動が実装できます。今回はリクエスト発生毎に「hello world」を出力してみます。

動作確認

ここからは実際に上記のコードをBurpにExtenderとして登録し、動作確認を行います。
Extenderを適用するには上記コードをファイルに保存の上、以下を行います。

  1. burp > Extender > Extension > Burp ExtensionsのAddを押す。
  2. 以下の設定を行う。
  3. 
    Extensions Details
        Extension type: Python
        Extension file (.py): 上記コードを指定
    Standard output
        Show in UI
    Standard Error
        Show in UI
    
    
    ※設定例

  4. Nextを押す。
  5. 問題なければCloseを押す。

これでExtenderの登録が完了しました。Burpを通して任意をリクエストを送信してみてください。ExtenderのOutputにhello worldが出力されます。

クエリをインクリメントするExtenderの実装

任意のクエリの値をインクリメントします。
例) ?a=1 → ?a=2
流れとしては以下のようになります。

  1. リクエストの対象パラメータを取得する。
  2. 対象パラメータの値 + 1を計算する。
  3. リクエストの編集により、対象パラメータを更新する。

使用するコード


# coding: UTF-8
from burp import IBurpExtender
from burp import IHttpListener

class BurpExtender(IBurpExtender, IHttpListener):
    def registerExtenderCallbacks(self, callbacks):
        callbacks.registerHttpListener(self)
        self._helpers = callbacks.getHelpers()
        

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if not messageIsRequest:
            return

        TARGET_PARAM_NAME = 'a' # 対象のパラメータ名
        
        # パラメータをすべて取得し、対象パラメータの捜索を行う
        parameters = self._helpers.analyzeRequest(messageInfo.getRequest()).getParameters()

        # パラメータから必要な値を取り出す
        target_parameter = [x for x in parameters if x.getName() == TARGET_PARAM_NAME][0]
        target_name = TARGET_PARAM_NAME
        target_type = target_parameter.getType()

        # 対象パラメータの値をインクリメントする
        old_value = target_parameter.getValue()
        new_value = str(int(old_value) + 1)

        # リクエストを編集する
        newParameter = self._helpers.updateParameter(
            messageInfo.getRequest(), 
            self._helpers.buildParameter(target_name, new_value, target_type))
        messageInfo.setRequest(newParameter)



動作確認

echoサーバへ`/?a=1`というリクエストを送信するとレスポンスのaパラメータが2になっていることが確認できます。

指定の2つのクエリの値を同期するExtenderの実装

クエリの同期を行います。シチュエーションとしてパスワードと確認パスワードを含むリクエストのそれらを同期させることを想定しています。

使用するコード


# coding: UTF-8
from burp import IBurpExtender
from burp import IHttpListener

class BurpExtender(IBurpExtender, IHttpListener):
    def registerExtenderCallbacks(self, callbacks):
        callbacks.registerHttpListener(self)
        self._helpers = callbacks.getHelpers()
        

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        FROM_PARAM_NAME = 'password' # 上書き元のパラメータ
        TO_PARAM_NAME = 'confirmPassword' # 上書き先のパラメータ
        from_parameter = None
        to_parameter = None

        # リクエスト以外(レスポンス等)の場合、処理を打ち切る
        if not messageIsRequest:
            return
        
        # パラメータをすべて取得し、対象パラメータの捜索を行う
        parameters = self._helpers.analyzeRequest(messageInfo.getRequest()).getParameters()
        from_parameter = [x for x in parameters if x.getName() == FROM_PARAM_NAME][0]
        to_parameter = [x for x in parameters if x.getName() == TO_PARAM_NAME][0]

        from_val = from_parameter.getValue()

        # リクエストを編集する
        newParameter = self._helpers.updateParameter(messageInfo.getRequest(),
        self._helpers.buildParameter(to_parameter.getName(), from_val, to_parameter.getType()))
        messageInfo.setRequest(newParameter)

動作確認

?password=hoge1234&confirmPassword=piyo4567 を送信すると?password=hoge1234&confirmPassword=hoge1234 へと同期されていることが確認できます。

注意点

Extenderでのリクエストの変更はProxyのhttp historyでは確認できません。Loggerであれば確認できます。

まとめ

いかがでしたか?Extenderの実装はpythonの知識さえあれば簡単に行なえます。気になった方は是非お試しください。

記事一覧に戻る