HTTPレスポンスヘッダーのバナー情報隠ぺいは無意味ではないけど根本的な対策ではない、という話


公開Webサーバーのバージョン露出は一般的には好ましくなく、安全対策として隠すことが推奨されています。

WebサーバとPHPのバージョンは、HTTPレスポンスヘッダーから取得できます(バナー情報)。バナー情報を隠すこと自体は全く無意味な対策ではないと思いますが、ただ、ネット上のサイトを色々見ているとバージョン番号を消す方法についてだけ書かれているものが多く、それ以上については踏み込んでいないサイトが多い印象がありました。そもそも、なぜデフォルトの状態では出力されているのでしょう? 何の意味もなく出力しているだけなのでしょうか?

隠ぺいを主要な安全対策とする方法は「隠ぺいによるセキュリティ」と呼ばれます。が、これは安全性を担保しにくいというか、それだけに頼ることは避けるべきものです。

この記事では、HTTPレスポンスヘッダーからApache、NGINX、PHPのバナー情報を秘匿する方法も記載すると同時に、「隠ぺいのセキュリティ」についても踏み込んで考えてみたいと思います。

ちなみに、Qiitaでは初となる記事です(今まで自分のブログで書いていました)。不備や誤りについてはご指摘下さいますと幸いです。

何が問題か

HTTPレスポンスヘッダーにバナー情報を出している場合、Webサーバーの該当バージョンに脆弱性が存在すると、その情報をわざわざ晒していることになります。

以下、実際のHTTPレスポンスヘッダを見てみましょう。
Apache HTTP ServerとNGINXは、インストール後のデフォルト状態では、HTTPレスポンスヘッダーの中、Server:でバージョン番号を返します。X-Powered-By:はPHPのバージョン番号ですが、PHPもデフォルトではバージョン番号を返します。

ApacheのHTTPレスポンスヘッダー
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Date: Tue, 27 Oct 2020 10:13:54 GMT
Keep-Alive: timeout=5, max=100
Link: <http://192.168.1.100/index.php>; rel="https://api.w.org/"
Server: Apache/2.4.37 (centos)
Transfer-Encoding: chunked
X-Powered-By: PHP/7.4.11
NGINXのHTTPレスポンスヘッダー
ontent-Encoding: gzip
Content-Type: text/html
Date: Wed, 28 Oct 2020 10:57:07 GMT
ETag: W/"5f4d14be-264"
Last-Modified: Mon, 31 Aug 2020 15:18:22 GMT
Server: nginx/1.18.0 (Ubuntu)

ChromeでもSafariでも最近のWebブラウザであれば、開発者ツール(デベロッパーツールとも)を使えば、上の情報は簡単に見ることが可能です。Chromeの場合、デベロッパーツールを開き、ネットワークを選択してページを読み込むと、下のHeadersから確認できます(下図参照)。

公表されている脆弱性については、ソフトウェアの脆弱性に関するデータベースであるJVN iPediaで確認できます。2020年に公表されているApache HTTP Serverの脆弱性を調べてみると、3件存在します(2020年10月時点)。

ちなみに、SHODANもこれらの情報を収集していると思われます。脆弱性が公表されている場合、放置するのは明らかに危険でしょう。

バナー情報を隠ぺいする方法

難しくはありません。

Apacheの場合、httpd.confに以下の1行を追加、もしくは修正します。
※設定方法の詳細はServerTokens Directive(Apache)をご確認下さい。

httpd.conf
ServerTokens Prod

NGINXは、nginx.confに以下の1文を追記します。
※設定の詳細はserver_tokens(NGINX)をご確認下さい。

nginx.conf
http {
    …
    server_tokens off;
}

PHPのバージョン番号(X-Powered-By)は、php.iniを修正することで隠ぺい可能です。
expose_php(PHP)

php.ini
expose_php = Off

設定ファイルの修正後は、忘れずに再起動・もしくは設定反映を実施しましょう。
修正自体は簡単ですね。

でも、何のためにバナー情報なんて出力するの?

ヒントは、Apache HTTP Serverマニュアル中のコメントです(英語のほう)。なぜか、日本語訳の方には記載がありませんでした。

Setting ServerTokens to less than minimal is not recommended because it makes it more difficult to debug interoperational problems. Also note that disabling the Server: header does nothing at all to make your server more secure. The idea of "security through obscurity" is a myth and leads to a false sense of safety.
(拙訳:相互作用的な問題をデバッグすることが困難になるため、ServerTokensをminimal未満に設定することは推奨されません。また、Server:ヘッダを無効にすることは、全くあなたのサーバーをセキュアにすることはありません。"隠ぺいによるセキュリティ"の考え方は神話であり、安全性のついての誤った感覚へと導きます。)

つまり、Webサーバー・ブラウザ間のデバッグのため、だそうです。
また、少し古い情報ですが、以下のブログにも記載があります。

