[SpringBoot][Tips] レスポンスヘッダからServer情報を消す

2016.08.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。こむろ@札幌です。北海道のくせに猛暑日で溶けそうです。我が家にはエアコンがないのです(むしろ道内はある方が珍しい)

IMG_20160724_162849

北大の中の様子。気持ちの良い緑(暑いけど)

はじめに

SpringBootで内包されているTomcatを利用すると、ヘッダ情報でサーバーのコンテナ名が表示されます。お客様によっては、この辺りの情報を削除して欲しいと言う要望があるかと思います。今回は、その要望を解決するための手法をご紹介します。

Serverの情報を制御する設定値ですが、SpringBootとTomcatではちょっとした違いがありました。さらにこの情報をまるっと消すための方法もありましたので、こちらもご参照ください。

ちなみに自分の環境は以下の様な環境で実装しています。

  • SpringBoot 1.3.2.RELEASE
  • java version "1.8.0_91"

レスポンスヘッダに含まれるServer

レスポンスヘッダには様々な情報が含まれています。レスポンスに関する大事なメタ情報があり、これらを使ってユーザーの利用するクライアントアプリは処理を行っています。そんな中には、たまーに動作しているサーバーに関する情報なども含まれます。まあ、これらはユーザーにとって特に益があるものではない上、攻撃者のためのヒントになるということから(今はあんまり関係ない?)、消したり偽装したりするのが望ましいとされているようです。

まずは、どのようなレスポンスヘッダが取得できるか確認してみます。起動しているSpringBootアプリケーションに存在しないパスを指定し、GETを実行します。以下の様なレスポンスが取得できました。

GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: _ga=xxxxxxxxxxxxxxxx
Connection: keep-alive

HTTP/1.1 404 Not Found
Content-Language: ja
Content-Type: text/html;charset=UTF-8
Date: Mon, 01 Aug 2016 09:12:50 GMT
Server: Apache-Coyote/1.1
Content-Length: 4837
Connection: keep-alive

コンテンツの長さや言語、HTTPステータスなどと一緒に返却されているのが、今回問題になってるこちら。

  • Server: Apache-Coyote/1.1

この情報を削除(もしくは偽装)するのが今回の目的になります。

Tomcatの場合

Tomcatの場合は、設定ファイル server.xmlConnector を修正します。こちらに server= という項目を追加すれば良いようです。

<Connector port="8080" protocol="HTTP/1.1" 
    server="hoge-hoge"
    connectionTimeout="20000" 
    redirectPort="8443" 
/>

SpringBootの場合

さて、本題であるSpringBootの場合はどうすればよいでしょう。

基本的に設定関係はほぼ application.yml (もしくは application.properties )に集約されています。ファイルに設定可能な値は、こちらに全て記載されています。ご参照ください。

application.properties において消したい対象の server にあたる設定値は以下になります。

server.server-header= "hoge.hoge"

application.yaml の設定値だと以下の様な記述になります。

server:
  server-header: "hoge.hoge"

これでレスポンスヘッダの server 部分を書き換えることが出来ます。

プロパティの説明には「no header is sent if empty」と書いてあるので、空にすればよいのかと色々と試行錯誤してみたのですが、こちらは結果が変わりませんでした。以下に試行錯誤した内容を一応記載しました。

serverの値を空にしたい

server-header の設定ですが、空白文字や未設定は許されていないようです。

設定なし

server:
  server-header:

これはNG。Apache-Coyote/1.1 が表示されます。

空文字

server:
  server-header: ""

これはNG。Apache-Coyote/1.1 が表示されます。

半角空白

server:
  server-header: " "

これもNG。Apache-Coyote/1.1 が表示されます。

全角空白

server:
  server-header: " "

これもNG。Apache-Coyote/1.1 が表示されます。

全角文字

server:
  server-header: "さんぷる"

これだと Server に空白文字が設定されます。 *1いずれの場合も、なかなかいうことを聞いてくれません。そのため、 1.3.2.RELEASE のバージョンでは削除ではなく偽装をする方向に倒した方が筋が良さそうです。

項目そのものを消せない?

Serverの表記そのものをDisableにする方法については、SpringBootのIssueに上がっていました。

スレッドを読みすすめていくと、SpringBootの 1.4.0.RELEASE で解決しているようです。試してみましょう。

build.gradle

buildscript {
    ext {
        springBootVersion = '1.4.0.RELEASE'
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

上記のようにバージョンを設定したら以下のコマンドを実行します。

IntelliJ IDEAのGUIツールを使うと微妙にキャッシュが残ったりしてアプリケーションの起動にコケたりすることがあるので、コマンドを実行したほうが良いです。

実行

$ ./gradlew clean bootRun --refresh-dependencies

結果

curlコマンドでヘッダごとダンプして確認します。

$ curl -D - http://localhost:8080
HTTP/1.1 404
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 08 Aug 2016 07:27:37 GMT

おお!見事に消えています。設定値も効かなくなってるようです。

1.3.2.RELEASEの場合

1.3.2.RELEASE でビルドしたもので再度確認してみます。

build.gradle

buildscript {
    ext {
        springBootVersion = '1.3.2.RELEASE'
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

先程のアプリケーション起動のコマンドを実行します。

結果

curlコマンドでヘッダごとダンプして確認します。

$ curl -D - http://localhost:8080
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 08 Aug 2016 07:33:11 GMT

お。Server: Apache-Coyote/1.1 が復活しました。やはり、 1.4.0.RELEASE で項目ごとなくなってますね。

まとめ

SpringBootは、1.4.0.RELEASE でレスポンスヘッダの Server はデフォルトで表示されないように鳴っていました。

なので、特に指定がなければ 1.4.0.RELASE 以降を使っておきましょう。どうしても 1.4.0 系以前を利用しなくてはならない場合は、 application.yml の設定値で対応しましょう。

おまけ

Tomcatのリファレンスを確認したところ、次のような記載がありました。

Unless you are paranoid, you won't need this feature.

つまり「あなたが余程偏執的でなければ、このパラメータは不要です。」って言っている?まあ、Apache-Coyote/1.1 は特に指定がなければデフォルトで入る文字列のようですし、特に消したところでセキュリティ的にも安全にならないんでしょうか? *2

参照

脚注

  1. 良いとは思いませんが
  2. いつからこの表記が出たんだろう?