[SpringBoot][Tips] レスポンスヘッダからServer情報を消す
こんにちは。こむろ@札幌です。北海道のくせに猛暑日で溶けそうです。我が家にはエアコンがないのです(むしろ道内はある方が珍しい)
北大の中の様子。気持ちの良い緑(暑いけど)
はじめに
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.xml
の Connector
を修正します。こちらに 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