プライム・ストラテジー「KUSANAGI」開発チームの石川です。
Apache HTTP Serverでは .htaccess というファイルを作成することでアクセス権を細かく設定することができます。
現在のApache HTTP Server 2.4が最初にリリースされたのは2012年2月と13年近くが経過していますが、その .htaccess ファイルのアクセス権に関するディレクティブがApache HTTP Server 2.4 から変わっていたことはご存知でしょうか。
Apache HTTP Server 2.2 が EOL になったのが 2017年6月と既に7年以上が前にも関わらず、未だに 2.2 の書き方が多く見られます。
ここでは、過去のApache HTTP Server (2.2まで)のディレクティブの書き方と、現在のApache HTTP Server (2.4以降)のディレクティブの書き方の違いについて解説します。
過去のApache HTTP Server (2.2まで)の書き方
これまでのApache HTTP Serverでは、Order, Allow, Deny
というディレクティブを使ってアクセス権を制御していました。
例えば、全てからアクセスを拒否する設定は以下のようになります。
Order deny,allow
Deny from all
逆に、全てからのアクセスを許可する設定は以下のようになります。
Order allow,deny
Allow from all
特定のIPアドレスからのアクセスを許可する設定は、以下のようにしていました。
Order deny,allow
Deny from all
Allow from IPアドレス
また、Basic認証では以下のように上記までの Allow from
Deny from
とは全く異なる設定をしていました。
AuthType Basic
AuthName "ENTER YOUR NAME & PASSWORD TO LOGIN"
AuthUserFile /home/kusanagi/.htpasswd
Require valid-user
Satisfy any
なお、この最後の Satisfy any
に重要な意味がありますので、後ほど解説します。
例えば、ローカルホスト (127.0.0.1) のアクセスは許可して、他のアクセスはBasic認証を必須とする場合は以下のようになります。
Order deny,allow
Deny from all
Allow from 127.0.0.1
AuthType Basic
AuthName "ENTER YOUR NAME & PASSWORD TO LOGIN"
AuthUserFile /home/kusanagi/.htpasswd
Require valid-user
Satisfy any
このディレクティブ (以降、「2.2互換のディレクティブ」とします) は現在のApache HTTP Server (2.4以降)でも引き続き使用することができます。
しかし、あくまでも互換として残されているものなので、将来的に使えなくなる可能性はあります。
また、Basic認証によるアクセス権の設定との組み合わせをより直感的にするため、新しいディレクティブ (以降、「2.4のディレクティブ」とします) が推奨されています。
2.2互換のディレクティブは何が問題だったか
2.2互換ディレクティブでの問題は、Apache HTTP Server 2.2より前から存在するIPアドレスベースのアクセス制御である Allow from
や Deny from
と、Basic認証のアクセス制御がそれぞれ別々に判定されていたことです。
そのため、IPアドレスによるアクセス制限とBasic認証の両方を有効にしようとすると問題が起きます。
一般的に、ウェブサイトでは以下のようにアクセス制限を運用します。
- BotやDoS攻撃のように明かに拒否したいアドレスをIPアドレスベースで制限
- 一般ユーザーは許可
- 管理者など制限されたページにアクセスできるユーザーをBasic認証で制限
Allow from
や Deny from
を設定すると、まずIPアドレスベースのアクセス制御が行われます。
許可されていないIPアドレスからのアクセスは、Basic認証を行うことなく拒否されます。
しかし、次にBasic認証のアクセス制御により、全てのユーザーにBasic認証が求められます。
そして、ページにアクセスするには場合はBasic認証を通る必要があります。
この問題は、localhost (127.0.0.1) など明かにBasic認証がなくてもアクセスを許可したい場合でも、Basic認証が必要となっていたことです。
これを解決するために設定に加えたのが Satisfy any
です。
IPアドレスによるアクセス制限とBasic認証の、いずれかを満たす (satisfy any) ことができればよい、という意味になります。
この Satisfy any
で問題は解決したように見えますが、実はそうではありません。
Deny from
で拒否しているはずのIPアドレスからのアクセスであっても、Basic認証の要求が行われます。
そしてBasic認証を突破することができれば、制限されているはずのページにアクセスできてしまいます。
これはIPアドレスによるアクセス制限が満たされなかったら、Basic認証で満たせればいいからです。
こうなると、BotなどにBasic認証へのbrute force攻撃を許すことになってしまいます。
ちなみに、同じ問題は Nginx でも発生することを過去に紹介しています。
現在のApache HTTP Server (2.4以降)の書き方
2.4のディレクティブでは、これまでの Allow from
や Deny from
を互換機能として分離して、 Require
ディレクティブを使うように変わりました。
例えば、全てからアクセスを拒否する設定は以下のようになります。
Require all denied
逆に、全てからのアクセスを許可する設定は以下のようになります。
Require all granted
2.2互換ディレクティブにあった Order
が廃止されて、直感的に denied
granted
で全て拒否・許可が書けるようになっています。
特定のIPアドレスからのアクセスを許可する設定は、以下のようになります。
Require ip IPアドレス
特定のホスト名からのアクセスを許可する設定は、以下のようになります。
Require host ホスト名やドメイン名
逆に拒否する場合は not
を付けます。
Require not ip IPアドレス
Require not host ホスト名やドメイン名
また、Basic認証では2.2互換のディレクティブとほぼ同じになりますが、 Satisfy any
が不要となります。
AuthType Basic
AuthName "ENTER YOUR NAME & PASSWORD TO LOGIN"
AuthUserFile /home/kusanagi/.htpasswd
Require valid-user
2.2互換のディレクティブの例と同じように、ローカルホスト (127.0.0.1) のアクセスは許可して、他のアクセスはBasic認証を必須とする場合は以下のようになります。
Require ip 127.0.0.1
AuthType Basic
AuthName "ENTER YOUR NAME & PASSWORD TO LOGIN"
AuthUserFile /home/kusanagi/.htpasswd
Require valid-user
2.2互換のディレクティブの問題の解決
2.2互換のディレクティブにあった Satisfy any
の問題を2.4のディレクティブでは解決しています。
2.4では <RequireAll>
<RequireAny>
が追加されています。デフォルトでは <RequireAny>
が適用されますので、先程の例は厳密には以下と等価です。
<RequireAny>
Require ip 127.0.0.1
AuthType Basic
AuthName "ENTER YOUR NAME & PASSWORD TO LOGIN"
AuthUserFile /home/kusanagi/.htpasswd
Require valid-user
</RequireAny>
例えばあるIPアドレスからアクセスを拒否した上で、Basic認証を設定する場合は以下のようになります。
<RequireAll>
Require not ip アクセス拒否するIPアドレス
AuthType Basic
AuthName "ENTER YOUR NAME & PASSWORD TO LOGIN"
AuthUserFile /home/kusanagi/.htpasswd
Require valid-user
</RequireAll>
まとめ
Apache HTTP Serverは歴史が長く、特に2.2互換のディレクティブについては1.xの頃からある記述方法です。
歴史が長いということはHow-Toやドキュメントも豊富ということであり、未だに使っている人も多いのは事実です。
互換性を維持した記述が使えることはよいことですが、逆に新しい機能を使うことができない、ということでもあります。
これを機会に2.4のディレクティブを使い始めてみるのはいかがでしょうか?
なお、ドキュメントについては残念ながら英語版しか存在しません。
日本語訳も存在はするのですが、英語版の最新に追従していないどころか古い記述が残っているため、むしろ誤った内容が記載されたまま、となっているので参照しない方がよいです。
我こそは、という方はぜひ日本語訳のアップデートに手を挙げてみるのもいかがでしょうか。
- 2.4のディレクテイブ: https://httpd.apache.org/docs/2.4/en/howto/auth.html
- 2.2互換のディレクティブ: https://httpd.apache.org/docs/2.2/en/howto/auth.html
- Upgrading to 2.4 from 2.2: https://httpd.apache.org/docs/2.4/upgrading.html