2026年5月27日

2026年5月27日

WordPressのファイルパーミッションを正しく設定する方法

はじめに

「WordPressのファイルパーミッションが777になっていてセキュリティが心配」「wp-config.phpが世界から読めてしまっている」「マルウェアに感染してPHPファイルが書き換えられた」——適切なファイルパーミッション設定でWordPressへの不正アクセスリスクを大幅に低減できます。

症状・原因

間違ったパーミッション(特に777)はPHPファイルを誰でも書き換えられる状態にします。WordPressには最低限の書き込み権限だけを与え、特に設定ファイルは厳しく保護する必要があります。

解決手順

ステップ1:推奨パーミッション値を理解する

# WordPress 推奨パーミッション
# ディレクトリ: 755 (rwxr-xr-x)
# ファイル:     644 (rw-r--r--)
# wp-config.php: 600 または 640
# .htaccess:    644

# 現在のパーミッションを確認
ls -la /var/www/html/
ls -la /var/www/html/wp-config.php
stat -c "%a %n" /var/www/html/wp-config.php

# オーナーを確認(Webサーバーユーザーと一致しているか)
ls -la /var/www/html/ | head -5
# www-data:www-data が一般的(Apache/Nginx)

ステップ2:パーミッションを一括修正するスクリプト

#!/bin/bash
# fix-wordpress-permissions.sh
# 実行前にバックアップを取ること

WP_ROOT="/var/www/html"          # WordPress インストールディレクトリ
WP_OWNER="www-data"              # Webサーバーユーザー
WP_GROUP="www-data"              # Webサーバーグループ

echo "WordPress パーミッション修正開始: $WP_ROOT"

# オーナーを設定
chown -R "${WP_OWNER}:${WP_GROUP}" "${WP_ROOT}"

# ディレクトリを 755 に設定
find "${WP_ROOT}" -type d -exec chmod 755 {} \;
echo "ディレクトリ: 755 設定完了"

# ファイルを 644 に設定
find "${WP_ROOT}" -type f -exec chmod 644 {} \;
echo "ファイル: 644 設定完了"

# wp-config.php を 600 に設定(オーナーのみ読み書き)
if [ -f "${WP_ROOT}/wp-config.php" ]; then
    chmod 600 "${WP_ROOT}/wp-config.php"
    echo "wp-config.php: 600 設定完了"
fi

# .htaccess を 644 に設定
if [ -f "${WP_ROOT}/.htaccess" ]; then
    chmod 644 "${WP_ROOT}/.htaccess"
    echo ".htaccess: 644 設定完了"
fi

# wp-content/uploads はWebサーバーが書き込めるよう 755
if [ -d "${WP_ROOT}/wp-content/uploads" ]; then
    find "${WP_ROOT}/wp-content/uploads" -type d -exec chmod 755 {} \;
    find "${WP_ROOT}/wp-content/uploads" -type f -exec chmod 644 {} \;
    echo "uploads: 755/644 設定完了"
fi

# wp-content/uploads 内の PHP ファイルを実行禁止
if [ -d "${WP_ROOT}/wp-content/uploads" ]; then
    find "${WP_ROOT}/wp-content/uploads" -name "*.php" -exec chmod 000 {} \;
    echo "uploads 内の PHP: 000 設定完了(実行禁止)"
fi

echo "パーミッション修正完了"

ステップ3:wp-config.phpとuploadsディレクトリを保護する

# .htaccess: wp-config.php への直接アクセスを拒否
<Files wp-config.php>
    Order Deny,Allow
    Deny from all
</Files>

# .htaccess 自体への直接アクセスを拒否
<Files .htaccess>
    Order Deny,Allow
    Deny from all
</Files>

# wp-content/uploads 内の PHP 実行を禁止
# wp-content/uploads/.htaccess に設置
<IfModule mod_php.c>
    php_flag engine off
</IfModule>
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule \.php$ - [F]
</IfModule>

# xmlrpc.php・readme.html・license.txt へのアクセスを拒否
<FilesMatch "^(readme|license|wp-config-sample)\..*$">
    Order Deny,Allow
    Deny from all
</FilesMatch>
# Nginx: uploads ディレクトリの PHP 実行禁止
location ~* /(?:uploads|files)/.*\.php$ {
    deny all;
}

