.htaccessのHSTS推奨事項

Oct 18 2020

以下のハイパーリンクにある私の以前の投稿を参照してください

.htaccessHSTSを考慮してファイルを更新し、推奨される変更の多くを追加しました。以下のスニペットを参照してください。HSTSの実装は、HSTSを初めて使用する人にとっては軽視されるべきではないことを強調したいと思います。そうは言っても、私はについての知識を持っている人とは違う方法で何ができるかについてのアドバイスを探しています.htaccess

#IMPLEMENT HSTS
<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</IfModule>

#CUSTOM ERROR PAGES
ErrorDocument 400 /allerror.php
ErrorDocument 401 /allerror.php
ErrorDocument 403 /allerror.php
ErrorDocument 404 /allerror.php
ErrorDocument 405 /allerror.php
ErrorDocument 408 /allerror.php
ErrorDocument 500 /allerror.php
ErrorDocument 502 /allerror.php
ErrorDocument 504 /allerror.php

RewriteEngine On

#REDIRECT TO SECURE HTTPS CONNECTION
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

#FORCE WWW TO NON-WWW
RewriteCond %{HTTP_HOST} ^www.example.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]

#URL EXTENSION REMOVAL
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]

#HOTLINKING PROTECTION
RewriteCond %{HTTP_REFERER} !^https://(www\.)?example\.com(/.*)*$ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule \.(css|flv|gif|ico|jpe|jpeg|jpg|js|mp3|mp4|php|png|pdf|swf|txt)$ - [F]

#CONTENT SECURITY POLICY
<FilesMatch "\.(html|php)$">
    Header set Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data: 'unsafe-inline'; media-src 'self' data: 'unsafe-inline'; connect-src 'self';"
</FilesMatch>

#REDIRECT FOR DATE PAGE
RewriteRule ^date$ /storage/date-202010 [R=301,L]

#REDIRECT FOR HOME PAGE
RewriteRule ^home$ / [R=301,L]

#PREVENT DIRECTORY BROWSING
Options All -Indexes

#FILE CACHING
    #cache html and htm files for one day
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=43200"
</FilesMatch>
    #cache css, javascript and text files for one week
<FilesMatch "\.(js|css|txt)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
    #cache flash and images for one month
<FilesMatch "\.(flv|swf|ico|gif|jpg|jpeg|mp4|png)$">
Header set Cache-Control "max-age=2592000"
</FilesMatch>
    #disable cache for script files
<FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
Header unset Cache-Control
</FilesMatch>

#BLOCKS FILE TYPES FOR USERS
<FilesMatch "\.(ht[ap]|ini|log|sh|inc|bak)$">
Require all denied
</FilesMatch>

HSTSの実装

HSTSの調査中に私が学んだいくつかのことに注意してください。

  1. SSL証明書が必要です
  2. サイトがHTTP経由で利用できる場合は、301パーマネントリダイレクトを使用してすべてのリクエストをHTTPSにリダイレクトします。
  3. .htaccessファイルに以下を含めますStrict-Transport-Security: max-age=31536000; includeSubDomains; preload。最大年齢は少なくとも10886400秒または18週間である必要があります。2年間の価値のために行きます。
  4. 以下の最初のリンクを使用して、ドメインをプリロードリストに追加します。

詳細については、以下の各ソースを読むことをお勧めします。

回答

3 MrWhite Oct 27 2020 at 23:09

HTTP Strict Transport Security(HSTS)には2つの側面があります。

  1. サイトにHSTSを実装します。
  2. すでにHSTSが有効になっているサイトをHSTSプリロードリストに送信します。これは、「HSTSサイトのリスト」がブラウザーに直接コンパイルされる場所であり、HTTPを介した最初の要求(要求がMITM攻撃に対して潜在的に脆弱である場合)を回避します。

あなたは#2に向かってまっすぐ進んでいるようです。これは必ずしも推奨されるわけではありません。「プリロードリスト」は片道の旅と考えてください。技術的には、プリロードリストから削除することが可能です。現実的には、それはあなたが考えたくないことでもありません。(難しい-遅い-HSTSのみから十分に後退します。)

