Help us understand the problem. What is going on with this article?

Apacheセキュリティ設定

概要

Apache の設定について共通化できるセキュリティ設定とその各項目についてまとめた。

設定例

必須設定

cat << _EOF_ > /etc/httpd/conf.d/security.conf
# バージョン情報の隠蔽
ServerTokens Prod 
Header unset "X-Powered-By"
# httpoxy 対策
RequestHeader unset Proxy
# クリックジャッキング対策
Header append X-Frame-Options SAMEORIGIN
# XSS対策
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options nosniff
# XST対策
TraceEnable Off

<Directory /var/www/html>
    # .htaccess の有効化
    AllowOverride All
    # ファイル一覧出力の禁止
    Options -Indexes
    # Apache 2.2以前の対策
    <IfVersion < 2.3>
        # バージョン情報の隠蔽
        ServerSignature Off
        # ETagのinode情報の隠蔽
        FileETag MTime Size
    </IfVersion>
</Directory>

<Directory "/var/www/cgi-bin">
    <IfVersion < 2.3>
        ServerSignature Off
        FileETag MTime Size
    </IfVersion>
</Directory>
_EOF_
CentOS7
cat /dev/null > /etc/httpd/conf.d/autoindex.conf ;
cat /dev/null > /etc/httpd/conf.d/welcome.conf ;

注意事項

  • 外部サイトからiframeで呼び出しできなくなる
  • Apache 2.2 の場合 ServerSignatureDirectory ディレクティブ内で指定しないと上書きされない。
  • 現状の上記設定では Apache 2.2 で以下が上書きされない
    • Options -Indexes
    • <Directory "/var/www/cgi-bin">

任意設定

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>
    <IfVersion > 2.4>
        Require method GET POST
    </IfVersion>
    <IfVersion < 2.3>
        <Limit GET POST>
            Order allow,deny
            Allow from all
        </Limit>
        <LimitExcept GET POST>
            Order deny,allow
            Deny from all
        </LimitExcept>
    </IfVersion>
</Directory>

<Directory "/var/www/cgi-bin">
    <IfVersion > 2.4>
        Require all denied
    </IfVersion>
    <IfVersion < 2.3>
        Order allow,deny
        Deny from all
    </IfVersion>
</Directory>
_EOF_

注意事項

  • GET/POST 以外使えなくなる
  • cgi-bin が使えなくなる
  • 現状の上記設定では Apache 2.2 で <Directory "/var/www/cgi-bin"> が上書きされない

想定環境

本記事は主に CentOS で Yum を使って Apache をインストールしている想定での情報のため、環境に合わせて適宜読み替えること。
対象とする Apache のバージョンは、現在サポートされている 2.42.2 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)

HTTPレスポンスヘッダー
Server: Apache/2.4.6 (CentOS) PHP/5.4.16

Apache 2.23 / 2.44 共に ServerTokens ディレクティブのデフォルト値は Full のため、 HTTP ヘッダーに上記のように Apache のバージョンが出力される。

ServerTokens Prod

上記のように ServerTokens ディレクティブに Prod または ProductOnly を指定することで、以下のように Apache のバージョン情報を隠蔽できる。

HTTPレスポンスヘッダー
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
ただ、検証および調査したところ Apache 2.4.0 からはデフォルト値は MTime Size になっており、2.4 系ではセキュリティ面では本設定は気にする必要はない。
2.2 系では FileETag MTime Size または FileETag None を指定するといいだろう。

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さん)

docs/manual/mod/core.xml
-<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&nbsp;MTime&nbsp;Size" in 2.3.14 and
+earlier.</compatibility>
include/http_core.h
-#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)
modules/dav/fs/repos.c
     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 unset X-Powered-By

PHP の場合は以下のように php.ini の expose_php ディレクティブ 14 で非表示にする設定が可能だが、Apache 側で一元的に強制削除した方が設定漏れのリスクがないだろう。

php.ini
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 になると CentOS のウェルカムページが表示されるが、余計な情報になるので削除。autoindex.conf と同様に削除するとアップデート時に再作成されるため空ファイルにする。

セキュリティ設定

AllowOverride

<Directory /var/www/html>
    AllowOverride All
</Directory>

