生存報告

主に情報セキュリティ関連のエントリをたまに書いて、存命であることを報告するページ。

Burp Suiteとnghttpxを使ってHTTP2のWebアプリに接続してみよう

2015年2月にHTTP2がRFC化された。これから普及が進むことが期待される。既にいくつかのクライアントやサーバはHTTP2に対応しており、対応アプリケーションは、以下のGitHubでまとめられている。*1


github.com


HTTP2では、バイナリプロトコル、サーバープッシュ、多重化など新要素がある。これに伴うセキュリティ面ではOWASP等で議論が重ねられているところだけど、ここでは置くとして、さしあたり僕が気になるのは、従来型のWebアプリケーションのテストはどうなるんだろうという点。

テストのためにはフォワードプロキシが欲しい。が、あいにくBurp SuiteやFiddlerなどはまだ対応していない模様。上のGitHubを見てもフォワードプロキシはあまりなく、すぐ利用できるものもなさそう。
HTTP2はバイナリプロトコルなので、HTTPリクエストをそのままガシガシ編集することもできない。

いざ「HTTP2でアプリケーション作ったのでテストよろしくね」的な無茶振りがきた場合、途方に暮れるおそれがある。*2 *3

そこで今回は実験的に、Burp Suiteとnghttpxを組み合わせてHTTP2のWebアプリケーションにアクセスしてみたい。

nghttpxについて

HTTP2のリバースプロキシである。なんか使い方によってはフォワードプロキシのようにも使えるみたい。以下リンクを参照。

qiita.com

今回は、フォワード/リバース両方使う。

検証環境

検証環境のイメージ

以下のイメージ。

f:id:tosebro:20150422063700p:plain

ざっくり流れを説明すると、

・ブラウザからBurp Suiteを通して接続する。ここはHTTP1。

・クライアント側のフォワードプロキシ(nghttpx)でHTTP1→HTTP2にアップグレード

・サーバ側のリバースプロキシ(nghttpx)でHTTP2→HTTP1にダウングレードしてApacheに転送*4

アプリケーション

検証用に、入力値(名前)を受け取ってようこそというメッセージを出すだけのシンプルなphpスクリプトを用意。*5


hello.php

<?php
$name = $_POST["name"];
if($name=="") {
	$name = "guest";
}
?>
<html>
<head>
<title>greeting</title>
</head>
<body>
<h1>greeting</h1>

Hello, <?php echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); ?> !<br />
<br />

<?php if($name=="guest") { ?>
Input your name.<br>
<form action="./hello.php" method="post">
Name: <input type="text" name="name" size="24" value="" />
<input type="submit" />
</form>
<?php } ?>

<a href="./hello.php">back</a><br />
<br />

</body>
</html>

手順

  • ブラウザとかBurpとかApacheはテキトーに起動する。
  • ブラウザのプロキシ設定をBurpに、Burpのプロキシ設定をフォワードプロキシのnghttpxに設定する。
  • フォワードプロキシのnghttpxを以下のコマンドで起動する。
nghttpx -p -k -LINFO -f0.0.0.0,8090 -b192.168.120.128,8443
  • リバースプロキシのnghttpxを以下のコマンドで起動する。
nghttpx -LINFO -f0.0.0.0,8443 -b127.0.0.1,80 /root/cert/server.key /root/cert/server.crt
  • ブラウザからサーバのURLにアクセスする。

結果

ブラウザから、フォワードプロキシを経由してWebアプリケーションに接続できることを確認した。

アクセスの様子

f:id:tosebro:20150420232333p:plain
ブラウザから、サーバのURL「http://192.168.120.128:8443/hello.php」にアクセスしたところ。


f:id:tosebro:20150420232338p:plain
フォームをSubmitしたときのHTTPリクエスト


f:id:tosebro:20150420232343p:plain
POSTパラメータ「name」の値を改変


f:id:tosebro:20150420232345p:plain
HTTPレスポンス。改変後の値で処理されている。


f:id:tosebro:20150420232349p:plain
結果表示。

ログでの確認

フォワードプロキシのログを見ると、リクエストがHTTP1→HTTP2にアップグレードされていることがわかる。
(前半がBurpから受け取ったHTTPリクエスト、後半がサーバに送るHTTPリクエスト)

20/Apr/2015:23:06:57 +0900 PID25573 [INFO] shrpx_https_upstream.cc:153 [UPSTREAM:0x7ffc3b84e060] HTTP request headers
POST http://192.168.120.128:8443/hello.php HTTP/1.1
Host: 192.168.120.128:8443
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.120.128:8443/hello.php
Connection: keep-alive
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 35

(中略)
20/Apr/2015:23:06:57 +0900 PID25573 [INFO] shrpx_http2_session.cc:1279 [DHTTP2:0x7ffc3b836780] Negotiated next protocol: h2-14
20/Apr/2015:23:06:57 +0900 PID25573 [INFO] shrpx_http2_downstream_connection.cc:438 [DCONN:0x7ffc3b8216c0] HTTP request headers
:scheme: http
:path: /hello.php
:authority: 192.168.120.128:8443
:method: POST
accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-encoding: gzip, deflate
accept-language: en-US,en;q=0.5
cache-control: max-age=0
content-length: 35
content-type: application/x-www-form-urlencoded
host: 192.168.120.128:8443
referer: http://192.168.120.128:8443/hello.php
user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.5.0
via: 1.1 nghttpx

課題

アクセス自体はできたものの、いま分かっている課題を挙げる。

  • フォワードプロキシ側で、サーバアドレスが決め打ちになってしまっている。複数ドメインにわたる場合などが問題。
  • サーバアドレスを実在のドメインに変えると動作しない場合があった。*6
  • TLS関連のテストができない。(別でnmapとかsslscanでやる?)
  • アップグレード/ダウングレードがあってロスする情報があるかもしれない。

まとめ

HTTP1→HTTP2にアップグレードできるフォワードプロキシ(nghttpx)を使って、Burp SuiteでHTTP2サイトにアクセスしてみた。Burp Suiteはテストに使えそうだけど、実用を考えるとまだクリアする課題がある。やはりBurp SuiteなどのテストツールがHTTP2に対応するのを期待したい。

*1:メジャーなところではTwitterがHTTP2に対応している。

*2:特に、NOと言うことが許されない体育会系の組織にいる現場の人(僕のような)には酷な話だ。

*3:Twitterはどうやってるんだろう。ソースコードレビュー?

*4:環境構築を簡単にするためApache利用

*5:脆弱性あったらごめんなさい。

*6:手元で見た限りではnghttp2.orgは接続可能、twitter.comは不可だった