.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コマンドを使って安全なパスワードファイルを作成すること。
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
の実行方式に依存せずどの環境でも確実に動作する。