/etc/httpd/conf.d/userdir.conf<Directory "/home/*/public_html"> で指定されている AllowOverride 以外はすべて None が指定されているので、.htaccess を利用するためにドキュメントルート配下を個別に許可する。

HTTP メソッドの制限

2.4
<Directory /var/www/html>
    Require method GET POST
</Directory>
2.2
<Directory /var/www/html>
    <Limit GET POST>
        Order allow,deny
        Allow from all
    </Limit>
    <LimitExcept GET POST>
        Order deny,allow
        Deny from all
    </LimitExcept>
</IfVersion>

X-Frame-Options(クリックジャッキング対策)

Header always append X-Frame-Options SAMEORIGIN

X-Frame-Options HTTP レスポンスヘッダーは、ブラウザーがページを <frame> または <iframe> の内部に表示することを許可するかを示すことができる。
クリックジャッキング対策として IE8 から実装されたオプションヘッダー。
自分のサイトのコンテンツが他のサイトに埋め込まれないことを保証する。16

設定値 内容
DENY サイト側の意図に関わらず、ページをフレーム内に表示することはできない。同じサイトのページをフレーム内に読み込むことも不可能になる。
SAMEORIGIN 自身と生成元が同じフレーム内に限りページを表示することができる。外部サイトのフレーム内にページを読み込むことを不可能にする。
ALLOW-FROM uri 指定された生成元に限り、ページをフレーム内に表示できる。Chrome、Safariは未対応。17

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 では以下のデフォルト値が設定されているので併せて確認したい。

php.ini
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 関連記事

参照情報


  1. http://qiita.com/bezeklik/items/7e2c02c3eabd2a416231 

  2. サーバのバージョンは隠すのが常識? | スラド オープンソース 

  3. https://httpd.apache.org/docs/2.2/ja/mod/core.html#servertokens 

  4. https://httpd.apache.org/docs/2.4/ja/mod/core.html#servertokens 

  5. https://httpd.apache.org/docs/2.2/ja/mod/core.html#serversignature 

  6. https://httpd.apache.org/docs/2.4/ja/mod/core.html#serversignature 

  7. http://blog.tokumaru.org/2013/01/TRACE-method-is-not-so-dangerous-in-fact.html 

  8. http://n.pentest.ninja/?p=952 

  9. https://httpd.apache.org/docs/2.4/ja/mod/core.html#limit 

  10. http://httpd.apache.org/docs/2.4/ja/mod/core.html#fileetag 

  11. http://www.iss.net/security_center/reference/jp/vuln/apache-mime-information-disclosure.htm 

  12. https://github.com/apache/httpd/commit/ba86234a7e627a50fdedc50b49ceaf40465911cb 

  13. http://httpd.apache.org/docs/2.4/en/mod/core.html#fileetag 

  14. http://php.net/manual/ja/ini.core.php#ini.expose-php 

  15. https://httpd.apache.org/docs/2.4/ja/mod/mod_dir.html#directoryindex 

  16. https://developer.mozilla.org/ja/docs/HTTP/X-Frame-Options 

  17. Issue 511521 - chromium - `X-Frame-Options` does not support the `allow-from` directive. - Monorail 

  18. X-Frame-Options、ブラウザ対応完了 | マイナビニュース 

  19. http://www.slideshare.net/masatokinugawa/xxn-ja/98 

  20. 2008/9/3 - Internet Explorer 8 のセキュリティ Part VI: Beta 2 の更新項目 

  21. http://b.hatena.ne.jp/entry/294900783/comment/yosuke_furukawa 

  22. CGI 等を利用する Web サーバの脆弱性 (CVE-2016-5385 等) に関する注意喚起 

  23. http://httpd.apache.org/docs/2.4/mod/core.html#LimitRequestFields 

  24. ChromeのみBad Requestで特定ページが開けない問題 - Qiita 

  25. Apacheに新たな脆弱性発見 | スラド セキュリティ 

  26. 「ELBからの通信で408が多発する」件で、結局どうすべきか調べたのでまとめた - 双六工場日誌 

bezeklik
サーバー管理、CMS構築のお仕事募集中。 CentOS / Apache / Nginx / PHP / MySQL / Docker / CMS (eZ Platform, eZ Publish, WordPress, Drupal) / Redmine
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした