JmeterでHTTPSをMITM Proxyとして使い暗号通信内容をぶっこ抜く


## 概要
HTTPSはend-endの暗号化をするため、エンドポイント以外では暗号化内容をデコードすることができません。自社アプリであれば、デバッガなどで当然暗号化される前、もしくは暗号化されて到着したデータをエンコード/デコード前後にアクセスできますが、他社製アプリやOSの通信などは、一般的には何がやりとりしているか、うかがい知ることはできません。wiresharkでは可能ですが、暗号化に使っている鍵を解析するために、サーバ証明書に含まれる公開鍵と対になる秘密鍵が必要です。

今回は中間者攻撃と呼ばれる手法を使って、httpsのトラフィックをデコードしてみます。

## なぜ復号できるのか？

![Screenshot 2015-03-16 15.05.47.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/4bdb2c7b-9586-4510-01ac-2e9611373070.png "Screenshot 2015-03-16 15.05.47.png")

上図はSSL暗号化通信が始まるまでのサーバとクライアントのやりとりをおおざっぱに示したものです。サーバ証明書は公開鍵を含み、公開鍵で暗号化したものは秘密鍵でしかデコードすることはできません（公開鍵暗号方式）。それならば、全ての通信を公開鍵暗号方式にすればいいのですが、公開鍵暗号のエンコード・デコードは計算量が多く負荷が高いため、共通鍵暗号で使用するデータのみ暗号化することでセッションの秘匿性を実現しています。
ただの公開鍵暗号であれば、これでデータ自体は暗号化されるのですが、SSLにはクライアントが通信使用としている相手が本当に通信相手としていいかどうかを確認するため、公開鍵暗号を含む証明書を検証する手順が規定されています。

