TOUCH THE SECURITY Powered by Security Service G
はじめまして。セキュリティ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の実装を行います。
- 事前準備
- Extenderでのhello world
- クエリをインクリメントするExtenderの実装
- 指定の2つのクエリの値を同期するExtenderの実装
事前準備
echoサーバの用意
実装したExtenderの動作確認用に、リクエストをそのまま返すechoサーバを用意します。
echoサーバの用意にはいくつかの手段がありますが、nodeのnpxコマンドが実行できる環境では「npx http-echo-server」を実行することで簡単に立ち上げられます。
Jythonのインストール
Burp Suiteでpython製Extenderを実行する場合、Jython(スタンドアロン版)を任意の場所に配置し、パスを通す必要があります。
- Jython公式サイトよりスタンドアロン版 Jythonをダウンロードする 。
- 任意の場所に配置し、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を適用するには上記コードをファイルに保存の上、以下を行います。
- burp > Extender > Extension > Burp ExtensionsのAddを押す。
- 以下の設定を行う。
- Nextを押す。
- 問題なければCloseを押す。
Extensions Details Extension type: Python Extension file (.py): 上記コードを指定 Standard output Show in UI Standard Error Show in UI※設定例
これでExtenderの登録が完了しました。Burpを通して任意をリクエストを送信してみてください。ExtenderのOutputにhello worldが出力されます。
クエリをインクリメントするExtenderの実装
任意のクエリの値をインクリメントします。例) ?a=1 → ?a=2
流れとしては以下のようになります。
- リクエストの対象パラメータを取得する。
- 対象パラメータの値 + 1を計算する。
- リクエストの編集により、対象パラメータを更新する。
使用するコード
# 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であれば確認できます。