概要
Apache の設定について共通化できるセキュリティ設定とその各項目についてまとめた。
設定例
必須設定
cat << _EOF_ > /etc/httpd/conf.d/security.conf
# バージョン情報の隠蔽
ServerTokens ProductOnly
Header always unset "X-Powered-By"
# httpoxy 対策
RequestHeader unset Proxy
# クリックジャッキング対策
Header always set X-Frame-Options "SAMEORIGIN"
# XSS対策
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
# XST対策
TraceEnable Off
<Directory /var/www/html>
# .htaccess の有効化
AllowOverride All
# ファイル一覧出力の禁止
Options -Indexes
</Directory>
_EOF_
cat /dev/null > /etc/httpd/conf.d/autoindex.conf ;
cat /dev/null > /etc/httpd/conf.d/userdir.conf ;
cat /dev/null > /etc/httpd/conf.d/welcome.conf ;
注意事項
- 外部サイトからiframeで呼び出しできなくなる
任意設定
cat << _EOF_ > /etc/httpd/conf.d/security-strict.conf
# DoS 攻撃対策
LimitRequestBody 10485760
LimitRequestFields 50
# slowloris 対策
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
# HTTPメソッドの制限
<Directory /var/www/html>
Require method GET POST
</Directory>
<Directory "/var/www/cgi-bin">
Require all denied
</Directory>
_EOF_
注意事項
- GET/POST 以外使えなくなる
- cgi-bin が使えなくなる
想定環境
本記事は主に CentOS で Yum を使って Apache をインストールしている想定での情報のため、環境に合わせて適宜読み替えること。
対象とする Apache のバージョンは、現在サポートされている 2.4 のみ1。詳細は Apache HTTP Server のサポート期限 を参照。
デフォルト値検証の環境情報
- CentOS 7.2.1511 (CentOS-7-x86_64-Minimal-1511.iso)
- Apache 2.4.6 (
yum install httpd
) - PHP 5.4.16 (
yum install php
)
ポリシー
- Yum によるパッケージ管理
- ソースからコンパイル?そんなものウチにはないよ。
- デフォルトの設定ファイルに極力手を入れない
- コストパフォーマンス優先
- 成立の可能性が低い脆弱性への対応で汎用性やシンプルさが失われるような設定は避ける
設定項目
情報の隠匿(隠蔽)
バージョンなどの情報隠匿については、セキュリティ対策としての実効性に関する議論 2 が一応ある。
バージョン情報(ServerTokens)
Server: Apache/2.4.6 (CentOS) PHP/5.4.16
Apache 2.23 / 2.44 共に ServerTokens
ディレクティブのデフォルト値は Full
のため、 HTTP ヘッダーに上記のように Apache のバージョンが出力される。
ServerTokens ProductOnly
上記のように ServerTokens
ディレクティブに Prod
または ProductOnly
を指定することで、以下のように Apache のバージョン情報を隠蔽できる。
Server: Apache
ServerSignature
Apache/2.2.15 (CentOS) Server at 192.168.56.101 Port 80
ServerSignature
ディレクティブは、 サーバーが生成するドキュメント(エラーメッセージ、mod_proxy における FTP のディレクトリーリスト、 mod_info の出力等)の最下行に上記のような出力を付与する設定を行う。
ServerSignature Off
Apache 2.25 / 2.46 共にデフォルト値は Off
になっているが、CentOS 6.x の Apache 2.2 ではディストリビューション側の設定で On
になっているためか、書き換える必要がある。
なお、 httpd.conf の設定を変更していない場合、 <Directory "/var/www/html">
内で指定しないと機能しない。
TRACEメソッドの無効化(XST対策)
TraceEnable Off
XSS と TRACE メソッドを組み合わせた XST (クロスサイトトレーシング)攻撃への対策。
BASIC認証のIDとパスワード等が漏洩する危険があるが、サポート切れの古いOSなど攻撃成立条件は限定的7 8 である。
なお、TRACE メソッドは <Limit>
や <LimitExcept>
ディレクティブでは制限できない。9
エンティティタグ(ETag)
過去の Apache では HTTP ヘッダーに出力する ETag に inode 番号を強制的に利用していた10ため、ETag ヘッダーからファイルの inode 番号を入手されるリスクがあった。11
ETagを削除して Last-Modified
ヘッダーを使えば HTTP ヘッダーのサイズがその分少なくなるというメリットがある。ETag を出力しない設定は以下の通り。
FileETag None
上記設定ではうまく ETag が消えない場合は、以下のように消すことも可能。
Header unset ETag
FileETag 設定の挙動検証
FileETag | ETag |
---|---|
(未指定) | "220-529841bdd9a78" |
MTime Size | "220-529841bdd9a78" |
All | "905069-220-529841bdd9a78" |
INode | "905069" |
MTime | "529830adcea90" |
Size | "220" |
公式リファレンスのデフォルト値は未だに FileETag INode MTime Size
と記載されている10が、検証環境で検証したところデフォルトでは MTime Size
だった。~~リファレンスの更新漏れか、あるいはディストリビューションのパッケージでデフォルト値を変更しているか。~~はてブで指摘があったのでソースを調べたら12Apache本体のデフォルト値が 2.4.0 から変わってたので、やはりリファレンスの更新漏れの模様。(英語版13は正しく修正されている by @matuuさん)
-<default>FileETag INode MTime Size</default>
+<default>FileETag MTime Size</default>
<contextlist><context>server config</context><context>virtual host</context>
<context>directory</context><context>.htaccess</context>
</contextlist>
<override>FileInfo</override>
+<compatibility>The default used to be "INode MTime Size" in 2.3.14 and
+earlier.</compatibility>
-#define ETAG_BACKWARD (ETAG_MTIME | ETAG_INODE | ETAG_SIZE)
#define ETAG_ALL (ETAG_MTIME | ETAG_INODE | ETAG_SIZE)
+/* This is the default value used */
+#define ETAG_BACKWARD (ETAG_MTIME | ETAG_SIZE)
if (ctx->finfo.filetype != APR_NOFILE) {
return apr_psprintf(ctx->pool, "\"%" APR_UINT64_T_HEX_FMT "-%"
- APR_UINT64_T_HEX_FMT "-%" APR_UINT64_T_HEX_FMT "\"",
+ APR_UINT64_T_HEX_FMT "\"",
- (apr_uint64_t) ctx->finfo.inode,
(apr_uint64_t) ctx->finfo.size,
(apr_uint64_t) ctx->finfo.mtime);
}
X-Powered-By
X-Powered-By: PHP/5.4.16
HTTP ヘッダーに上記のように PHP などのバージョンが出力されている場合があるので、以下のように Apache 側でヘッダーを強制削除する。
Header always unset "X-Powered-By"
PHP の場合は以下のように php.ini の expose_php
ディレクティブ 14 で非表示にする設定が可能だが、Apache 側で一元的に強制削除した方が設定漏れのリスクがないだろう。
expose_php = Off
Options -Indexes
<Directory /var/www/html>
Options -Indexes
</Directory>
Apache 2.0/2.2/2.4 共に Options
のデフォルト値は All
。
DirectoryIndex
ディレクティブ 15 で指定したファイル (index.html等) がディレクトリー内に無い場合に mod_autoindex がディレクトリー内のファイル一覧を整形して返す。
autoindex.conf
cp /dev/null /etc/httpd/conf.d/autoindex.conf
または
> /etc/httpd/conf.d/autoindex.conf
iconsの設定等が記載されているが、ディレクトリ一覧は表示させないため利用しない。ファイル自体を削除するとアップデート時に再作成されるので、空ファイルにする。
welcome.conf
cp /dev/null /etc/httpd/conf.d/welcome.conf
または
> /etc/httpd/conf.d/welcome.conf
ドキュメントルートに index.html がない場合など Forbidden になると OS のウェルカムページが表示されるが、余計な情報になるので削除。autoindex.conf と同様に削除するとアップデート時に再作成されるため空ファイルにする。
セキュリティ設定
AllowOverride
<Directory /var/www/html>
AllowOverride All
</Directory>
/etc/httpd/conf.d/userdir.conf
の <Directory "/home/*/public_html">
で指定されている AllowOverride
以外はすべて None
が指定されているので、.htaccess を利用するためにドキュメントルート配下を個別に許可する。
HTTP メソッドの制限
<Directory /var/www/html>
Require method GET POST
</Directory>
X-Frame-Options(クリックジャッキング対策)
Header always append X-Frame-Options SAMEORIGIN
X-Frame-Options HTTP レスポンスヘッダーは、ブラウザーがページを <frame>
または <iframe>
の内部に表示することを許可するかを示すことができる。
クリックジャッキング対策として IE8 から実装されたオプションヘッダー。
自分のサイトのコンテンツが他のサイトに埋め込まれないことを保証する。16
X-Frame-Options
に対応するブラウザーのバージョンは IE8 以上、Firefox 3.6.9 以上、Chrome 4.1.249.1042 以上、Safari 4 以上、Opera 10.50 以上。18
Google、Twitter、Yahoo! JAPAN などで SAMEORIGIN
が指定されている。
Facebook では DENY
が指定されている。
X-XSS-Protection(XSSフィルター機能)
Header always set X-XSS-Protection "1; mode=block"
X-XSS-Protection
はブラウザの XSS フィルター機能を制御できるレスポンスヘッダー。
0
は無効、 1
は有効(部分的書き換え)、 1; mode=block
は有効(表示の完全な停止)を意味する。
サイトの XSS 対策に問題はなく誤検知をなくしたい場合は 0
を、そうでない場合は 1; mode=block
を指定するのが望ましく、デフォルトの 1
の状態は望ましくない。 19
Google、Twitter、Yahoo! JAPAN などで指定されている。
Facebook では 0
が指定されている。
X-Content-Type-Options
Header always set X-Content-Type-Options nosniff
X-Content-Type-Options
レスポンスヘッダーの値に nosniff
を設定して送信すると、Internet Explorer が MIME Sniffing 機能で content-type 宣言を回避するのを防止できる。20
Facebook、Twitter、Yahoo! JAPAN などで指定されている。
Content Security Policy (CSP)
素人にはお勧めできない。
https://content-security-policy.com/
http://blog.hash-c.co.jp/2013/12/Content-Security-Policy-CSP.html
httpoxy 対策
Foo: Bar っていう header 送ったら CGI の spec 的には HTTP_Foo = Bar にしてくれるっていう仕様を突いて PROXY: xxx っていうheader送ると HTTP_PROXY書き換えられるんじゃねっていう脆弱性。21
HTTPOXY Vulnerability Checking Tool でテストできる。
以下のソフトウエアが影響を受ける。22
- PHP (CVE-2016-5385)
- GO (CVE-2016-5386)
- Apache HTTP Server (CVE-2016-5387)
- Apache Tomcat (CVE-2016-5388)
- HHVM (CVE-2016-1000109)
- Python (CVE-2016-1000110
LimitRequestBody
このディレクティブはリクエストボディに許されるバイト数を指定する。
ディレクティブが書かれたコンテキスト(サーバ全体、ディレクトリ、ファイル、ロケーション)内で許容する HTTP リクエストメッセージボディのサイズに制限をかけることができる。
デフォルト値は 0
で無制限。上限は 2147483647
(2GB) まで。
LimitRequestBody 10485760
10MiB に制限したい場合は上記のように記述。リファレンスで DoS 攻撃を避けるのに有効としている。
なお、PHP では以下のデフォルト値が設定されているので併せて確認したい。
memory_limit = 128M
post_max_size = 8M
upload_max_filesize = 5M
LimitRequestFields
このディレクティブは HTTP リクエストにおいて許可するリクエストヘッダフィールド数を指定する。
デフォルト値は 100
になっている。
LimitRequestFields 50
リファレンスには「リクエストヘッダーフィールドの数が 20 を超えることはほとんどない。」23 とある。また、DoS 攻撃を避けるのに有効としている。
なお、値を 20 に設定していたら特定の Web ページで Chrome においてのみ Bad Request が返されたとする報告があり、参照する Web ページやブラウザによって挙動が異なることもあるようだ。 24
RequestReadTimeout
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
slowloris 25 対策で実装された mod_reqtimeout モジュールで使用できるディレクティブ。
2.2.15 以降に実装され、2.3.15 以降はデフォルトで有効になった。
AWS の ELB を利用している場合、 ELB の Connection Settings: Idle Timeout
の値が Apache の RequestReadTimeout header
の最低値よりも大きいと、 Apache のエラーログに 408 が大量に吐かれてしまうようなので注意。26
セキュリティテスト
CentOS 7.2.1511 に yum で Apache をインストールして設定変更していないケースをテストした結果。
[root@localhost program]# perl ./nikto.pl -h 127.0.0.1
- ***** SSL support not available (see docs for SSL install) *****
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 127.0.0.1
+ Target Hostname: 127.0.0.1
+ Target Port: 80
+ Start Time: 2016-01-16 10:00:00 (GMT9)
---------------------------------------------------------------------------
+ Server: Apache/2.4.6 (CentOS) PHP/5.4.16
+ Server leaks inodes via ETags, header found with file /, fields: 0x220 0x529841bdd9a78
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ PHP/5.4.16 appears to be outdated (current is at least 5.6.9). PHP 5.5.25 and 5.4.41 are also current.
+ Apache/2.4.6 appears to be outdated (current is at least Apache/2.4.16). Apache 2.2.31 is also current for the 2.x branch.
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS, TRACE
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ Retrieved x-powered-by header: PHP/5.4.16
+ OSVDB-3092: /test.php: This might be interesting...
+ 8225 requests: 0 error(s) and 10 item(s) reported on remote host
+ End Time: 2016-01-16 10:00:11 (GMT9) (11 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Apache 関連記事
- Apacheセキュリティ設定
- Apache HTTP Server のサポート期限
- Apache のログをコマンドラインで集計する
- Apache の情報をコマンドラインで取得する
- IPアドレスから国や都市を判別する (GeoIP)
- Apache チューニング スクリプト
-
Apache 2.2 は2017年7月11日に 2.2.34 をリリースし、2017年12月31日をもって2.2系の開発終了を宣言している。
Apache HTTP Server のサポート期限 #Apache - Qiita - qiita.com ↩ -
ApacheやOSのバージョンを表示しないようにする方法や、PHPでX-Powered-Byを応答しなくする方法が紹介された記事ですが、コメント欄や260件以上の登録を集めたはてなブックマークでは賛否両論になっています。
サーバのバージョンは隠すのが常識? | スラド オープンソース - opensource.srad.jp ↩ -
このディレクティブは、クライアントに送り返す Server 応答ヘッダ内に、サーバの一般的な OS 種別や、 コンパイルされて組み込まれているモジュールの情報を含めるかどうかを指定します。
core - Apache HTTP サーバ バージョン 2.2 - httpd.apache.org ↩ -
このディレクティブは、クライアントに送り返す Server 応答ヘッダ内に、サーバの一般的な OS 種別や、 コンパイルされて組み込まれているモジュールの情報を含めるかどうかを指定します。
core - Apache HTTP サーバ バージョン 2.4 - httpd.apache.org ↩ -
https://httpd.apache.org/docs/2.2/ja/mod/core.html#serversignature ↩
-
https://httpd.apache.org/docs/2.4/ja/mod/core.html#serversignature ↩
-
http://blog.tokumaru.org/2013/01/TRACE-method-is-not-so-dangerous-in-fact.html ↩
-
http://httpd.apache.org/docs/2.4/ja/mod/core.html#fileetag ↩ ↩2
-
http://www.iss.net/security_center/reference/jp/vuln/apache-mime-information-disclosure.htm
ただ、検証および調査したところ Apache 2.4.0 からはデフォルト値はMTime Size
になっており、2.4 系ではセキュリティ面では本設定は気にする必要はない。
2.2 系ではFileETag MTime Size
またはFileETag None
を指定するといいだろう。 ↩ -
https://github.com/apache/httpd/commit/ba86234a7e627a50fdedc50b49ceaf40465911cb ↩
-
http://httpd.apache.org/docs/2.4/en/mod/core.html#fileetag ↩
-
https://httpd.apache.org/docs/2.4/ja/mod/mod_dir.html#directoryindex ↩
-
https://developer.mozilla.org/ja/docs/HTTP/X-Frame-Options
| 設定値 | 内容 |
|---|---|
|DENY
| サイト側の意図に関わらず、ページをフレーム内に表示することはできない。同じサイトのページをフレーム内に読み込むことも不可能になる。 |
|SAMEORIGIN
| 自身と生成元が同じフレーム内に限りページを表示することができる。外部サイトのフレーム内にページを読み込むことを不可能にする。 |
|ALLOW-FROM uri
| 指定された生成元に限り、ページをフレーム内に表示できる。Chrome、Safariは未対応。17 | ↩ -
Issue 511521 - chromium - `X-Frame-Options` does not support the `allow-from` directive. - Monorail ↩
-
2008/9/3 - Internet Explorer 8 のセキュリティ Part VI: Beta 2 の更新項目 ↩
-
http://b.hatena.ne.jp/entry/294900783/comment/yosuke_furukawa ↩
-
http://httpd.apache.org/docs/2.4/mod/core.html#LimitRequestFields ↩