WordPressの脆弱性で最も多いのは、テーマやプラグイン経由での脆弱性突破による権限昇格です。My WP Translateの脆弱性の例では、低権限ユーザーが管理者権限に昇格することで、不正な操作を許してしまうという致命的な脆弱性が発生しました。では発想を変えましょう。作られることを前提に考えてしまえば良いのです。肝心なのは、不正に忍び込まれたあとの事後対応です。仮に不正操作が成功したとしても、その後すぐに権限が購読者に降格させられたら目も当てられません(あくまで攻撃者にとって)。それを目指します。
明示的に許可したユーザー以外は強制降格させる
WordPress全般に多いのが、脆弱なテーマやプラグイン経由での権限上昇です。一度管理者・編集者権限を得てしまえば、あとはやりたい放題に改ざんされてしまいます。しかしながら、せっかく作ったアカウントが勝手に降格させられたらどうでしょうか?実はそれを狙っています。次のような攻撃が発生したと仮定します。
- 脆弱性を含むテーマまたはプラグイン経由で新規アカウントを作成
- 新規アカウントの権限を購読者から管理者に変更
- テーマファイル改ざん
- 任意コード注入や記事改ざん
この攻撃の重要なポイントは、2の権限昇格です。WordPressは購読者権限で行える操作は限られています。しかし、管理者権限を得た段階で致命的な状況となります。であれば、許可している管理者ユーザー以外が管理者に特権昇格した場合が致命的です。そこで作成したのが、明示したユーザー以外が特権奪取に成功しても強制的に権限を降格させるプラグインです。
権限昇格の発生経路
主な権限昇格の発生経路はこのようなものです。
- set_user_role
- REST API(rest_pre_dispatch)
- profile_update(プロフィール更新)
- user_register(新規ユーザー登録)
先ほども書いたように、権限昇格の殆どは脆弱なプラグインを導入した場合や、古いWordPressテーマを使ってる場合(あるいは、自作のGETを検証せず使うようなテーマ)で発生します。逆説的に考えれば、その経路を潰してしまえば良いのです(ホワイトリスト化)。
Admin Whitelist
このプラグインは、不正なユーザーの作成と権限昇格を感知した瞬間に全権限を購読者に降格させ、ログインすらできなくするものです。仮に権限昇格に成功したとしても権限降格が最優先でhookするうえ、ログインすらできなくなります。管理画面にすら入れません。悲惨です。(安全機能として操作中の管理者は必ずホワイトリストに追加されるようになっています。また、技量不足のためcheckedがすべてに入るようになっています。ホワイトリスト化不要のユーザーはチェック外してください。いずれ修正します)。
実例
今回、lowlevelというユーザーを作成します。権限は購読者とします。想定シチュエーションは、脆弱なプラグインを通じてユーザーを作成された状態で、権限はいきなり管理者ユーザーだったと仮定します。しかしこのユーザーは、ホワイトリストに追加されていません。試しにこのユーザーでログインを試行してみるとどうなるでしょうか。
画面ではわかりづらいのですが、ログインを試行してもログインができません。この理由は単純明快でして、基本的には明示的にホワイトリストに追加していない限り、管理者ユーザーであってもログインすることができない仕組みになっています。そのうえ、原則として最低権限の購読者まで落とされる仕組みになっています。
設定は2通りあり、既存維持と外部降格の二種類があります。ただ、エラーメッセージが出るか出ないかの違いだけです。既存維持の場合は「」エラーメッセージが表示され、ログインすることができません。個人的にはどうせ権限を落とすなら、そのままエラーすら出さない外部降格をお勧めします。
防げない攻撃
SQLインジェクションで強制的に管理者権限にさせられた上で、かつホワイトリストに追加されてしまった場合はどうしょうもありません。一応、接頭辞の変更機能を付けていますが、インジェクションが通る時点でサイトが乗っ取られているのと同じため、意味は大きくありません。また、最初はログインユーザーの権限昇格操作の禁止を明示的に盛り込んでいたのですが、データベースアクセスが増える=オーバーヘッドが高くなるため廃止しました。主目的は「脆弱性のあるテーマやプラグインでユーザーを追加された際、そのユーザーが権限昇格することでサイトを改ざんする」ことを防ぐことが目的のため、ログイン可能ユーザーの明確化および降格処理のみで十分と考えます(SQLインジェクション喰らったらどちらにしろすべて見られるので無意味です)。
絶対に組み合わせて使ってほしいプラグイン
このプラグイン単体で使うよりも組み合わせて使ってほしいです。admin-ajax.phpを経由した場合やREST API経由された場合も潰したいからです。
- admin-ajax-blocker 非ログインユーザーによるadmin-ajax.phpへのアクセスを禁止します
- api-write-blocker(WordPress.org) POST,PUT,PACHI,DELETEなどのREST APIへの操作をホワイトリスト化します
- auth-priv-guard 権限昇格の可能性を徹底的に潰すプラグインです(管理者・編集者未満の記事編集権を剥奪したうえで、内部的な権限昇格操作を剥奪します)
- media file limiter(WordPress.org) 元は投稿ファイルの容量を制限するプラグインでしたがプラグインやREST API経由での不正ファイルアップロードを禁止する機能を設けています
- REST API Shield and XML RPC Blocker(WordPress.org) REST APIのエンドポイントを潰します(users,postsなどへのアクセス制限とXMLRPCの無効化)
肝心のadmin-whitelistはこちら(GitHub)からダウンロードしてください。





