プライム・ストラテジー「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以降)のディレクティブの書き方の違いについて解説します。
2.2互換の記述から2.4の Require 系へ書き換えるときは、実際の挙動(期待通りに403/認証がかかるか)を検証環境で確認しておくと安全です。KUSANAGIクイックスタートでは、初期設定時に Apache httpd 2.4(--httpd24) を選択でき、必要に応じて PHP 8.5(--php85) も選べます。
▼KUSANAGIクイックスタート
https://kusanagi.tokyo/document/kusanagi-quickstart
▼WordPressに関連する脆弱性情報を毎週日本語で公開する「Security Advisory for WordPress」を配信中!
https://kusanagi.biz/wordpress-security-advisory/

学生時代は自ドメインを取得して自宅でサーバを運用していました。前職ではミドルウェアの企画・開発・拡販に一貫して従事し、現在はKUSANAGI・WEXAL・Davidの開発をしています。
過去の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攻撃を許すことになってしまいます。
アクセス制御はディレクティブの書き換えだけでなく、Webサーバ構成によって実現方法や運用の置き方が変わります。KUSANAGIでは nginx / httpd の選択に加えて、nginxリバースプロキシ + httpd の構成も選べるため、.htaccess を前提にした検証や構成比較ができます。
▼KUSANAGIのWebサーバ構成(nginx / httpd / nginxリバースプロキシ + httpd)
https://kusanagi.tokyo/document/kusanagi-web-servers/
ちなみに、同じ問題は Nginx でも発生することを過去に紹介しています。
現在のApache HTTP Server (2.4以降)の書き方
2.2互換の記述から Require へ置き換えたあとは、意図した認可条件になっているか(許可/拒否/Basic認証の組み合わせ)を検証環境で確認してから本番に反映するのが安全です。
KUSANAGIでは kusanagi httpd --use httpd24 で Apache httpd 2.4 を起動できるため、.htaccess の挙動確認にも使えます。
▼kusanagi httpd コマンド(httpd24を起動)
https://kusanagi.tokyo/document/commands/httpd/
2.4のディレクティブでは、これまでの Allow from や Deny from を互換機能として分離して、 Require ディレクティブを使うように変わりました。
例えば、全てからアクセスを拒否する設定は以下のようになります。
Require all denied逆に、全てからのアクセスを許可する設定は以下のようになります。
Require all granted2.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-user2.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-user2.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のディレクティブを使い始めてみるのはいかがでしょうか?
Apache HTTP Server2.2互換の記述から2.4の Require 系へ置き換えると、意図せず許可/拒否の条件が変わることがあるため、適用前に検証環境で挙動を確認しておくのが安全です。
KUSANAGIクイックスタートでは初期設定時に--httpd24(Apache httpd 2.4)を選択でき、必要に応じて --php85(PHP 8.5)も指定できます。既に環境がある場合は kusanagi httpd --use httpd24 で httpd 2.4 に切り替えて確認できます。
▼KUSANAGIクイックスタート(初期設定で –httpd24 / –php85 を指定)
https://kusanagi.tokyo/document/kusanagi-quickstart/
▼kusanagi httpd コマンド(httpd24へ切り替え)
https://kusanagi.tokyo/document/commands/httpd/
なお、ドキュメントについては残念ながら英語版しか存在しません。
日本語訳も存在はするのですが、英語版の最新に追従していないどころか古い記述が残っているため、むしろ誤った内容が記載されたまま、となっているので参照しない方がよいです。
我こそは、という方はぜひ日本語訳のアップデートに手を挙げてみるのもいかがでしょうか。
- 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