# wp-config.php へのアクセス拒否
location = /wp-config.php {
    deny all;
}

# .htaccess・.git などの隠しファイルを拒否
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

ステップ4:WordPressからのファイル編集を無効化する

// wp-config.php: 管理画面からのテーマ・プラグイン編集を無効化
// (パーミッション保護と組み合わせることで二重に保護)
define( 'DISALLOW_FILE_EDIT', true );

// プラグイン・テーマのインストール・更新を無効化
// (本番環境でデプロイフローを管理している場合)
define( 'DISALLOW_FILE_MODS', true );

// 自動更新をコアのマイナーアップデートのみに制限
define( 'AUTOMATIC_UPDATER_DISABLED', false );
add_filter( 'auto_update_plugin', '__return_false' );
add_filter( 'auto_update_theme',  '__return_false' );
add_filter( 'auto_update_core',   function( $update, $item ) {
    return $item->type === 'minor'; // マイナーのみ自動更新
}, 10, 2 );

ステップ5:パーミッションをWP-CLIで定期監視する

// WP-CLIカスタムコマンドでパーミッションを監査
if ( defined( 'WP_CLI' ) && WP_CLI ) {
    WP_CLI::add_command( 'security check-permissions', function(): void {
        $wp_root  = ABSPATH;
        $critical = [
            $wp_root . 'wp-config.php'       => [ 600, 640 ],
            $wp_root . '.htaccess'            => [ 644 ],
            $wp_root . 'wp-content/uploads'   => [ 755 ],
        ];

        $issues = 0;
        foreach ( $critical as $path => $allowed_perms ) {
            if ( ! file_exists( $path ) ) continue;

            $actual = (int) substr( sprintf( '%o', fileperms( $path ) ), -3 );
            if ( ! in_array( $actual, $allowed_perms, true ) ) {
                WP_CLI::warning( sprintf(
                    '%s: パーミッション %o (推奨: %s)',
                    $path,
                    $actual,
                    implode( ' または ', $allowed_perms )
                ) );
                $issues++;
            } else {
                WP_CLI::line( sprintf( '✓ %s: %o', $path, $actual ) );
            }
        }

        // uploads内のPHPファイルを検索
        $uploads_dir = WP_CONTENT_DIR . '/uploads';
        $php_files   = glob( $uploads_dir . '/**/*.php', GLOB_BRACE );
        if ( $php_files ) {
            WP_CLI::error( sprintf(
                'uploads に %d 個の PHP ファイルが存在します!マルウェアの可能性があります。',
                count( $php_files )
            ) );
            foreach ( $php_files as $file ) {
                WP_CLI::line( '  危険: ' . $file );
            }
            $issues += count( $php_files );
        }

        if ( $issues === 0 ) {
            WP_CLI::success( 'パーミッションに問題は見つかりませんでした' );
        } else {
            WP_CLI::warning( "{$issues} 件の問題が見つかりました" );
        }
    } );
}
# 実行
wp security check-permissions

# cronで毎日監視
0 6 * * * /usr/bin/wp --path=/var/www/html security check-permissions >> /var/log/wp-security.log 2>&1

注意事項

  • chmod 600 wp-config.phpに設定する場合、Webサーバーユーザー(www-data等)がオーナーである必要があります。異なるユーザーがオーナーの場合は640にしてグループで読めるようにしてください。
  • DISALLOW_FILE_MODS=trueはプラグイン・テーマの自動更新も止めます。セキュリティアップデートを手動で管理できる体制がある場合のみ設定してください。
  • WebサーバーがsuEXECphp-fpmでサイトごとに別ユーザーで実行している場合、パーミッション設定が異なります。共有ホスティングでは644/755が標準です。

まとめ

ファイルパーミッション設定は「ディレクトリ755・ファイル644・wp-config.php 600が基本→シェルスクリプトで一括修正→.htaccessでwp-config.phpとuploads内PHP実行を保護→DISALLOW_FILE_EDIT=trueで管理画面編集を無効化→WP-CLIカスタムコマンドで定期監査→cronで自動チェック」の流れで整備します。関連記事:WordPressのwp-config.phpを安全に設定する方法WordPressにセキュリティヘッダーを設定する方法

お気軽にご相談ください

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