2026年10月1日

2026年10月1日

OWASP Top 10:2025で見直すWordPressのセキュリティ対策|運用と開発のチェックリスト

OWASP(Open Worldwide Application Security Project)は、Web アプリケーションのセキュリティを扱う非営利の団体です。代表的な成果物の OWASP Top 10 は、Web アプリケーションで多く見られる重大なリスクを10の分類にまとめたもので、2026年10月時点の最新版は OWASP Top 10:2025 です。

OWASP Top 10 は WordPress 専用の基準ではありませんが、分類ごとに「WordPress では何を確認するか」を当てはめると、対策の抜けを見つけやすくなります。この記事では、サイトを運用する人が確認する設定と、テーマやプラグインを書く人が守る書き方を、分類ごとに整理します。

OWASP Top 10:2025 の一覧と WordPress での主な対策

分類 内容 WordPress での主な対策
A01 アクセス制御の不備 権限のない人が操作・閲覧できてしまう 権限グループの見直し、current_user_can()・nonce・permission_callback
A02 セキュリティ設定のミス 既定のまま・不要な機能が有効 DISALLOW_FILE_EDIT、デバッグ表示の停止、ファイルの権限
A03 ソフトウェアサプライチェーンの不備 依存するソフトの脆弱性・改ざん プラグイン・テーマの選定と更新、使わないものの削除
A04 暗号化の失敗 通信や秘密情報が保護されていない HTTPS、FORCE_SSL_ADMIN、認証用キーの管理
A05 インジェクション SQL インジェクション・XSS など $wpdb->prepare()、エスケープ関数、入力の無害化
A06 安全でない設計 設計段階で安全が考慮されていない 最小権限、公開範囲の設計
A07 認証の失敗 推測しやすいパスワード、総当たり攻撃 強いパスワード、2段階認証、ログイン試行の制限
A08 ソフトウェアやデータの整合性の不備 改ざんされたファイルやデータを信用してしまう チェックサムの確認、入手元の限定
A09 ログと警告の不備 攻撃や異常に気付けない 操作ログ、サーバーログ、更新・エラーの通知
A10 例外的な状況の不適切な扱い エラー時に情報が漏れる・安全でない状態になる エラー表示の停止、is_wp_error() の確認

分類名の日本語は、英語の分類名(A01:2025 - Broken Access Control など)をもとにこの記事で訳したもので、OWASP の日本語版の表記とは異なる場合があります。

作業前の準備: バックアップ

設定を変える前に、ファイルとデータベースのバックアップを取ります。WP-CLI が使える場合は次のとおりです。

mkdir -p ~/backup
cd /var/www/html/wordpress
wp db export ~/backup/db_$(date +%Y%m%d).sql
tar czf ~/backup/files_$(date +%Y%m%d).tar.gz -C /var/www/html wordpress

バックアップは Web から見える場所(公開ディレクトリーの中)に置かないでください。定期的な取得と保存先の考え方は WordPressのバックアップの基本 を参考にしてください。

A01 アクセス制御の不備

運用での確認

  • 「ユーザー」→「ユーザー一覧」で、退職者や使っていないアカウント、必要以上に「管理者」になっているアカウントがないか確認します。
  • 記事を書くだけの人は「投稿者」や「編集者」など、必要な権限グループにします。
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

開発での確認

  • 管理画面の処理や保存処理では、current_user_can() で権限を確かめ、nonce(wp_nonce_field() と check_admin_referer()、Ajax なら check_ajax_referer())で本人の操作か確かめます。
  • REST API のルートには permission_callback を書きます。WordPress 5.5 以降、省略すると開発者向けの注意が出ます。誰でも使ってよいルートだけ __return_true にします。
<?php
add_action( 'rest_api_init', function () {
	register_rest_route(
		'myplugin/v1',
		'/settings',
		array(
			'methods'             => 'POST',
			'callback'            => 'myplugin_save_settings',
			'permission_callback' => function () {
				return current_user_can( 'manage_options' );
			},
		)
	);
} );

A02 セキュリティ設定のミス

公式ドキュメントの「WordPress の安全対策(Hardening WordPress)」に沿って、次を確認します。

