miauのブログ

はてなダイアリー「miauの避難所」をはてなブログに移行しました

HTTP リクエストの改ざん方法いろいろ

私の会社/部署はいちおうセキュリティに強いことを売りにしているらしく、最近作ってる Web アプリケーションでは某セキュリティ会社による診断(ペネトレーションテスト)を受けることが増えています。

今作ってる Web プリケーションも診断を受けたのですが、今回指摘されたのは「HTTP リクエストを Host: ヘッダなしで送ると Location: に内部 IP アドレスが表示されている」というもの。

この検証を軽くやっておくかー、と思ったら結構いろいろやってしまったのでメモしておきます。ちょっとした HTTP リクエスト改ざんツール比較みたいになってますが、他にもいいやり方があったら教えてくださいませ。

ツールの選定基準について

「ローカルプロキシを立ちあげてブラウザのプロキシ設定を立ちあげて〜」というツールは、使い方を説明するのが面倒なのであまり使いたくありません。ブラウザのプラグインとして動作するものか、Fiddler のようにブラウザ側の設定も自動的に変更してくれるツールがよいです。

使い方も「○○画面に遷移するときにリクエストヘッダの Host: を消してね」くらいの説明ですんなり使えるものがベストです。(結局見つかってないですけど。)

Web Developer みたいに HTML の内容を変更することでフォームの値を改ざんするものもありますが、今回は HTTP プロトコルレベルでの改ざんがメインということで。

TamperIE

IEプラグインです。

という特長があって IE6 の頃はそれなりに愛用していたのですが、IE7 だか IE8 だかにしてから利用できなくなってしまったので残念です。

短所としては、

  • クエリストリングを urlencode/urldecode できないので、多少不親切
  • ヘッダの改ざんが不完全(Host: とか送出されるはずなのに「Raw Headers」に表示されない)
  • リクエストを改ざんした場合、Referer: を送信しない

という点があります。

メイン PC にはすでに IE8 が入っていたので今回試してませんが、Host: を削ってリクエストを投げたりはできなかった気がします。

Tamper Data

Firefox アドオンです。説明に

w.r.t. to GET parameters:

GET parameters are part of the URI, which at the point I am hooking into (using the observer service) is immutable.

とあるように、リクエスト行(HTTPメソッド、URL、クエリストリング、プロトコルバージョン)が変更できない・・・と思ってたんですけど、「Replay in browser」から http/https の切り替えや、URL の変更、クエリストリングの書き換えくらいはできるようです。

最初の Tamper 時にできれば便利なんですけど、使ってる仕組みが違うようで。以下の URL が参考になりそうな感じでした。

これでいけそうだったんですが、よく考えたら今回は Host: ヘッダを削除するので、HTTP/1.1 だと 400 Bad Request になってしまいます。リクエストを HTTP/1.0 に変えるには、about:config を開いて「network.http.version」を「1.0」にする必要があります。(Configuration Mania を入れておけば「HTTP ネットワーク」→「接続」から変更ができます。)

今回のケースではこのツールでも検証できましたが、

  • メソッドの書き換えができないので TRACE メソッドのテストなんかにも使えない
  • ヘッダの追加や削除をいちいちマウス右クリック→「Add element」とかでやる必要があるのでちょっと面倒

という不満点もあるので、別のツールを探したいところです。

Live HTTP Headers

Firefox アドオンです。リクエスト/レスポンスのログを残すのがメインですが、リクエストのリプレイ機能があり、このときに改ざんが行えます。こちらは Tamper Data と違ってメソッドの書き換えもできるので TRACE メソッドのテスト等も行えます。

プロトコルバージョンのプルダウンも用意されていて、一見ここから HTTP/1.1 と HTTP/1.0 の切り替えができそうなんですが、グレーアウトされており変更できないようなので about:config から設定を変更する必要があります。

こちらも目的の検証は行えたのですが、改ざんが目的のときに一度リクエストを送信してリプレイ、というのが少々面倒です。

ちなみに、似たようなアドオンで HttpFox があります。こちらは改ざんが行えない代わりにレスポンスボディ部分もログを残してくれるので、リクエスト改ざん時のコンテンツを確認したいような場合に使ったりしていました。

Fiddler2

ローカルプロキシとして動作するので、IE でも Firefox でも使えます。今回は改ざんに使っていますが、本当はもっと色々なことができるツールで・・・機能紹介スライドがあったので貼っておきます。

Request Builder を使うと HTTP メソッド、URL、プロトコルバージョンが変えられるようなので、さっそく Host: ヘッダを削ろうとしたんですが、URL を指定するとそれを元に Host: ヘッダが勝手につく(HTTP/1.0 にしても変化なし)のようで。

解決方法を探してみると、名前解決されるホスト名と違う Host: ヘッダを送りたくて困っている人を発見。

この場合はスクリプトで対応できたみたい(最近のバージョンだと Host Remapping の設定でもできるっぽい)だけど、Host: ヘッダを削るにはどうすればいいんだろう?

と、Script Samples を見ながら適当にやったところ、OnBeforeRequest イベントの最後に

		oSession["x-overridehost"] = oSession.oRequest.host;
		oSession.oRequest.headers.Remove("Host");

みたいな処理を入れると Host: ヘッダを消すことができました。

最初は「oSession.oRequest.headers.Remove("Host");」だけでいけると期待していたんですけど、oSession.oRequest.host の情報が消えてしまって接続先のホストがわからなくなるのか、VMnet1 のアダプタの IP アドレスにつなぎに行こうとしてたりして謎な挙動になっていました。

追加した行については、

に載っている x-overrideHost の説明の通りで、

Provide the Host:Port combination which should be used for DNS resolution purposes. Note that this mechanism does not change the HOST header on the request, and thus is not useful if there's an upstream gateway.

のように使えるらしいので、これをあらかじめ設定しておけば接続先が変になることもないみたいです。

で、さっそく目的のホストに対して使ってみたんですが・・・Host: ヘッダを削ってみても 400 Bad Request にならないし、Location: はちゃんとドメイン名で返ってくる。

・・・というところで気づきました。今回のサイトは HTTPS のみ閲覧を許可しているんですが、HTTPS のプロキシは最初の CONNECT 時にホスト情報を渡してるから、それ以降の Host: は必要ないんですね。

こちらがプロキシを使わない場合の HTTPS の詳細な(詳細すぎる)解説で、

HTTPS のプロキシを使った場合のリクエストは この真ん中くらいに。今回やりたいことはプロキシ型の改ざんツールじゃ実現できないってことですね・・・。

プロキシ型が今回使えないことがわかったので試しませんでしたが、後者の URL で紹介されている Achilles は .exe を起動するだけらしいですし、FoxyProxy あたりを使えばプロキシの切り替えは簡単にできるので、この辺も今度は試してみたいですね。

openssl

普段簡単なリクエストは telnet の手打ちでやっているんですが、今回は HTTPS サイトだから telnet 手打ちはできない・・・こともなくて。よく考えたら msysGit と一緒に openssl.exe が入っていたので、これもやってみました。

openssl s_client -connect www.example.com:443

あとは telnet と同じで、

GET / HTTP/1.0

とかやれば OK と。やっぱり簡単なリクエストならこれが一番確実ですね。

curl

Fiddler掲示板に載っていたので、ついでにこちらも試してみました。ちなみに curl.exe は msysGit にもついてくるし、Gow にも入ってます。

curl -i -0 -H "Host:" https://www.example.com/

使ってるオプションはこの辺り。

-i/--include       Include protocol headers in the output (H/F)
-0/--http1.0       Use HTTP 1.0 (H)
-H/--header <line> Custom header to pass to server (H)

ということで、こちらもちゃんと期待通りに動作しました。

その他試したもの

に知らないのがいくつか載っていたので、これも試してみました。

UrlParams (GETパラメータ、POSTパラメータを書き換えて再リクエスト)
https://addons.mozilla.org/ja/firefox/addon/1290

こっちはパラメータ以外だと Referer くらいしか書き換えできないみたいで、ヘッダ等をいろいろいじるには使えない感じでした。

Modify Headers (HTTPリクエストヘッダを書き換え)
https://addons.mozilla.org/ja/firefox/addon/967

元々モバイル端末のリクエストを模倣するためのもので、すべてのリクエストに対して決まったリクエストヘッダを追加/変更/削除できるようです。

Host: ヘッダを削るなら、Action: Filter、Name: Host のように指定すればいいんですけど、HTTP/1.0 への切り替えは別途必要ですし、目的が違うツールなのでセキュリティまわりの作業には向いてないかなと。

(2010-12-24 追記)

というものを見かけたので試しました。

  • Method はプルダウンから選択する形
  • 生のヘッダは指定できず、Conent-Type、Accept のヘッダのみ指定が可能

ということで、ヘッダの改ざん全般には向かなそうです。