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).
<insert wordpress URL> -p <insert plugin name>存在漏洞的端点 /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 的回调逻辑是这样评估的:

问题在于返回的 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 正确拒绝未经授权的访问,使利用不再可行。