はじめに
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箇所あります.
<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>
<!--見つかった・・-->
<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 と似ています。
ここでやりたいことは
- http://www.hackerschool.jp/hack/take17.php にアクセス
- レスポンスをinterceptして一時止める。
- レスポンスボディに含まれる上記JavaScriptを一部書き換え、resumeする。
- パスワードを入力し、ボタン押下
です。
インターセプトするには i 押下し、以下のように設定します。
~bs というのはResponse bodyの中に「take17_dummy_referrer」が含まれれば一時止める。と読みます。
これでインターセプトの準備ができました。
http://www.hackerschool.jp/hack/take17.php にアクセスすると、
条件に適合したHTTP通信が赤色で表示されます。
当該行でエンター押下
Response intercepted というタブになってますね。
ここからResponse Bodyを書き換えてやります。
a) response-body を選択肢、エンター押下。
するとviが立ち上がり、response bodyの内容が表示されます。
<!--見つかった・・-->
<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です。
参考
履歴
2018/08/13 初版