オフェンシブセキュリティ部アプリケーションセキュリティ課の山崎です。
WordPressプラグインAdvanced Custom Fields(以下ACF)で発見した一連の脆弱性(CVE-2021-20865、CVE-2021-20866、CVE-2021-20867、CVE-2022-23183)について解説します。
ACF は編集画面をカスタマイズすることを可能にする WordPressプラグインで、ダウンロード数も 200 万以上と人気の高いプラグインの一つです。
本脆弱性はユーザが自身の権限を超えてデータベース内のデータへのアクセスや操作ができる脆弱性であり、特にサイトのユーザ登録が許可されていると第三者による悪用が可能です。
実際に本脆弱性によって非公開情報の奪取が可能となってしまっているサイトの存在も確認されているため、お使いの方はアップデートすることを推奨します。
●「wp_ajax_」フック
解説にあたり、ちょっとした前提についてお話します。
WordPress では、「wp_ajax_」フックや「wp_ajax_nopriv_」フックを追加することで Ajax経由で呼び出すことができる API を生やすことが可能です。https://codex.wordpress.org/AJAX_in_Plugins#Ajax_on_the_Viewer-Facing_Side
逆に言えば、ソースコードからこれらのフックを探すことで、Ajax経由で呼び出すことのできる関数を得ることができます。
例えば、WordPress本体には「wp_ajax_nopriv_generate_password」というランダムパスワードを生成するための関数が存在しますが、これは「/wp-admin/admin-ajax.php?action=generate-password」という URL から呼び出すことができます。https://github.com/WordPress/WordPress/blob/3a3cb930d6822023f1c8255924f8ba6f46817c5f/wp-admin/includes/ajax-actions.php#L4097

特に「wp_ajax_nopriv_」フックはログインしていないユーザからの呼び出しも許可されているため、外部の攻撃者にとっては有用です。
対して「wp_ajax_」フックを利用するには最低でも管理画面にログインしなければいけないため、攻撃者にとってハードルは高いと考えられます。
ただし、WordPress のユーザにもプロフィールを設定できるだけの「購読者」や記事の投稿だけが可能な「寄稿者」といったグループが存在し、第三者がコメントをするために「購読者」として自由にアカウント登録を許可しているサイトも存在します。
また、設定を誤ってユーザ登録が可能となっているサイトも稀に存在しますし、委託先の会社に必要最小限の権限でアカウントを発行するといったケースもあるでしょう。
一見して最もできることの少ない「購読者」ユーザであっても前述した「wp_ajax_」フックをを利用することができるため、この経路の攻撃にも注意が必要です。

●発見した脆弱性(CVE-2021-20866、CVE-2021-20867)
CVE-2021-20866、CVE-2021-20867 ではそれぞれ「wp_ajax_nopriv_acf/fields/user/query」「wp_ajax_acf/field_group/move_field」を呼び出すことで「購読者」ユーザが本来許可されていないデータの参照・更新が可能となっていました。
前者の API は「wp_ajax_nopriv_」フックですが、呼び出しにはログイン後にプラグインの発行する nonce値を手に入れる必要があるため、管理画面へのログインが必要です。
●発見した脆弱性(CVE-2021-20865、CVE-2022-23183)
CVE-2021-20865、CVE-2022-23183 は「wp_ajax_parse_media_shortcode」フック経由の脆弱性になります。
このフックは ACF由来のものではなく WordPress本体の提供するフックで、
[gallery id=”123″ size=”medium”]
のような記事に埋め込むショートコードを展開するものです。https://codex.wordpress.org/Shortcode_API
ショートコードは WordPressプラグインによって拡張することができ、ACF をインストールすると
[acf field=”field_name” post_id=”123″]
のようなショートコードが利用できるようになります。https://www.advancedcustomfields.com/resources/shortcode/
通常このショートコードは ACF上でユーザが定義したフィールドの値が得られるだけなのですが、以下のコードの通りショートコード中に指定された値を使って WordPress のオプションやメタデータを取得することが可能となっていました。
脆弱性の存在した ACF では関数「get_option」を通じて「foo_bar」形式のオプションが、関数「get_metadata」を通じてメタデータがといったように、ACFと関係のないデータベース上のデータも取得することが可能になっていました。

WordPress のオプションテーブル(wp_options)には様々な情報が格納されているのですが、例えばメールサーバのパスワードはオプション「mailserver_pass」として設定されているため、以下のショートコードから入手することができます。
[acf post_id=”mailserver” field=”pass”]

また、導入している他のプラグインによってはサイト全体のセキュリティに関わるような重要なトークンや鍵文字列がオプションテーブルに保管されている場合もあります。
メタデータに関しては以下のテーブルのデータが入手可能でした。
– wp_commentmeta
– wp_postmeta
– wp_termmeta
– wp_usermeta
例えば、以下のショートコードを展開するとユーザの IPアドレスを含むデータを得ることが可能でした。
[acf post_id=”user_1″ field=”community-events-location”]
ということで、本件は本来できることの少ない「購読者」ユーザがサイトの様々な情報を閲覧できてしまう脆弱性でした。
●最後に
WordPressプラグインで発見した脆弱性を紹介しました。
調査の過程で発見した本プラグイン以外の脆弱性についての解説も行う予定でしたが、未修正のためそれはまた別の機会にできればと思います。
これらの脆弱性は IPA 及び JVN を通じて報告され、ACF v5.12.1 では全て修正されています。
v5.12 以前の ACF をお使いの方はアップデートを推奨します。
また、サイト管理者の方はうっかり WordPress のユーザ登録を許可していないか、設定画面を確認してみてもいいかもしれません。