admin
2 weeks ago
cli
2 weeks ago
lib
1 month ago
captcha.php
2 weeks ago
cloudsecure-wp.php
6 days ago
common.php
4 months ago
config.php
2 years ago
disable-access-system-file.php
1 month ago
disable-author-query.php
2 weeks ago
disable-login.php
1 month ago
disable-restapi.php
2 weeks ago
disable-xmlrpc.php
1 year ago
htaccess.php
4 months ago
login-log.php
1 month ago
login-notification.php
3 months ago
protect-rest-batch.php
1 month ago
rename-login-page.php
4 months ago
restrict-admin-page.php
3 months ago
server-error-notification.php
3 months ago
two-factor-authentication.php
6 days ago
unify-messages.php
2 years ago
update-notice.php
9 months ago
waf-engine.php
6 days ago
waf.php
1 month ago
protect-rest-batch.php
65 lines
| 1 | <?php |
| 2 | |
| 3 | if ( ! defined( 'ABSPATH' ) ) { |
| 4 | exit; |
| 5 | } |
| 6 | |
| 7 | /** |
| 8 | * REST APIバッチエンドポイント(/batch/v1)への未認証アクセスを拒否する |
| 9 | * |
| 10 | * WordPressコアの脆弱性 wp2shell(CVE-2026-63030: バッチAPIのルート混同 + CVE-2026-60137: SQLi) |
| 11 | * による未認証RCEの緩和パッチ。設定を持たず、対応環境(非マルチサイト・競合プラグインなし)で |
| 12 | * プラグインが動作していれば常時有効。根本対策はWordPressコアの更新(6.8.6以上 / 6.9.5以上 / 7.0.2以上)。 |
| 13 | */ |
| 14 | class CloudSecureWP_Protect_REST_Batch extends CloudSecureWP_Common { |
| 15 | private const ERROR_CODE = 'protect_rest_batch'; |
| 16 | private const BATCH_ROUTE = '/batch/v1'; |
| 17 | |
| 18 | function __construct( array $info ) { |
| 19 | parent::__construct( $info ); |
| 20 | } |
| 21 | |
| 22 | /** |
| 23 | * rest_pre_dispatch |
| 24 | * バッチエンドポイントへの未認証アクセスを拒否する |
| 25 | */ |
| 26 | function rest_pre_dispatch( $result, $server, $request ) { |
| 27 | if ( is_wp_error( $result ) ) { |
| 28 | return $result; |
| 29 | } |
| 30 | |
| 31 | if ( ! $this->is_batch_route( $request->get_route() ) ) { |
| 32 | return $result; |
| 33 | } |
| 34 | |
| 35 | if ( is_user_logged_in() ) { |
| 36 | return $result; |
| 37 | } |
| 38 | |
| 39 | return new WP_Error( self::ERROR_CODE, 'REST APIバッチ機能への未認証アクセスは許可されていません', array( 'status' => rest_authorization_required_code() ) ); |
| 40 | } |
| 41 | |
| 42 | /** |
| 43 | * バッチエンドポイントのルート判定 |
| 44 | * |
| 45 | * コアのルートマッチングとのズレを埋めるため、判定前に3点の正規化を行う。 |
| 46 | * - strtolower: コアの正規表現は大文字小文字を区別しない(`@...@i`)ため、`/BATCH/V1` 等を取りこぼさない |
| 47 | * - trim: コアの正規表現は D 修飾子が無く、末尾の `$` が末尾改行の直前にもマッチする。このため |
| 48 | * `/batch/v1\n`(例: `?rest_route=/batch/v1%0a`)はコアではバッチにディスパッチされるが、 |
| 49 | * 厳格な文字列一致では取りこぼす。末尾の空白・制御文字を除去してこのバイパスを防ぐ |
| 50 | * - untrailingslashit: 末尾スラッシュ(`/batch/v1/`)を正規化する |
| 51 | * |
| 52 | * @param string $route |
| 53 | * @return bool |
| 54 | */ |
| 55 | public function is_batch_route( string $route ): bool { |
| 56 | $route = strtolower( untrailingslashit( trim( $route ) ) ); |
| 57 | |
| 58 | if ( self::BATCH_ROUTE === $route ) { |
| 59 | return true; |
| 60 | } |
| 61 | |
| 62 | return strpos( $route, self::BATCH_ROUTE . '/' ) === 0; |
| 63 | } |
| 64 | } |
| 65 |