.htaccess の設置場所(3箇所の全体像)
public_html/
├── .htaccess ← ルートの設定(リライト・ヘッダー・キャッシュ等)
├── wp-admin/
│ └── .htaccess ← 管理画面専用の設定
└── wp-content/
└── uploads/
└── .htaccess ← アップロードディレクトリ専用
なぜ <Directory> ではなく別ファイルを使うのか
<Directory>
ディレクティブは Apache のメイン設定ファイル(
httpd.conf
)専用で、
.htaccess
内では使用できない。ディレクトリ単位で制御したい場合は、そのディレクトリに別の
.htaccess
を設置する。
wp-admin/.htaccess — 管理画面への Basic 認証
# wp-admin/.htaccess
# admin-ajax.php は除外(フロントエンドの Ajax に必要)
<Files admin-ajax.php>
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
Satisfy Any
Order allow,deny
Allow from all
Deny from none
</IfModule>
</Files>
# upgrade.php はサーバー内部からのみ許可(WordPress 自動更新のため)
<Files upgrade.php>
<IfModule mod_authz_core.c>
<RequireAny>
Require ip 127.0.0.1 ::1
Require valid-user
</RequireAny>
</IfModule>
</Files>
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /home/username/.htpasswd
Require valid-user
Basic 認証の役割
WordPress のログイン画面(
/wp-admin/
)に追加の認証壁を設ける。WordPress 本体のログイン処理が実行される前にサーバーレベルで認証を要求するため、ブルートフォース攻撃(パスワードの総当たり)に対して有効な対策となる。
admin-ajax.php を除外する理由
admin-ajax.php
はフロントエンドの Ajax 処理(フォーム送信・ポップアップ表示・カートへの追加など)に使われる。管理画面の Basic 認証を適用したままにすると、ログインしていない一般ユーザーの Ajax 処理が失敗するため、このファイルだけ認証を除外する。
upgrade.php のサーバー内部 IP 除外の理由
WordPress の自動更新は内部でサーバー自身(127.0.0.1/::1)がupgrade.phpにアクセスする。Basic 認証がかかっていると自動更新が失敗するため、ループバック IP アドレスからのアクセスだけ Basic 認証なしで許可する。なお、上記の設定例は Apache 2.4 以降(mod_authz_core)を前提としており、Apache 2.2 を利用している場合は同等の許可設定を別途追加する必要がある。
Basic 認証の設定項目
| ディレクティブ | 意味 |
|---|---|
AuthType Basic |
認証方式を Basic 認証に指定 |
AuthName |
認証ダイアログに表示されるメッセージ |
AuthUserFile |
パスワードファイル(
.htpasswd
)のフルパス
|
Require valid-user |
認証に成功したユーザーのみアクセスを許可 |
.htpasswd ファイルの作成
パスワードファイルはhtpasswdコマンドで生成する。このファイルは Web から直接アクセスできない場所(ドキュメントルートの外)に設置する。
# 新規作成(-c オプション)
htpasswd -c /home/username/.htpasswd ユーザー名
# 既存ファイルにユーザーを追加
htpasswd /home/username/.htpasswd ユーザー名
パスワードの自動生成や
.htpasswdのハッシュ生成は .htaccess Generator では行わない。bcrypt ハッシュの生成には外部ライブラリが必要で、SHA1 はセキュリティ上不十分なため。htpasswdコマンドを使って安全なパスワードファイルを作成すること。
注意: .htaccess Generator で生成されるコードには
AuthUserFile "/path/to/your/.htpasswd"というダミーパスが入ります。サーバー上の実際の.htpasswdのフルパス(例:/home/username/.htpasswd)に必ず書き換えてください。また、upgrade.phpの IP 除外を有効化している場合はRequire ip 192.0.2.1の IP もサーバーの実際の内部 IP(例:127.0.0.1)に書き換える必要があります。これらは環境依存のためツール側では自動判定できません。
ルート .htaccess — wp-includes / wp-admin/includes の保護
WordPress のコアファイルへの直接アクセスをブロックするルール。ルートの
.htaccess
内、
mod_rewrite
ブロック内に記述する。
# wp-admin/includes/ への直接アクセスをブロック
RewriteCond %{REQUEST_URI} ^/wp-admin/includes(?:/|$) [NC]
RewriteRule .* - [F,L]
# wp-includes/*.php への直接アクセスをブロック
RewriteCond %{REQUEST_URI} ^/wp-includes/[^/]+\.php$ [NC]
RewriteRule .* - [F,L]
wp-admin/includes/ を全ブロックする理由
wp-admin/includes/
は管理画面の内部処理ファイルが格納されるディレクトリで、ブラウザから直接アクセスする必要がない。すべてのリクエストをブロックする。
wp-includes/*.php のみブロックする理由
wp-includes/
には CSS・JS・画像などフロントエンドで必要なアセットも含まれるため、ディレクトリ全体をブロックするとサイトが壊れる。PHP ファイルのみをブロックし、アセットへのアクセスは許可する。
パターン
[^/]+\.php$
はディレクトリ直下の PHP ファイルのみにマッチする。これにより
wp-includes/js/tinymce/wp-tinymce.php
などサブディレクトリ内の正当な PHP ファイルへのアクセスを妨げない。
ディレクトリ一覧( -d 判定)との違い
ディレクトリ一覧の表示は
Options -Indexes
で既にカバーされる。このルールは PHP ファイルへの直接アクセスという、より実害の大きい攻撃パターンを防ぐ。
wp-content/uploads/.htaccess — PHP 実行防止
# wp-content/uploads/.htaccess
<FilesMatch "\.(?:php|phar|phtml)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
</FilesMatch>
役割
アップロードディレクトリ(
/wp-content/uploads/
)への PHP ファイルのアップロードと実行を防ぐ設定。
WordPress の脆弱なプラグインやテーマを悪用して
.php
ファイルをアップロードし、それをブラウザから実行してサーバーを乗っ取る攻撃(リモートコード実行)がある。このファイルはその攻撃への防衛線として機能する。
<FilesMatch> の役割
<Files>
の正規表現版。単一のファイル名にマッチする
<Files>
と異なり、正規表現パターンで複数の拡張子をまとめてマッチできる。
| ブロック対象 | 理由 |
|---|---|
.php |
PHP スクリプト本体 |
.phar |
PHP Archive。PHP コードを含む実行可能なアーカイブ |
.phtml |
PHP のレガシーな拡張子。Apache の設定によっては PHP として実行される |
正常な WordPress 運用では
uploads/に.pharや.phtmlが入ることはない。攻撃者は.php以外の拡張子でアップロード制限を回避しようとするため、まとめてブロックする。
Apache 2.2 / 2.4 互換パターンを使う理由
ルートの
.htaccess
は管理者が意図的に設置するが、
uploads/
の
.htaccess
はプラグイン(WP Super Cache・EWWWIO 等)が自動生成するケースもある。幅広い Apache バージョンへの互換性を確保することで、どの環境でも確実に機能させる。
<IfModule mod_authz_core.c>
# Apache 2.4+ の書き方
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2 以前の書き方(フォールバック)
Order deny,allow
Deny from all
</IfModule>
なぜ php_flag engine off を使わないのか
php_flag engine off
は
mod_php
(Apache モジュールとして動く PHP)環境でのみ有効なディレクティブ。XServer・ConoHa WING 等の主要レンタルサーバーが採用する PHP-FPM(FastCGI)環境では
php_flag
が使えないため効果がない。
FilesMatch
+
Require all denied
は Apache のアクセス制御レイヤーで処理するため、PHP の実行方式に依存せずどの環境でも確実に動作する。