// wp-config.php(「編集が必要なのはここまでです」の行より上)
define( 'DISALLOW_FILE_EDIT', true );   // 管理画面のテーマ・プラグインのファイル編集を無効にする
define( 'WP_DEBUG', false );            // 本番ではデバッグを無効にする
  • DISALLOW_FILE_EDIT は、管理画面のファイル編集機能を止めます。公式ドキュメントでは、悪意のあるファイルのアップロードまでは防げないが、一部の攻撃は止められると説明されています。
  • ファイルの権限は、公式ドキュメントではディレクトリーが 755、ファイルが 644、wp-config.php は 400 か 440(自分と Web サーバーだけが読める)とされています。詳しくは WordPressのファイルのパーミッション設定 を参考にしてください。
  • Web サーバーのディレクトリー一覧表示を止めます(Apache なら Options -Indexes)。
  • 使っていない機能を閉じます。XML-RPC を使っていなければ XML-RPCの無効化 を検討します。
  • セキュリティ関連の HTTP ヘッダーは セキュリティヘッダーの設定 を参考にしてください。

A03 ソフトウェアサプライチェーンの不備

WordPress サイトの脆弱性の多くは、本体よりもプラグインやテーマから見つかります。

# 更新があるものを一覧する
wp core check-update
wp plugin list --update=available
wp theme list --update=available

# 無効のまま置いてあるプラグイン・テーマを一覧する
wp plugin list --status=inactive
wp theme list --status=inactive
  • 使っていないプラグイン・テーマは、無効化するだけでなく削除します(wp plugin delete プラグインのスラッグ)。無効でもファイルが残っていれば、脆弱性のあるファイルに直接アクセスされることがあります。
  • 長期間更新されていないプラグインや、wordpress.org で配布が止められたプラグインは、代わりを探します。
  • 更新はテスト環境で確かめてから本番に入れるのが理想です。小さなサイトでは、管理画面の「プラグイン」の一覧で自動更新を有効にする方法もあります。
  • 入っているプラグインの既知の脆弱性は、WPScan・Wordfence Intelligence・Patchstack などの脆弱性データベースで調べられます。

A04 暗号化の失敗

  • サイト全体を HTTPS にします。手順は WordPressでSSLを有効にする方法 を参考にしてください。
  • wp-config.php に define( 'FORCE_SSL_ADMIN', true ); を書くと、ログインと管理画面が HTTPS に限られます。
  • wp-config.php の認証用キーとソルト(AUTH_KEY など)は、漏えいの疑いがあるときに作り直します。作り直すと、ログイン中のユーザーは全員ログアウトします。
wp config shuffle-salts

WordPress 6.8 からは、ユーザーのパスワードの保存に bcrypt が使われています。古い独自のログイン処理やプラグインでパスワードを扱っている場合は、本体の wp_hash_password()・wp_check_password() を使っているか確認します。

A05 インジェクション

テーマやプラグインを書く人が守る基本は、「入力は無害化し、SQL はプレースホルダーで組み、出力はエスケープする」の3点です。

<?php
global $wpdb;

// 入力の無害化
$keyword = isset( $_GET['keyword'] ) ? sanitize_text_field( wp_unslash( $_GET['keyword'] ) ) : '';

// SQL はプレースホルダーで組み立てる
$rows = $wpdb->get_results(
	$wpdb->prepare(
		"SELECT ID, post_title FROM {$wpdb->posts} WHERE post_status = %s AND post_title LIKE %s",
		'publish',
		'%' . $wpdb->esc_like( $keyword ) . '%'
	)
);

// 出力はエスケープする
foreach ( $rows as $row ) {
	printf(
		'<a href="%s">%s</a><br>',
		esc_url( get_permalink( $row->ID ) ),
		esc_html( $row->post_title )
	);
}
出力先 使う関数
HTML の本文 esc_html()
HTML の属性 esc_attr()
URL esc_url()
一部の HTML を許可する本文 wp_kses_post()

