mitmproxy のintercept機能の使い方をhackerschool.jp Take #17のwriteupで解説


はじめに

mitmproxy というのはコンソール型の通信監視ツールで、プロキシ機能を通じて通信サーバと端末の間に入り、その通信内容を表示するものです。

このmitmproxyの使い方をCTFの問題を解きつつ解説します。
(使い方と言っても intercept 機能に絞ってます)

環境

MacBook Air (11-inch, Early 2015)
macOS High Sierra バージョン 10.13.6
Google Chrome バージョン: 68.0.3440.106(Official Build) (64 ビット)

(本記事では以下をインストールします)
mitmproxy: stable 4.0.4
Google Chrome 拡張機能 Proxy SwitchySharp 1.10.6

問題

http://www.hackerschool.jp/hack/take17.php
この問題を解きつつ、mitmproxyの使い方を解説していきます。

パスワードを入力して「突破する」ボタンを押下するだけですが、なんのパスワードを入力するか探すことが問題ですね。

writeup

準備

インストール

mitmproxyをインストールします。
$ brew install mitmproxy

Chrome上で手軽にプロキシを設定できるように拡張機能「Proxy SwitchySharp」もインストールしてください。そしてHTTP Proxyの設定を、127.0.0.1:8080 にセットし、名前を「mitmproxy」等つけてください。「Direct Connection」をクリックすれば通常通りProxy無しに、「mitmproxy」をクリックすればセットしたアドレスとポートがProxyになります。

「Direct Connection」
Chrome --------------------------------> internet
「mitmproxy」
Chrome --> mitmproxy(127.0.0.1:8080) --> internet

ですね。

mitmproxyの起動

ターミナルで
$ mitmproxy

Proxy SwitchySharp で「mitmproxy」にセットします。

これでchromeで好きなサイトを見ると、ターミナルにキャプチャされたHTTP requestが表示されています。これで準備完了です。

HPへアクセス

まずはソースを読みます。
chromeで 表示 > 開発/管理 > ソースを表示

<form action="./take17.php" method="post" name="form1" id="form1" onsubmit="return false;" class="form-horizontal">
  <fieldset>
    <div class="control-group">
      <label class="control-label">パスワード:</label>
      <div class="controls">
        <input type="text" name="input_id" value="" style="">
          <br><span class="red"></span>
      </div>
    </div>
    <div class="form-actions">
      <button class="btn btn-primary" type="button"  onclick="fnFormSubmit()">突破する!</button>
    </div>
  </fieldset>

突破するボタンをクリックすると、fnFormSubmit()が呼ばれます。
fnFormSubmit()を探すと、2箇所あります.

1110行目
<script type="text/javascript">
  function binary(input) {
    return input.toString(2);
  }

  //パスワードチェック
  function fnFormSubmit(){
    if (binary(parseInt(document.form1.input_id.value))==100110100100) {
      self.location=document.form1.input_id.value + '.html';
    } else {
      alert('残念!');
      document.form1.submit();
    }
  }
</script>
1220行目
<!--見つかった・・-->
<script type="text/javascript">
  //パスワードチェック
  function fnFormSubmit(){
    if(document.referrer
        =="http://www.hackerschool.jp/hack/take17_dummy_referrer/"){
      if (binary(parseInt(document.form1.input_id.value))==11010100001011) {
        self.location=document.form1.input_id.value + '.html';
      } else {
        alert('残念!');
        document.form1.submit();
      }
    }else{
      alert('残念!');
      document.form1.input_id.value = "";//パスワード初期化
      document.form1.submit();
    }
  }
</script>

javascriptは後から出てきたほうが勝つので後者のfnFormSubmit()が勝ちます。

抜粋
if(document.referrer=="http://www.hackerschool.jp/hack/take17_dummy_referrer/"){
  if (binary(parseInt(document.form1.input_id.value))==11010100001011) {
    self.location=document.form1.input_id.value + '.html';
  } else {
    alert('残念!');
    document.form1.submit();
  }
}

リファラーの条件が邪魔です。こんなURLから飛んできたわけではないので。
input boxに入れた整数値を2進数にすると 11010100001011 と等しくなるのがパスワードですね。10進に変換します。

$ echo "obase=10;ibase=2;11010100001011"|bc
13579

さて、13579をinput boxに入れてボタンを押しても、リファラーが異なるので適正にパスワード評価がなされません。

ということで、mitmproxyを使ってjavascriptを無理やり書き換えてやります。

mitmproxyの使い方

mitmproxyの基本的な使い方はこちら等を見てください。
https://qiita.com/hkurokawa/items/9034274cc1b9e1405c68

? を押すとヘルプが出ます。key bindとfilterのコマンドが左右キーで切り替えられます。
元の画面に戻るには q を押下します。基本的な操作は vi と似ています。

ここでやりたいことは
1. http://www.hackerschool.jp/hack/take17.php にアクセス
2. レスポンスをinterceptして一時止める。
3. レスポンスボディに含まれる上記JavaScriptを一部書き換え、resumeする。
4. パスワードを入力し、ボタン押下
です。

インターセプトするには i 押下し、以下のように設定します。
~bs というのはResponse bodyの中に「take17_dummy_referrer」が含まれれば一時止める。と読みます。

リターン押下で

とセットされます。

これでインターセプトの準備ができました。
http://www.hackerschool.jp/hack/take17.php にアクセスすると、

条件に適合したHTTP通信が赤色で表示されます。
当該行でエンター押下

Response intercepted というタブになってますね。
ここからResponse Bodyを書き換えてやります。

eを押下すると小窓が開きます

a) response-body を選択肢、エンター押下。
するとviが立ち上がり、response bodyの内容が表示されます。

1220行目
<!--見つかった・・-->
<script type="text/javascript">
  //パスワードチェック
  function fnFormSubmit(){
    if(document.referrer
        !="http://www.hackerschool.jp/hack/take17_dummy_referrer/"){

リファラーチェックを == から != に書き換えてやります。これで適正にパスワードが評価されるようになります。

viなので
:wq
で保存すると、書き換えたレスポンスが返ります。

一時停止した通信を再開(resume)するには a か A を押下します。
a だと当該通信のみ。A だとすべてのinterceptされた通信がresumeします。

問題はこの後も続くのですが、mitmproxyの解説が終わったのでここまでとします。
Happy Hacking!

感想

mitmproxy。便利です。wiresharkだとBodyの日本語が化けるので、その点でも良いです。

ちなみに、Man In The Middle Proxy で、mitmproxyです。

参考

モバイルアプリ開発者のための mitmproxy 入門

mitmproxyでandroidの通信を改竄

mitmproxy cheat sheet

履歴

2018/08/13 初版