Kazuho@Cybozu Labs 奥 一穂のお仕事ブログ (2007/9/5)

なぜサーバのバージョン情報を公開する必要があるのか。それは、クライアント側で、サーバのバグや規格解釈の相違に起因する問題を回避するためです。

要するに、サーバー側のバグ、実装や規格解釈の相違に対応するためで、無意味に出力しているわけではないようです。

バージョンを隠ぺいしても確認できる方法は実はある

実は、バナー情報を隠したところで、バレないわけではありません。

以下のサイトで解説されていますが、「実際に脆弱性を突く」、「HTTPレスポンスの違いからバージョンを推測する」という方法で、サーバーのバージョンを推測可能です。

後者のサイトで詳しく説明されていますが、Apache 2.4.39と2.4.41で「404 Not Found」のレスポンスが異なるので、そこで確認ができるのだとか。

「隠ぺいする」という方法は、リスクの元となる情報をわざわざ外部に露出させないという点では確かに有意義ですが、「隠すだけ」では問題の根本解決にはなりません。上の2つのサイトで説明されている方法以外にも、今は露見していないだけで後々発見される可能性はあります。

ちなみに、Mozillaのサイトに以下の説明があります。
Server (MDN web docs)

Server の値は、攻撃者が既知のセキュリティホールを悪用するのを (少し) 容易にする情報を暴露する可能性があるので、過度に詳細にすることは避けてください。

"(少し)"とわざわざ付け加えてあるのが、気になります。原文ではslightlyですが、避けてくださいとは言いつつも、微少な対策だというニュアンスが感じ取れそうです。

「隠すだけ」という方法には問題がありそうです。

「隠しているだけ」なら問題

「隠ぺい」が安全性の主要な担保となる考え方を、英語では"Security through obscurity" (もしくは"Security by obscurity")と呼び、明確に呼び名があるようです。日本語に訳すと「隠ぺいによるセキュリティ」でしょうか。obscurityは不明や難読の意味があり、難読化も対象に含みます。

日本語の情報源はネット上に少ないですが、Security through obscurity(Wikipedia)に詳しい説明があります(英語)。「遡ると1851年以降から専門家はこの考え方を否定しており、隠ぺいだけが安全性のメカニズムであってはいけないと助言している」と冒頭にあります。

ApacheやPHPのバナー情報を隠す方法を解説したWebサイトは探すと結構見つかると思いますが、バナーを隠すだけでなく最新の修正パッチを当てるなど別の方法にまで踏み込んで解説しているサイトはあまりない印象です。ですが、ここは無視できないポイントでしょう。

CentOS 8のデフォルトのbaseリポジトリーからインストールされるApacheのバージョンは2.4.37ですが、実はこれも脆弱性を含んだバージョンですので、放置は禁物です。上でも書きましたが、バナー情報を隠すこと自体は本当に些細な対処でしかありません。

「隠ぺいによるセキュリティ」は脆弱性になりうる

CWE(Common Weakness Enumeration: 共通脆弱性タイプ一覧)はソフトウェアの脆弱性を定義したものですが、「隠ぺいによるセキュリティ」も脆弱性の1つとして数えられているようです(意外でした)。

This reliance on "security through obscurity" can produce resultant weaknesses if an attacker is able to reverse engineer the inner workings of the mechanism. Note that obscurity can be one small part of defense in depth, since it can create more work for an attacker; however, it is a significant risk if used as the primary means of protection.
(拙訳:もし攻撃者が仕組みの内部的な働きをリバースエンジニアリングすることが可能なら、「隠ぺいのセキュリティ」への依存は結果として脆弱性を生み出す可能性がある。攻撃者に対する作業を増やすことができるため、隠ぺいは綿密な防御の1つの小さな部分にはなりえることは覚えておいて下さい。しかし、主要な保護手段として使うのなら、それは重大なリスクです。)

「とりあえずバージョン番号だけ消しておこう」で終わると、リスクをいつまでも抱えたままで根本的には何も解決していないことになります。

組織内部のイントラサイトなら攻撃される機会はそれほどないかもしれませんが、グローバルIPを持つWebサーバーに対しては、修正版がリリースされているのであればインストールするなどの根本的な対処が必要でしょう。他サーバーに対する踏み台にされてしまったら、管理者としては目も当てられません。

だけど、隠すことは全く無意味なことではない

下の記事でも書かれていますが、完全な対策ではないにしても、複数の対策を施して多層的にすることでリスクを減らすことができるという考え方もあります。

それに、必要もないのに、わざわざ判断材料になる情報を公開する必要もないでしょう。

ただ、何度も書いた通り、ちゃんとソフトウェアをアップグレードするなどの根本的な対策が重要になりそうです。

以上。

 
 
文中であげた以外の参考サイト