A06 安全でない設計

  • 外部に公開する機能(フォーム、REST API、Ajax)を増やすときは、「誰が」「何を」できるべきかを先に決め、最小限の権限で動くようにします。
  • 会員サイトや決済など重要な機能は、プラグインを組み合わせる前に、権限とデータの流れを図にして確認します。
  • 公開する必要のない REST API は REST APIへのアクセスを制限する方法 を参考に絞ります。

A07 認証の失敗

  • admin や webmaster のような推測しやすいユーザー名を避けます(公式ドキュメントの推奨)。
  • 強いパスワードと2段階認証を使います。設定は WordPressの2段階認証の設定 を参考にしてください。
  • 総当たり攻撃には、ログイン試行回数の制限が有効です(プラグインなしでログイン試行を制限する方法)。
  • 使わなくなったアプリケーションパスワードは、「ユーザー」→「プロフィール」から取り消します。

A08 ソフトウェアやデータの整合性の不備

本体や wordpress.org のプラグインのファイルが改ざんされていないかは、WP-CLI で公式のチェックサムと比べて確かめられます。

wp core verify-checksums
wp plugin verify-checksums --all
  • 違いが出たファイルは、改ざんか手作業での変更かを確かめます。wordpress.org 以外から入れたプラグインは比較できないので、警告として表示されます。
  • プラグインやテーマは、wordpress.org か開発元の公式サイトから入手します。配布元のわからない「無料版」の有料テーマは使いません。
  • 開発では、外部から受け取ったデータを unserialize() しないようにし、JSON(json_decode())を使います。

A09 ログと警告の不備

  • 管理画面での操作(ログイン、設定変更、プラグインの有効化など)を記録するプラグイン(例: WP Activity Log、Simple History)を入れると、何が起きたかを後から追えます。
  • Web サーバーのアクセスログ・エラーログを保存し、wp-login.php や xmlrpc.php への大量のアクセスがないかを見ます。
  • 障害調査で PHP のエラーを記録する場合は、画面に出さずにファイルへ書き出します。ログファイルは公開ディレクトリーの外に置きます。
// wp-config.php(調査のあいだだけ)
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_DEBUG_LOG', '/var/log/wordpress/debug.log' );

A10 例外的な状況の不適切な扱い

  • 本番では PHP のエラーを画面に表示しません(WP_DEBUG_DISPLAY を false、PHP の display_errors を Off)。エラーメッセージにはファイルのパスなどの内部情報が含まれます。
  • WordPress 5.2 以降は、プラグインやテーマで致命的なエラーが起きると、サイトの管理者メールアドレスに「リカバリーモード」の案内が届きます。管理者メールアドレスが実際に受信できるものか、「設定」→「一般」で確認しておきます。
  • 開発では、外部との通信や処理が失敗した場合の扱いも書いておきます。たとえば wp_remote_get() の戻り値は is_wp_error() で確かめ、失敗したときに権限の確認を飛ばしたり、未完成のデータを保存したりしないようにします。

ネットワークと WAF

OWASP Top 10 の分類とは別に、サーバーの手前で攻撃を減らす方法もあります。

  • サーバーのファイアウォールでは、使うポート(例: SSH・HTTP 80・HTTPS 443)だけを開け、FTP など使わないサービスは止めます。HTTP の 80 番を閉じると、HTTPS への転送や証明書の自動更新(HTTP-01 認証)が動かなくなることがあるので注意します。
  • WAF(Web アプリケーションファイアウォール)を使うと、既知の攻撃パターンをサイトに届く前に止められます。導入は WAFの導入方法 や Cloudflare WAFの設定 を参考にしてください。誤って正しいアクセスを止めていないか、導入後はログを定期的に確認します。

まとめ

  • OWASP Top 10:2025 は Web アプリケーション全般のリスク分類で、WordPress でも分類ごとに確認する点を当てはめられます。
  • 運用では、ユーザーと権限の見直し、プラグイン・テーマの更新と削除、HTTPS、2段階認証、DISALLOW_FILE_EDIT、ログの保存を優先します。
  • 開発では、current_user_can() と nonce、permission_callback、$wpdb->prepare()、エスケープ関数、is_wp_error() の確認を守ります。
  • wp core verify-checksums や wp plugin list --update=available で、定期的に点検します。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