1. wp-config.php を別ディレクトリへ移動
■ なぜ有効?
wp-config.php にはDB情報や認証キーが入っており、最重要ファイルです。 WordPressは ドキュメントルートの1階層上のディレクトリも自動的に探す仕様 があるため、Webから直接アクセスできない場所に置きます。
■ 例
/home/user/
├─ wp-config.php ← ここに移動(Webから直接アクセス不可)
└─ public_html/
└─ wordpress本体
■ wp-config.php内で修正が必要な箇所
wp-config.phpを移動した場合、パスの定義を修正する必要があります。
// wp-config.php の先頭付近に追加
/** 絶対パス設定 */
if ( !defined('ABSPATH') ) {
define('ABSPATH', dirname(__FILE__) . '/public_html/');
}
/** wp-content ディレクトリのパス(カスタマイズしている場合) */
// define('WP_CONTENT_DIR', dirname(__FILE__) . '/public_html/wp-content');
// define('WP_CONTENT_URL', 'https://example.com/wp-content');
/** プラグインディレクトリのパス(カスタマイズしている場合) */
// define('WP_PLUGIN_DIR', dirname(__FILE__) . '/public_html/wp-content/plugins');
// define('WP_PLUGIN_URL', 'https://example.com/wp-content/plugins');
重要なポイント:
ABSPATHは WordPress本体がインストールされているディレクトリを指す- 移動先の階層に応じて
dirname(__FILE__) . '/public_html/'の部分を調整 - 通常は
ABSPATHの定義だけで動作するが、wp-contentを別の場所に配置している場合は追加定義が必要
■ 確認方法
移動後、以下をチェック:
// デバッグ用(確認後は削除)
echo ABSPATH; // WordPressのルートパスが正しいか確認
■ 注意点
- 移動できるのは1階層上のみ(2階層以上上には置けない)
- シンボリックリンクを使う場合は別の考慮が必要
- サーバー設定によっては動作しない場合がある
- 移動後は必ず動作確認を行う(管理画面へのログイン、メディアアップロードなど)
■ 応用:wp-content も公開ディレクトリ外に配置(最高レベル)
さらにセキュリティを高める場合、wp-contentディレクトリも移動できます。
/home/user/
├─ wp-config.php
├─ wp-content/ ← テーマ・プラグインも外に出す
│ ├─ plugins/
│ ├─ themes/
│ └─ uploads/
└─ public_html/
└─ wordpress本体(wp-contentは空またはダミー)
wp-config.phpに追加:
// wp-content の場所を変更
define('WP_CONTENT_DIR', dirname(__FILE__) . '/wp-content');
define('WP_CONTENT_URL', 'https://example.com/wp-content');
// uploads ディレクトリだけは公開ディレクトリ内に戻す場合
// define('UPLOADS', 'public_html/wp-content/uploads');
注意: この設定は高度で、.htaccessやNginx設定での静的ファイル配信設定が別途必要になります。
■ 追加でやると強い
// wp-config.php の先頭付近
define('DISALLOW_FILE_EDIT', true); // テーマ・プラグインエディタを無効化
define('DISALLOW_FILE_MODS', true); // プラグイン・テーマのインストール/更新/削除を無効化
// デバッグモードは本番環境では必ずfalse
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
// データベーステーブルの接頭辞をデフォルトから変更(新規構築時のみ推奨)
// $table_prefix = 'wp_'; ← これを変更
// $table_prefix = 'xyz_'; のようにランダムな文字列に
重要: DISALLOW_FILE_MODS を有効にすると、管理画面からのプラグイン/テーマのインストール・更新・削除がすべて不可になります。FTPやSSHでの作業が必要になるため、運用体制を整えてから実装しましょう。
2. ファイル編集機能の完全無効化(管理画面対策)
管理画面からテーマ/プラグインを改ざんされるケースは多いです。
define('DISALLOW_FILE_EDIT', true);
これだけで 侵入後の被害拡大を大幅に抑制 できます。 実務では「初期設定に入れるレベル」の重要度です。
■ 効果
- テーマエディタが非表示になる
- プラグインエディタが非表示になる
- 管理者権限でもファイル編集不可
3. XML-RPCの機能単位ブロック
昔は「xmlrpc.php を丸ごと無効(全停止)」が主流でしたが、今は少し進化しています。
■ なぜ?
Jetpackや一部連携機能がXML-RPCを利用するため、全停止は業務上不便な場合があります。
■ 推奨:機能制限
WordPressフィルタで ブルートフォースに使われる機能だけ無効化
// functions.php または専用プラグイン
add_filter('xmlrpc_methods', function($methods){
// ブルートフォース攻撃で悪用されやすいメソッド
unset($methods['wp.getUsersBlogs']);
unset($methods['system.multicall']);
unset($methods['system.listMethods']);
return $methods;
});
■ 完全に使わない場合
// XML-RPC 完全無効化
add_filter('xmlrpc_enabled', '__return_false');
または .htaccess で
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
4. REST API の不要エンドポイント制限
REST API からユーザー情報を取得できるのは地味に危険です。
■ ユーザー列挙対策
// /wp-json/wp/v2/users を無効化
add_filter('rest_endpoints', function ($endpoints) {
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
}
if (isset($endpoints['/wp/v2/users/(?P<id>[\d]+)'])) {
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
}
return $endpoints;
});
■ より厳格な対策:ログインユーザーのみに制限
add_filter('rest_authentication_errors', function($result) {
if (!is_user_logged_in()) {
return new WP_Error(
'rest_not_logged_in',
'REST APIへのアクセスにはログインが必要です。',
array('status' => 401)
);
}
return $result;
});
これで ユーザーID総当たり攻撃の足がかりを遮断 できます。
5. プラグイン・テーマの存在秘匿
攻撃者はまず「どのプラグインが入っているか」を調べます。
■ 対策例
1. バージョン情報削除
// functions.php
remove_action('wp_head', 'wp_generator');
// CSS/JSのバージョン情報も削除
add_filter('style_loader_src', 'remove_version_from_assets', 9999);
add_filter('script_loader_src', 'remove_version_from_assets', 9999);
function remove_version_from_assets($src) {
if (strpos($src, 'ver=')) {
$src = remove_query_arg('ver', $src);
}
return $src;
}
2. ディレクトリリスティング無効化
.htaccess に追加
# ディレクトリ一覧表示を無効化
Options -Indexes
# wp-content へのアクセス制限
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-content/plugins/.*\.php$ - [F,L]
RewriteRule ^wp-content/themes/.*\.php$ - [F,L]
</IfModule>
3. 不要プラグインは削除(停止だけではダメ)
停止しているだけでは、ファイルが残っているため脆弱性スキャンの対象になります。
6. PHP実行制限(wp-content/uploads)
画像アップロード用ディレクトリでPHPが実行できると即終了です。
■ .htaccess(Apache)
wp-content/uploads/.htaccess を作成
# PHP実行を完全禁止
<FilesMatch "\.(php|php3|php4|php5|phtml|pl|py|jsp|asp|sh|cgi)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
</FilesMatch>
■ Nginx の場合
location ~* ^/wp-content/uploads/.*\.php$ {
deny all;
}
これは 実際の改ざん被害を止める超実戦的対策 です。
7. 認証キーの定期ローテーション
WordPressのセキュリティキーは「設定して終わり」ではなく、 漏洩前提でローテーションする思想が本来は正しい です。
■ 方法
- 公式APIで新しいキーを取得
wp-config.phpの以下の8つのキーを更新
define('AUTH_KEY', 'ここに新しいキー');
define('SECURE_AUTH_KEY', 'ここに新しいキー');
define('LOGGED_IN_KEY', 'ここに新しいキー');
define('NONCE_KEY', 'ここに新しいキー');
define('AUTH_SALT', 'ここに新しいキー');
define('SECURE_AUTH_SALT', 'ここに新しいキー');
define('LOGGED_IN_SALT', 'ここに新しいキー');
define('NONCE_SALT', 'ここに新しいキー');
- 全ユーザー強制ログアウト(セッション無効化)
■ 実運用での注意
- ローテーション後は全ユーザーが再ログイン必要
- メンテナンス時間帯に実施
- ユーザーへの事前告知を推奨
- 推奨頻度:3〜6ヶ月に1回、または漏洩の疑いがある場合は即座に
8. ログインURL変更よりも重要な「レート制限」
wp-login.php のURL変更はセキュリティ through obscurity(隠蔽による安全性) で気休めレベルです。 本質は 試行回数制限か2要素認証です。
3つの方法を紹介します。
■ 1. サーバー側で制御
fail2ban の設定例(推奨)
# /etc/fail2ban/filter.d/wordpress.conf
[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
^<HOST> .* "POST /xmlrpc.php
# /etc/fail2ban/jail.local
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/apache2/access.log
maxretry = 5
bantime = 3600
その他のオプション:
- WAF(Web Application Firewall)
- mod_security
- CloudflareのRate Limiting
■ 2. アプリ側
プラグインで対応:
- Limit Login Attempts Reloaded
- WP Limit Login Attempts
ボットの総当たりは”防ぐ”より”弾く”が正解 です。
■ 3. 2要素認証(2FA)の導入
ログインセキュリティを本気で強化するなら:
- Google Authenticator
- WP 2FA プラグイン
- Two Factor Authentication
9. 自動更新をあえて止める判断(上級者向け)
一般的には自動更新推奨ですが、 企業サイト・会員制サイト・カスタマイズが多いサイトでは「即時自動更新=リスク」になる場合があります
■ 自動更新を無効化
// すべての自動更新を停止
define('AUTOMATIC_UPDATER_DISABLED', true);
// または細かく制御
define('WP_AUTO_UPDATE_CORE', false); // コア更新を無効化
add_filter('auto_update_plugin', '__return_false'); // プラグイン
add_filter('auto_update_theme', '__return_false'); // テーマ
■ 推奨運用フロー
- ステージング環境で更新テスト
- 互換性・動作確認
- 問題なければ本番環境へ手動更新
- バックアップは必須
これが「壊れないセキュリティ運用」です。
■ ただし注意
- セキュリティパッチの適用が遅れるリスクがある
- 手動更新を忘れると脆弱性が放置される
- 専任の担当者がいる場合のみ推奨
小規模サイトや個人ブログでは自動更新を有効にしておく方が安全です。
まとめ:守る=設定+構造+運用
WordPressのセキュリティは「プラグインを入れれば終わり」ではありません。
3層の防御が必要
- 設定層:wp-config.php、定数定義
- 構造層:ファイル配置、権限設定、サーバー設定
- 運用層:定期更新、監視、バックアップ
今日から実装できる優先順位
【高】即実装推奨
- ファイル編集機能の無効化(DISALLOW_FILE_EDIT)
- uploads での PHP実行禁止
- REST API ユーザー列挙対策
【中】環境に応じて実装
- wp-config.php の移動
- XML-RPC の機能制限
- 認証キーのローテーション
【低】上級者・専任担当者がいる場合
- 自動更新の無効化(ステージング運用)
セキュリティは一度設定して終わりではなく、継続的な改善が必要です。
