
CVE-2024-11972 in Hunk Companion <1.9.0 allows unauthenticated attackers to exploit insecure REST API endpoints and install vulnerable plugins, risking RCE, SQLi, XSS, and backdoors.
CVE-2024-11972 は、Hunk Companion WordPress プラグインのバージョン 1.9.0 未満における深刻な脆弱性です。この脆弱性により、認証されていない攻撃者が適切に認可されていない REST API エンドポイントを悪用して、WordPress.org リポジトリからプラグイン(古いバージョンや既知の脆弱性があるものを含む)をインストールおよび有効化できるようになります。この脆弱性を悪用すると、リモートコード実行、SQL インジェクション、XSS、管理バックドアの作成など、深刻なセキュリティリスクが発生する可能性があります。
この脆弱性を悪用する一般的な例として、WP Query Console プラグインが挙げられます。この脆弱性を利用してインストールされると、プラグインは WordPress 内にコンソールインターフェースを提供し、ユーザーがサイトのデータベースに対して SQL クエリを実行できるようになります。これにより、データの盗難、バックドアの作成、データベース全体の侵害が可能になります。
必要な Python ライブラリ → argparse, requests, urljoin
options:
-h, --help show this help message and exit
-u URL, --url URL Base URL of the WordPress site (default: http://localhost/wordpress/).
-p PLUGIN, --plugin PLUGIN
Plugin name to install (default: classic-editor).
<WordPress の URL を入力> -p <プラグイン名を入力>脆弱なエンドポイント /wp-json/hc/v1/themehunk-import は、Daniel Rodriguez 氏が進行中の調査の一環としてアクセスログを分析した際に最初に特定されました。この情報を基に、インポートエンドポイントのソースコードを確認できます。
/import/core/class-installation.php ファイル内で、次の行が見られます:
204 | $temp_file = download_url('https://downloads.wordpress.org/plugin/'.$slug.'.zip');
HUNK_COMPANION_SITES_BUILDER_SETUP クラスは、WordPress プラグインとテーマのインストールおよび有効化を管理し、入力パラメーターに基づいてフリー版とプレミアム版の両方を処理します。プラグインやテーマがインストールされているか、または有効かを動的にチェックし、不足している場合は必要なファイルをダウンロードおよび解凍し、WordPress コア関数を使用してそれらを有効化します。
このハードコードされた機能により、プラグインは WordPress リポジトリから(削除されたり廃止されたものも含めて)任意のプラグインをダウンロードできるため、攻撃者は脆弱なプラグインを悪用する機会を得ることができます。
さらに詳しく調査するために、/import/app/app.php を確認してみましょう。
バージョン 1.8.0 | 1.8.7 | 1.9.0 で導入されたさまざまな修正を比較してみます。各バージョンで新たなセキュリティ層が追加されています:
register_rest_route( 'hc/v1', 'themehunk-import', array(
'methods' => 'POST',
'callback' => array( $this, 'tp_install' ),
'permission_callback' => '__return_true',
) );
permission_callback は常に true を返すため、任意のユーザー または認証されていないアクターが POST リクエストを使用してエンドポイントにアクセスできます。
Nonce 検証や認証プロセスが一切存在しないため、攻撃者は必要な権限をバイパスして、目的のプラグインを直接インストールできました。
バージョン 1.8.7 では、以前のバージョンに存在した問題を解決するためにいくつかのセキュリティ改善が導入されましたが、エンドポイント /hc/v1/themehunk-import および全体的な実装には依然として重大な欠陥があります:
public function register_routes() {
register_rest_route( 'hc/v1', 'themehunk-import', array(
'methods' => 'POST',
'callback' => array( $this, 'tp_install' ),
'permission_callback' => function () {
// Check if the user is logged in
if ( ! is_user_logged_in() ) {
return new WP_REST_Response( 'Unauthorized: User not logged in', 401 );
}
// Debug: Log the user role and capabilities to see what they have
$current_user = wp_get_current_user();
// error_log( 'Current user: ' . $current_user->user_login );
// error_log( 'User roles: ' . implode( ', ', $current_user->roles ) );
// error_log( 'User capabilities: ' . print_r( $current_user->allcaps, true ) );
// Ensure the user has the 'install_plugins' capability
if ( ! current_user_can( 'install_plugins' ) ) {
return new WP_REST_Response( 'Unauthorized: Insufficient capabilities', 401 );
}
// Get the nonce from the request header
$nonce = $request->get_header('X-WP-Nonce');
// Verify the nonce
if ( ! wp_verify_nonce( $nonce, 'hc_import_nonce' ) ) {
return new WP_REST_Response( 'Unauthorized: Invalid nonce', 401 );
}
return true; // Permission granted
このバージョンでは、ユーザーがログインしているかの確認 (is_user_logged_in()) や、適切な権限を持っているかの検証 (current_user_can('install_plugins')) が実装され、該当しない場合は 401 Unauthorized レスポンスを返しますが、根本的な問題は未解決のままです。
WordPress の permission_callback に関するコールバックロジックは、次のように評価されます:

つまり、正しいレスポンスは true、false、または WP_Error のいずれかでなければなりません。
問題は、返された WP_REST_Response がブール値でも WP_Error でもない点にあります。WordPress はこれを拒否 (false) やエラー (WP_Error) として解釈しないため、暗黙的に受け入れられ、認証されていないユーザーにアクセス権が付与される可能性があります。これにより、根本的な問題は解決されません。
バージョン 1.9.0 では問題が正常に解決され、脆弱性が悪用不可能になりました:
public function register_routes() {
register_rest_route( 'hc/v1', 'themehunk-import', array(
'methods' => 'POST',
'callback' => array( $this, 'tp_install' ),
'permission_callback' => function () {
// Check if the user is logged in
if ( ! is_user_logged_in() ) {
return false;
}
// Debug: Log the user role and capabilities to see what they have
$current_user = wp_get_current_user();
// error_log( 'Current user: ' . $current_user->user_login );
// error_log( 'User roles: ' . implode( ', ', $current_user->roles ) );
// error_log( 'User capabilities: ' . print_r( $current_user->allcaps, true ) );
// Ensure the user has the 'install_plugins' capability
if ( ! current_user_can( 'install_plugins' ) ) {
return false;
}
// Get the nonce from the request header
$nonce = $request->get_header('X-WP-Nonce');
// Verify the nonce
if ( ! wp_verify_nonce( $nonce, 'hc_import_nonce' ) ) {
return false;
}
return true; // Permission granted
このバージョンでは、ユーザーがログインしていないか適切な権限を持っていない場合に、正しい false 値が返されるようになっています。これにより、permission_callback は認証されていないアクセスを適切に拒否し、脆弱性の悪用が不可能になります。