プリロードリスト送信ページ自体は、「プリロードリスト送信」に直接進むことを推奨していません。max-ageプリロードリストに送信する最後のステップを実行する前に、一定期間(数か月)にわたってパラメータを増やすことをお勧めします。その間にテストテストをテストして、SSL証明書が確実に更新され、混合コンテンツの警告などがないことを確認します。

また、SSL構成を完全に制御できない共有サーバーでのHSTSプリロードリストの送信(またはHSTS自体もある程度)についても注意が必要です。共有サーバー上にいるかどうかは実際にはわかりませんが、このすべての構成をで行っているので.htaccess、そうだと思います。独自のサーバーがあり、サーバー構成にアクセスできる場合は、これらのほとんどをサーバー/仮想ホスト構成で構成する必要があります(これは、間違いなく簡単で信頼性が高くなります)。

HSTSルートを通過すると(ユーザーがHTTPSサイトにアクセスするか、「プリロードリスト」にアクセスすると)、サイトにはHTTPS経由でのみアクセスできることに注意してください。これは、サイトだけでなく、使用している可能性のあるサードパーティのサービス(混合コンテンツブラウザの警告など)にも当てはまります。

#IMPLEMENT HSTS
<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</IfModule>

これにより、「ほとんどの」* 1応答に必要なHSTSHTTP応答ヘッダーがpreload設定されます(ただし、パラメーターに注意してください。最初はおそらく省略してください)。

* 1ただし、このディレクティブは必ずしもすべての応答に必要なヘッダーを設定するわけではありません。HSTSの要件は、「リダイレクト」応答のヘッダーも設定することです(たとえば、HTTPSではwwwから非wwwへ)。現在、上記はこれを行いません。200 OK以外の応答にヘッダーを設定するには、ディレクティブのalways 条件を使用する必要がありますHeader。例えば:

# Use "always" condition to set on "redirects" as well.
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"

preload今のところ、パラメーターも削除しました。)

<IfModule>ラッパーは必要ないため、削除する必要があります。mod_headersはデフォルトで有効になっている必要があります。これはあなたのサーバーです、あなたはmod_headersが有効になっているかどうかを知っています。これを機能させるに、mod_headersを有効にする必要あります。mod_headersが利用できない場合に、これがサイレントに失敗することは望ましくありません。ログにエラーが表示されて失敗したらすぐに通知する必要があります。

多くの記事では、セキュア(HTTPS)応答にのみStrict-Transport-Securityヘッダーを設定する必要があると述べています。また、ヘッダーをHTTP経由で送信した場合、「プリロードリストの送信」は実際に「警告」(厳密には「エラー」ではないと思います)を発行します。ただし、HTTPS応答でのみ設定する必要がありますが、準拠しているブラウザは、暗号化されていないHTTP接続を介して送信される場合(MITM攻撃を防ぐため)、このヘッダーを無視するため、ヘッダーがHTTPを介して「不必要に」送信されるかどうかは関係ありません。これは<VirtualHost>、メインサーバー構成の適切なコンテナーで管理する方が簡単です。のHTTPS応答でのみこのヘッダーを送信すること.htaccessは、より複雑です(したがって、エラーが発生しやすくなります)。HSTS応答ヘッダーを条件付きで設定するために使用できる追加の環境変数を使用する必要があります。

例えば:

# Set environment var "HSTS" if accessed over HTTPS connection
RewriteCond %{HTTPS} on
RewriteRule ^ - [E=HSTS:1]

# Conditionally set only on HTTPS connections (ie. when "HSTS" env var is set)
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" env=HSTS

それ以外の場合は、HSTSに関して残りのディレクティブは問題ないと思います。しかし、いつものように、テストテストテスト。


複数の(不要な)リダイレクトを解決する

#FORCE WWW TO NON-WWW
RewriteCond %{HTTP_HOST} ^www.example.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]

#URL EXTENSION REMOVAL
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R]

ここでの潜在的な問題(HTTPからHTTPSへのリダイレクト後の上記の2番目と3番目の正規リダイレクト)は、www+.htmlが要求された場合に2つの追加のリダイレクトが発生する可能性があることです。これは、2つのリダイレクトを逆にして、「URL EXTENSION REMOVAL」リダイレクトに正規のホスト名を含めることで解決できます(以前の質問に対する私の回答で述べたように)。

