Host ヘッダとIPアドレス漏えい

# はじめに

こんな感じで、Hostヘッダのない HTTP1.0通信でIPアドレスが漏れる。

![ipMore.png](https://qiita-image-store.s3.amazonaws.com/0/182822/0aa9aa04-e9dd-7a81-1afd-8daf447ff243.png)

グローバルIPアドレスならいいけど、プライベートIPアドレスだと、少しセキュリティ上の問題になる。

# 仕組み

- HTTP/1.0 の話
- HTTP/1.0 では Host ヘッダはオプション(あってもなくてもよい)
- まぁ、大抵のWebブラウザでは、HTTP/1.0でもHostヘッダは付けるけど、つけなくてもよい
- 大抵の Web サーバは、仮想ホスト機能に対応している
- Hostヘッダのない HTTP リクエストは、どの仮想ホストに対応させていいか分からない
- しかも、ディレクトリに対して最後の「/」がないという「no TrailingSlash」状態
- Location で再リクエストを要求したいけど、フルパスURLのホスト名が分からない
- しょうがないので、NICのIPアドレスつけちゃえ

という感じ

# 対策

## 仮想ホストを設定する

- 運用しているホスト名の仮想ホストの設定をする
- それ以外の既定の設定は、無効にする。
    - または空のルートディレクトリだけを用意する
    - 全てアクセス禁止にする

とあれば、Host ヘッダのない HTTP リクエストは、既定の設定になり、上記のようなリダイレクトメッセージは送出されなくなる

つまり元々、仮想ホスト機能は、一つの Webサーバで複数のWebサイトを運用するための機能だけど、

![074.png](https://qiita-image-store.s3.amazonaws.com/0/182822/f28b2c04-d9cd-65ea-0086-5c63b6d8bc84.png)

一つのWebサイトでもいいジャン・・・そして、既定のWebサイト(設定されたものとは当てはまらなかったホスト名(ホストヘッダ無も含))の設定をエラー/禁止/無意味(空のPublicRoot)にすれば、リダイレクト要求のレスポンスが送出されないようにできる

![075.png](https://qiita-image-store.s3.amazonaws.com/0/182822/a88fd7d6-041c-d209-2950-5d15665dc9a5.png)

### 仮想ホストを設定するのデメリット

- ぶっちゃけ面倒じゃない!?
- DNSが壊れた時、緊急で IPアドレスの URL でアクセスしようとしてもできなくなる
- DNSが壊れた時、Hosts ファイルで名前解決すればアクセスできるけど・・・

上記のデメリットがデメリットでない環境であれば、仮想ホストを設定するのが王道かと思う

### Nginx の場合

ググレばいくらでもあると思う

### Apache の場合

ググレばいくらでもあると思う

### IIS6 の場合

![iis1a.png](https://qiita-image-store.s3.amazonaws.com/0/182822/481e0790-88fb-2e06-8fa4-9dd802f39eca.png)

デフォルトだと「ホストヘッダ」の値が空欄なので、なんでも受け付ける

![iis4.png](https://qiita-image-store.s3.amazonaws.com/0/182822/60649ab4-de2e-e866-dd1b-e3f0de97e352.png)

仮想ホストの設定で、「ホストヘッダ」を限定させる

![iis2a.png](https://qiita-image-store.s3.amazonaws.com/0/182822/892ead5f-f0d4-15b9-8e6e-046994ff0354.png)

すると、こんな感じになる

![iis6.png](https://qiita-image-store.s3.amazonaws.com/0/182822/bcc0dc41-9af2-2c01-5af4-7bfe14635e63.png)

Hostヘッダがないと、アクセスできなくなる(**Bad Request**になる)

### IIS7 の場合

![iis5a.png](https://qiita-image-store.s3.amazonaws.com/0/182822/33471e1a-372c-4915-a201-d12d0feec1f3.png)

こんな感じで「ホスト名」を空欄から特定値に設定する

![iis3.png](https://qiita-image-store.s3.amazonaws.com/0/182822/94e46be0-ce15-e604-21b1-8410684b135c.png)

Hostヘッダがないと、アクセスできなくなる(**Not Found**になる)

## 仮想ホストを設定する以外の対策

### Nginx の場合

設定ファイルの「**server_name**」を適切に設定し、「**server_name_in_redirect on**」にする

![nginx.png](https://qiita-image-store.s3.amazonaws.com/0/182822/6f68817e-1668-e646-6467-f16e463997dc.png)

すると、こんな感じになる。

#### 「server_name_in_redirect on」の弊害

仮想ホスト環境でも、唯一の「server_name」がリダイレクトURLのホスト名になってしまう事だが、そういう環境の場合は、上記の仮想ホストを作る対策(既定は無効なWebサイト)でいいので、そちらにすること。


### Apache の場合

設定ファイル(httpd.conf)の「**ServerName**」ディレクティブを設定する

![centos3.png](https://qiita-image-store.s3.amazonaws.com/0/182822/35809da9-0a0f-d437-bf88-e662c1418efb.png)

すると、こんな感じになる。

#### Apache2.4 系の場合

そもそも 2.4 系列からは、IPアドレスではなくて、「**hostname**」コマンドで指定された値が返されるようになったらしい。

![cebtos2.png](https://qiita-image-store.s3.amazonaws.com/0/182822/540d19ec-d447-a180-88c0-eb8b14bce2f5.png)

こんな感じ
「**localhost.localdomain**」って、CentOS の既定値だな。

それでも、おかしな値を **hostname** コマンドで指定すると、IPアドレスが出てしまう事もある。

![centos1.png](https://qiita-image-store.s3.amazonaws.com/0/182822/24e6479d-521b-8ec0-1110-e7499b9385be.png)

この画面例は IPv6 アドレスだけどね。

### IIS の場合

IIS4.0/5.0/5.1の場合、メタベースなど変更

これも、ググってくれ

この設定で、IPアドレスの代わりにコンピュータ名が使われるようになるが、コンピュータ名とNTドメイン名(ActiveDirectoryドメイン名)を工夫すると、コンピュータ名とはいいながら適切な FQDN として出力させる事もできるので、工夫してくれ

#### IIS の場合 URLScan を使う

- [IISのヘッダ情報の一部を消去](http://www.atmarkit.co.jp/fsecurity/rensai/securitytips/020iis.html)

#### IIS の場合 sISAPILocation を使う

昔、ISAPIフィルタ「[sISAPILocation](http://rocketeer.dip.jp/sanaki/free/free100.htm)」を作った。

これには、特定の値(例えば今回の事象で漏れてしまうプライベートIPアドレス)を、別の値(例えばFQDNの文字列)に書き換える機能があるので、それが使えると思う。
というか、このために作った。

#### IIS の場合 トレイディングスラッシュの強制

- [トレイディングスラッシュを強制する HttpModule{sForceTrailingSlash.dll}](http://rocketeer.dip.jp/sanaki/free/free151.htm)

という HttpModule を作ってみた。

これは、「no TrailingSlash」なディレクトリ要求を「TrailingSlash」にして、IISに渡す HttpModuleなので、今回のような事象は発生しないようにしている。

加えて
「no TrailingSlash」→「リダイレクト要求」→「TrailingSlashで再度リクエスト」→「求めていた結果」ではなく、
「no TrailingSlash」→「TrailingSlashにしてIISに渡す」→「求めていた結果」なので、通信上もメリットがあると思う。

### IIS の場合(蛇足)

これ以外にも基本認証を有効にしていると IPアドレスが漏れる場合があるので、注意。

# リンクと書籍

- [apache 2.4 の ServerName](https://chibitcpu.blogspot.com/2017/04/apache-24-servername.html)
- [ServerName ディレクティブ](http://httpd.apache.org/docs/2.4/ja/mod/core.html#servername)
- 「Apacheクックブック」(ISBN978-4-87311-381-4)
    - P189 "レシピ9.1 Hostフィールドがないリクエストを処理する"
    - P252 "レシピ13.3 「末尾のスラッシュ」問題を解決する"
    - P254 “レシピ13.5 Hostヘッダフィールドがないリクエストを処理する”
- オライリー「マスタリングnginx」(ISBN-13: 978-4873116457)
- [nginx はどのようにリクエストを処理するか - サーバ名未定義のリクエストの処理を防ぐ
How to prevent processing requests with undefined server names](
http://nginx.org/en/docs/http/request_processing.html#how_to_prevent_undefined_server_names)
- [NginxによるTrailingSlashのメモ](https://qiita.com/kt_higa/items/02b30907e7aeeac69d46)
- [Rails + Nginx環境で強制的にURLの最後に / を付ける方法](https://marketing-web.hatenablog.com/entry/trailing_slash_rails_nginx)
- [参考 : IIS が HTTP ヘッダー (Content-Location) で IP アドレスを返す](http://support.microsoft.com/kb/218180/ja)
- [フィールドには、TCP ヘッダーには、IIS 6.0 で IP アドレスが表示されます。](http://support.microsoft.com/default.aspx?scid=kb;ja;834141&sd=tech)
- [Removing an IIS server's IP address from HTTP responses](http://blogs.msdn.com/b/mike/archive/2008/11/18/removing-an-iis-server-s-ip-address-from-http-responses.aspx)

# 蛇足

ときどき、全ての正常なページ遷移(リンク)が「no TrailingSlash」な場合があるけど、これは
「no TrailingSlashな要求」→「30x リダイレクト要求」→「TrailingSlashにして再要求」→「求めていた結果」となるので、通信が2往復かかるので、ネットワークに無駄な負荷がかかるので、パフォーマンス上も「no TrailingSlashな要求」はよくないと思う。

今回のメインテーマは、パフォーマンス上もなにも、プライベートIPアドレスが知りたいので、あえて実行しているので、この項の正常なページ遷移とは異なるテーマなんだけど、一応書いておいた。

# 以上