- クライアントが信頼するCA(認証局）から発行されている証明書であること
- 有効期限内であること
- 通信先相手の名前が正しく記載されていること
- 失効されていないこと

これらを確認した上で、いずれも問題が無い場合のみ、暗号通信を継続します。

この暗号通信にネットワーク上で割り込むためには証明書の秘密鍵を使ってシークレットを取得するしかありません。wiresharkで実現しているhttpsデコードはこの通信に介入してシークレットから秘密鍵を生成し、共通鍵暗号通信をデコードしています。

![Screenshot 2015-03-17 00.07.09.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/4c4ef855-40fd-e805-f30d-95cba6024d75.png "Screenshot 2015-03-17 00.07.09.png")

中間者攻撃では、サーバとクライアントの間に、自身がさもそのサーバであるかのようなふるまいをするサーバを設置します。証明書を要求した際に、中間者は、リアルタイムに、有効な、対象サーバを偽装する証明書署名要求を作成し、自身が持っている認証局にて署名を行います。クライアントには何らかの手段で、中間者の認証橋を信頼させておきます。こうすることで、証明書の検証プロセスを不正に通過させます。中間者は、対象サーバとは個別に通信を行うことにより、対象サーバとクライアントとの間における通信を傍受することができます。

これをアクティブに活用することにより、クライアントとサーバ間の通信をデコードして取り出すことができます。


## 手順
1. Javaのインストール
	https://www.java.com/ja/download/mac_download.jsp?locale=ja
2. Jmeterのダウンロード
   http://jmeter.apache.org/download_jmeter.cgi
3. Jmeterの実行

 ```console:
 $ java -jar ApacheJMeter.jar
 ```
4. JMeterが起動します。左ペインのWorkbenchを右クリックし、Non-Test ElementsのHTTP(S) Test Script Recorderを追加します。
![Screenshot 2015-03-17 10.11.56.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/98c46d69-a3dc-9a56-bcae-15fa74cf0c10.png "Screenshot 2015-03-17 10.11.56.png")

5.追加したRecorderにListenerのView Results Treeを追加します。

![Screenshot 2015-03-17 10.46.54.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/b0afc08d-fe1a-b8c0-5843-8dfa2dbf5479.png "Screenshot 2015-03-17 10.46.54.png")
6. HTTP(S) Test Script Recorderを選択し、一番下の[Start]ボタンを押します。
7. 動的に証明書に署名するtemporaryCAのCA証明書をjmeterのbinディレクトリに作成した、という趣旨のダイアログが表示されます。OKをクリックします。

![Screenshot 2015-03-17 10.51.08.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/78580025-0631-bd37-0cdf-1753d9504d8e.png "Screenshot 2015-03-17 10.51.08.png")
8.Finder上で作成されていることを確認します。.crtファイルをコピーしておくとよいでしょう。
![Screenshot 2015-03-17 10.57.13.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/ad2a1217-99f7-bf50-caba-7f8c6845ce5f.png "Screenshot 2015-03-17 10.57.13.png")
9.取り出したファイルを使って信頼済みCAにします。ここではFirefoxの手順を説明しておきます。FirefoxはOSとは独立した信頼を構成しているため、ブラウザで読み込みます。Chrome/Safariの場合は、Keychainに読み込んでAlways Trustに追加すればOKです。

Firefoxを起動して、メニューのFirfox->環境設定->詳細->証明書を表示ボタンを選択していきます。

![Screenshot 2015-03-17 11.00.52.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/0ecbab75-029f-3b30-442e-5b146ea1371d.png "Screenshot 2015-03-17 11.00.52.png")
10.証明書マネージャが開きます。認証局証明書->読み込むボタンをクリックします。
   ダイアログから、先ほどの.crtファイルを選択します。

![Screenshot 2015-03-17 11.02.32.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/1763d22c-abfd-5599-ecd0-8f8cae470346.png "Screenshot 2015-03-17 11.02.32.png")
11.信頼の種類を選択します。Webサイトの識別だけチェックしておけばよいでしょう。
　　また、証明書の表示を押すと中身が表示されます。JMeterでProxyのStart時に表示されたダイアログのSHA-1 Fingerprintと比較すると、読み込もうとしているファイルが確かにそこで生成されたものであるという確認ができますので、併せて実施しておくとよいでしょう。

![Screenshot 2015-03-17 11.03.19.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/4a190d4e-ab82-9171-57a9-1b42a17771d3.png "Screenshot 2015-03-17 11.03.19.png")

![Screenshot 2015-03-17 11.05.34.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/594bb880-91e9-60be-37ac-77f13f433d3f.png "Screenshot 2015-03-17 11.05.34.png")
12.OKを押すと、信頼された認証機関として登録されます。

![Screenshot 2015-03-17 11.06.13.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/a7ab7748-6e45-1a68-3310-e4dee830f19d.png "Screenshot 2015-03-17 11.06.13.png")
13.次にProxyを設定します。証明書マネージャを閉じるとFirefoxの設定画面に戻っているので、詳細のネットワークを選択します。接続設定ボタンをクリックします。

![Screenshot 2015-03-17 11.08.04.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/6aa75ea3-f6ab-2ae6-779e-b5ace2ad9dfe.png "Screenshot 2015-03-17 11.08.04.png")
14.以下のように、手動でプロキシを設定するを選択し、HTTPとSSLプロキシにlocalhost:8080を指定し、OKボタンを押します。
（リモートマシンからの場合はこのJMeterが動作しているマシンのIPアドレスかホスト名を指定します）

![Screenshot 2015-03-17 11.09.28.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/6e081493-77b3-1391-fb1d-de7ec9139d30.png "Screenshot 2015-03-17 11.09.28.png")
15.設定画面を閉じて、httpsサイトにアクセスしてみましょう。
　　下記のように、https接続でも、応答がデコードされています。
　　
　　![Screenshot 2015-03-17 11.11.14.png](https://qiita-image-store.s3.amazonaws.com/1951/66163/a4ee5d35-d55e-e913-0dd8-5319904ad23b.png "Screenshot 2015-03-17 11.11.14.png")

##TODO

生成されるCA証明書の有効期限が短いものになるため、ある程度期間の長いものを生成したいのですが、パラメータがいまのところわかってません。

##注意

このように、安易に証明機関を信頼することは即暗号通信を危機にさらすことになりますので、注意しましょう。