例えば:

#URL EXTENSION REMOVAL
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ https://example.com/%1 [R=301,L]

#FORCE WWW TO NON-WWW
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [R=301,L]

いくつかの潜在的な問題に対処する「URLEXTENSIONREMOVAL」リダイレクトへの代替アプローチについては、以前の回答を参照しください。

www他のホスト名(例www.subdomain.example.com)でサブドメインを使用していない場合は、wwwのCondPatternをwww以外のリダイレクトに単純化できます^www\.。ホスト名www.全体をチェックするのではなく、単に開始する要求されたホスト名。


追加の修正

URL拡張の削除/書き換えループ(500内部サーバーエラー)

以前の質問で対処できなかった他の問題がいくつかありますが、HSTSとは関係ありません。これについては、以下で説明します...

#URL EXTENSION REMOVAL
:
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]

これ(および同様のもの)は、拡張子のないURLを使用するときにファイル拡張子を追加(URL書き換え)する「標準」の方法として、どこでも(つまりどこでも)「盲目的に」コピー/貼り付けされるコードスニペットの1つです。ただし、有効なURLに対してはおそらく「機能」しますが、無効なURLを要求すると重大な欠陥が発生します...

/about.html拡張子のないURLをリクエストするときに提供したい有効なファイルであれば/about、問題なく動作します。ただし、(悪意を持って)要求した/about/場合、または/about/<anything>サーバーをらせん状の書き換えループに送信すると、500内部サーバーエラー応答が発生します。エンドユーザーは、そのような応答を呼び出すことができないようにする必要があります(DDOS攻撃やその他の敵対的な行動に対してより脆弱になる可能性があります)。

これは、REQUEST_FILENAME(マップされたファイルシステムパス)がREQUEST_URI(要求されたURLパス)変数と同じパブリックURLパスを必ずしも参照しないためです。

これを解決するには、REQUEST_URI全体を使用します。例えば:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule ^ %{REQUEST_URI}.html [L]

(ここNCRewriteRuleディレクティブではフラグは不要です。)

詳細について、次のServerFaultの質問に対する私の回答を参照しください。

ホットリンク保護-条件を簡素化

#HOTLINKING PROTECTION
RewriteCond %{HTTP_REFERER} !^https://(www\.)?example\.com(/.*)*$ [NC]

これは比較的マイナーです。上記の条件の正規表現は簡略化できます。.htaccessファイルのこの時点で、ホスト名はwwwサブドメインを削除するためにすでに正規化されているため(www\.)?、上記のサブパターンは不要です。末尾の(/.*)*$サブパターンも同様で、他のすべてと単純に一致します。ここでは実際に何かに一致する必要はありません。Refererヘッダーが適切な(scheme +)ホスト名で始まることを表明する必要があります。

例えば:

RewriteCond %{HTTP_REFERER} !^https://example\.com

NCフラグは、ここにも不必要です。大文字と小文字を区別しない一致を必要のないときに強制すると、サーバーの作業が(わずかに)増え、場合によっては脆弱性が発生する可能性があります(「重複コンテンツ」は一般的なものですが、ここでは問題ではありません)。 。

不要な有効化 Options

#PREVENT DIRECTORY BROWSING
Options All -Indexes

これは「ディレクトリの閲覧」を妨げるだけではありません。このAll引数により、サーバーサイドインクルード(Includes)やCGIスクリプトを実行する機能()など、おそらく必要のない他の多くのものが有効になりますExecCGI。(ちなみに、これは、引数をaと組み合わせて、+または引数なしで混在させることができる唯一の場合です-。)ディレクトリブラウジング(つまり、mod_autoindexによるディレクトリインデックスの自動生成)のみを防ぐには、All引数を削除します。

ただし、おそらく必要なのは FollowSymLinks(サーバー構成ですでに設定されている可能性がある)だけので、代わりに次のように設定できます。

Options FollowSymLinks

が存在しないことに注意してください+-。これ設定するだけなFollowSymLinksので、Indexesすでに設定されている場合は無効にします(「ディレクトリブラウジング」)。